Is 5 minutes of drift too long? Winter is coming, and so is CFEngine support for dealing with immutable files.

CFEngine has always been a powerful tool for enforcing configuration and preventing drift. It’s the very essence of its mission to ensure the state of a system remains in line with its policy.
For years, that periodic enforcement with the speed and frequency of execution has been the core of CFEngine’s value. But what if you need to add another layer of protection? What if you want to make files on a system even more resistant to change, whether from a well-meaning administrator, an errant process, or even a malicious actor but not necessarily hamper CFEngine?
In this episode Nick showed off support for the immutable bit coming later this year in 3.27.0. While the new fsattrs
body could eventually support additional file system attributes the immutable bit is the first target.
At the kernel level, the immutable bit is an extended file attribute (i) that, when set on a file, prevents any modification, including deletion, renaming, or changes to permissions, even by the root user. The only way to modify the file is to first remove the immutable bit using the chattr
command (chattr -i filename
). Previously, if a CFEngine promise attempted to manage an immutable file, it would simply fail and report a promise not kept, as it lacked the ability to temporarily remove this bit.
The new fsattrs
body changes this dynamic. CFEngine can now actively manage this bit as part of a files promise transparently adding and removing the bit as necessary automatically when needed to facilitate change.
How CFEngine interacts with files based on the immutable bit setting in a promise:

- When a promise has an
fsattrs
body attached which containsimmutable => "true"
: CFEngine will ensure that the file is in an immutable state at the conclusion of the promise actuation. If the file needs to be modified for instance, if its content, permissions, or ownership needs to be updated CFEngine will transparently and temporarily remove the immutable bit, make the required changes, and then re-apply the immutable bit. This allows a single CFEngine promise to manage both the content and the immutability of a file without causing a promise failure. - When a promise has an
fsattrs
body attached which containsimmutable => "false"
: CFEngine will ensure that the file is in a mutable state. If it encounters a file that has the immutable bit set, it will remove the bit, leaving the file in a state that can be freely modified by other processes or administrators with proper permission. - When a promise does not contain a body
fsattrs
or ifimmutable
is not set in an attachedfsattrs
body: CFEngine will revert to its legacy behavior. If it attempts to modify a file that has the immutable bit set, the operation will fail with a “permission denied” error, and the promise will be reported as not kept.
There was discussion about the benefits of this functionality:
- Should CFEngine be able to do this?
- Some people use reporting about the presence of files with the immutable bit and presnece or absence of promises not kept. These reports help operators determine what might be the cause of an issue. In this context, CFEngine transparently handling and modifying immutable files would be undesirable.
- Examples of files on which people consider that setting the immutable bit could be useful include
/etc/resolv.conf
, andssh_known_hosts
. If you have more thoughts and use cases please share them with the team. - Managed Service Providers (MSPs) were thought to be an area that might make more use of functionality like this.
Video
The video recording is available on YouTube:
At the end of every webinar, we stop the recording for a nice and relaxed, off-the-record chat with attendees. Join the next webinar to not miss this discussion.
This time discussion included:
- Advice to use the immutable bit as a warning signal to identify policy gaps and correlate them with promise failures.
- Commiserating about the struggle in managing complex permissions and, as a result, often disables SELinux.
- The importance of being able to track why a file was changed or flagged, highlighting the potential for embedding context via extended file attributes.
- Desire for new CFEngine functionality regarding SELinux.
Links
- Connect w/ Cody, Craig, Herman, or Nick
- All Episodes