CFEngine 2 network communication is insecure by today’s standards.
CFEngine 2
- CVE-2016-6329:
CFEngine 2 uses Blowfish cipher (1993) which today is considered:
- Weak
- Deprecated
- Subject to key recovery attack
- No security fixes since 2008.
- Protocol communications not encrypted; only data transfer (which facilitates attack).
- Encryption is off by default.
CFEngine 3
- All communication is encrypted
- Uses TLS 1.3 (current state of the art)
- Up to date, maintained, secure from the software vendor
- Full Enterprise support, with SLA.
Solution
CFEngine 3 was intentionally designed so that you can install it side by side with 2, so you have time to migrate your policies from 2 to 3.
If you are running a large CFEngine 2 installation, you can increase the security of your site by installing CFEngine 3 side by side with CFEngine 2 and using CFEngine 3 for network transport.
The following demonstration of running 2 and 3 side by side was done in the CFEngine Vagrant sandbox environment, which provides two CentOS 6.5 VMs, called “hub” and “host001”, to represent a CFEngine policy distribution server and a managed host.
The rest of this write-up documents my steps for building and installing CFEngine 2 and configuring CFEngine 3 to run the version 2 agent alongside the version 3 agent.
The idea being, once you’ve got 3 running side by side with 2, you can take your time to transition your CFEngine policy code base from 2 to 3.
Procedure
Get the latest CFEngine 2 source code (2008).
Install build tool prerequisites:
yum install -y byacc flex
Install library prerequisites:
yum install -y db4-devel openssl-devel
Build and install CFE2:
./configure --prefix=/opt/cfengine-2.2.9
make install
Create a stub CFEngine 2 file, /var/cfengine/masterfiles/cfagent.conf
on the Hub.
control:
actionsequence = ( shellcommands )
shellcommands:
any::
'/bin/echo $(version) agent says "Hello world"'
Make sure it works:
[root@hub ~]# /opt/cfengine-2.2.9/sbin/cfagent
cfengine:hub:/bin/echo 2.2.9: 2.2.9 agent says Hello world
[root@hub ~]#
Add a comparable promise to the CFE3 code base, /var/cfengine/masterfiles/services/main.cf
:
###############################################################################
#
# bundle agent main
# - User/Site policy entry
#
###############################################################################
bundle agent main
# User Defined Service Catalogue
{
commands:
any::
"/bin/echo $(sys.cf_version) agent says 'Hello world'";
}
Update CFE3 controls to run CFE2 agent after CFE3 agent:
[root@hub masterfiles]# git diff --color=never controls/cf_execd.cf
diff --git a/controls/cf_execd.cf b/controls/cf_execd.cf
index 74e5c4b..6d46080 100644
--- a/controls/cf_execd.cf
+++ b/controls/cf_execd.cf
@@ -51,6 +51,6 @@ body executor control
exec_command => "$(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated -f \"$(sys.update_policy_path)\" & $(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated";
!windows::
- exec_command => "$(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated -f \"$(sys.update_policy_path)\" ; $(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated";
+ exec_command => "$(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated -f \"$(sys.update_policy_path)\" ; $(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated ; /opt/cfengine-2.2.9/sbin/cfagent";
}
[root@hub masterfiles]#
Allow some time for the host to pick up the changes from the hub (it should happen within 5-10 minutes).
Observe the host (host001) is now running CFEngine 3 and 2 agents:
/var/cfengine/outputs/previous
:
[root@host001 outputs]# cat previous
notice: Q: ".../bin/echo 3.15.": 3.15.0 agent says Hello world
cfengine:host001:/bin/echo 2.2.9: 2.2.9 agent says Hello world
[root@host001 outputs]#
The first line of output is from CFEngine 3, and the second from CFEngine 2.
Credits
I want to acknowledge the team at Nortern.tech, especially Nils Christian Flinder Roscher-Nielsen and Nick Anderson, who helped with this research and reviewed this article.