CFEngine 3.16 – Compliance

Posted by:

25 Jun 2020

Today we announce the newest additions to CFEngine. CFEngine 3.16 brings several improvements, bug fixes, and new features. The theme for this release has been compliance, and it notably includes a new category of reports for proving compliance to regulation and other compliance frameworks in high level, easy to read reports.

If you are interested to learn more about CFEngine, schedule training, or hear about pricing options, feel free to reach out to us!

What’s new

Compliance reports (Beta)

Compliance reports allow you to implement internal or regulatory frameworks as a list of checks which have to pass on all or a subset of your hosts. The system is very flexible, allowing you to implement checks using Inventory values, software updates, or even custom SQL queries. Once the report is completed, the results can be exported to PDF, or scheduled to run at a fixed interval, for example every week. Different compliance reports can be set up for various stakeholders in your organization, and automated e-mails with PDFs can bring this valuable information to people/departments which don’t use Mission Portal directly. This feature is still in beta, and a lot of the UI will change, but we are excited to show it to you and start getting some feedback on it, so it will be in a great shape for the next LTS release.

Compliance report (beta)

Secret Encryption

A new tool has been introduced, cf-secret, which allows you to encrypt files for specific hosts in your infrastructure.
It is open-source, available in both community and enterprise packages, and can be used from policy or as a stand-alone tool.

Read more about cf-secret here.

Detailed host and license counts

Mission Portal now gives you a detailed overview of your hosts, including the license count, number of recently deleted hosts, as well as the total number of hosts before RBAC filtering is applied. This should clear up some confusion in large infrastructures, especially when you are approaching the license count, and if you decommission hosts frequently. (Unfiltered host count is a separate control in our Role Based Access Control (RBAC) system, so you can grant or remove access to it for any user/role).

Detailed breakdown of license information and host counts

New version macros

From CFEngine 3.16 and onward, you can more easily target specific CFEngine versions within the policy language. Previously, you could use the minimum_version macro to avoid using newer syntax and features on older versions that don’t support it. However, there was no obvious approach to where you would put the alternative (the policy which you want to run on older versions only). For this reason and to allow greater flexibility to policy writers, we have introduced a few new macros:

  • maximum_version
  • else
  • at_version
  • between_versions
  • before_version
  • after_version

Read more about all these macros in the documentation.

New functions

CFEngine 3.16.0 introduces 9 new functions. To complement the version macros, which function at a parsing level, we also now have functions for making decisions based on the version of the agent from the policy.

A new utility function to strip leading and trailing whitespace was added.

And two new data validation functions were added for making decisions based on data validity.

New files promise type attribute

The new content attribute for files type promises make it more clear and concise to promise the full content of a file.

bundle agent example_file_content
# @brief Example showing files content
        string => "Hello from var!";

        create => "true",
        content => "Hello from string!";

        create => "true",
        content => "$(my_content)";

        printfile => cat( $(this.promiser) );
        printfile => cat( $(this.promiser) );

body printfile cat(file)
# @brief Report the contents of a file
# @param file The full path of the file to report
        file_to_print => "$(file)";
        number_of_lines => "inf";

bundle agent __main__
  methods: "example_file_content";

Here we can see the results of executing the example above.

# cf-agent --no-lock --file /tmp/
R: /tmp/hello_string
R: Hello from string!
R: /tmp/hello_var
R: Hello from var!

You can find the documentation about the content attribute here.


We have made a lot of smaller improvements, dependency updates, and bug fixes which would not fit into a single blog post. Some of these are brand new to CFEngine 3.16, while some we were also included in the recent 3.12.5 and 3.15.2 releases. You can read all the details in our changelogs:


We are always looking for new contributions to CFEngine! Are you unsure how to get started? Please check out our contributing guide in addition to the following suggestions.

Ole Herman Elgesem

CFEngine Product Manager