CFEngine build modules are great for quickly integrating 3rd party policy into your policy set. Module input (not to be confused with inputs in body common control or body file control which are the list of policy files to load) allows you to define values that apply for a particular module as it’s integrated into your policy set.
Let’s take a look at a case of extending a module to support input.
Nick and Cody celebrate Thanksgiving with a holiday special reviewing some policy related questions Nick recently received.
Get the list of all network interfaces present default:sys.interfaces only contains configured interfaces, not configured interfaces.
default:sys.interfaces_data at least for Linux systems, this variable contains much more information.
/tmp/getindices-sys.interfaces_data.cf bundle agent __main__ { vars: "sys_interfaces_data_keys" slist => getindices( "sys.interfaces_data" ); reports: "$(sys_interfaces_data_keys)"; } command cf-agent --no-lock --log-level info --file /tmp/getindices-sys.interfaces_data.cf output R: lo R: enx0892048803e7 R: enx5cff35c6864b R: wlp0s20f3 R: virbr0 R: docker0 R: br-a7d465b9949b R: vboxnet0 R: tun0 cf-promises can be very useful for reviewing the first order variables that are defined using the --show-vars option.
Ever need to make a decision based on the version of something? The version_compare() function might be useful for you.1
Over time, software changes and features are added and removed. Sometimes, we need to make a decision based on versions. For example, the Include directive in ssh_config was introduced in OpenSSH 7.3.2 Let’s take a look at how we could possibly use it.
This example illustrates the basic use of version_compare():
Looking for a tool to help you format your CFEngine policy? Have you heard of cffmt?
You might recall that we had a chat with the author, Miek Gieben in The agent is in - Episode 24.1 In case you missed it, cffmt is a command line tool for formatting CFEngine policy files, like gofmt for .cf files.2 Let’s take a look.
Consistent formatting can really ease reading of policy, but sometimes editors are configured differently and you can end up with inconsistently formatted policy. For example, here is a contrived policy file with some irregular formatting:
Have you seen the new Groups feature in CFEngine Enterprise Mission Portal?
It was first released in 3.23.0 and it’s part of the 3.24 LTS series released earlier this year, let’s check it out.
Groups in Mission Portal can be based on any host reported data. They can be dynamic (hosts can come and go from a group) or they can be static and tied to specific hosts by hostname, mac address, IP or CFEngine’s public key. By default groups are not shared with other users and they can be used any place where you would use a filter constraining the scope of hosts based on various conditions related to the hosts reported data. If a group is shared it can have data associated with it.
Out of the box, Mission Portal uses port 80 for HTTP and 443 for HTTPS traffic. These ports are widely used for web services, which makes the initial setup straightforward. However, there are several reasons why you might want to change these default ports:
Port conflicts: other services on your system might already be using ports 80 or 443. Security concerns: well-known ports are common targets for attacks. Compliance requirements: your organization’s policies might restrict the use of standard web ports. Changing default ports Note: The custom port configuration feature described below is available in CFEngine Enterprise master (nigthlies), 3.25.0 (to be released this winter) or later.
Over three years ago we introduced git and systemd custom propmise types.
While these are quite functional I recently needed to manage a git repository that was private and so needed a way to authenticate to a git server, in this case gitlab.
Gitlab has project access tokens but we didn’t directly support any sort of authentication attributes on the promise type.
I ran across git credential as a way to provide authentication and thought it was a good fit.
Did you know CFEngine can self-organize hosts into different groups?
Say you have a few hosts that you want to reboot once a month. You don’t care when, but you want the hosts to self-organize and pick a date. The select_class attribute for classes type promises might be what you’re looking for. Let’s take a look.
We’ll keep things simple, so we want each host to self-select a day of the month (1-28).
The prolific contributor and CFEngine Champion Bas Van der Vlies joins the team for a chat about his history and experience with CFEngine dating back to version 1.0.3.
For this special Halloween edition Bas joined Cody, Craig and Nick to reflect on his journey getting into information technology beginning with chemical engineering through joining the Dutch National Compute Center where he was managing many SGI and AIX machines and where he discovered CFEngine and how it could help him manage all the machines. Bas went on to highlight some of his favorite features and discussed how CFEngine has evolved over the years. His advice for both new and old users is to check out some of the newer tooling like cf-remote and cfbs for the CFEngine Build system as they can dramatically help to simplify policy maintenance.
What’s the difference between an associative array and a data container in CFEngine?
CFEngine has two ways in which structured data can be used, associative arrays (sometimes called classic arrays) and data containers. Let’s take a look at a simple data structure.
Here we have two data structures, a_email an associative array and d_email a data container. The policy emits the JSON representation of each.
bundle agent __main__ { vars: "a_email[john@example.com][FirstName]" string => "John"; "a_email[john@example.com][LastName]" string => "Doe"; "d_email" data => '{ "john@example.com": { "FirstName": "John", "LastName": "Doe" } }'; reports: "JSON representation of a_email (associateve array):$(const.n)$(with)" with => storejson( a_email ); "JSON representation of d_email (data container):$(const.n)$(with)" with => storejson( d_email ); } Looking at the output, they are identical: