Interactive key exchange with CFEngine

Here at Normation, we use CFEngine 3 extensively for configuration management across Linux and Windows servers.

CFEngine 3 is a very secure tool, that relies on keys to identify hosts and authorize connections. To set up a secure CFEngine infrastructure, you ought to exchange keys between hosts (note that if you don’t have confidential data on your promises, you can skip the security offered by the public key system).

Key exchange

The client-server communication is based on keys (very much like ssl). Each node must have a copy of the other public keys, obtained either via a remote copy (with scp), by trusting keys automatically, or using the bootstrap system introduced in Cfengine 3.2.0 (that would still require the server to accept automatically keys).

If you don’t want to accept keys based on automatic trust, you need to manually exchange them to set up the system. This article will show you how to do this using the cf-runagent tool, by connecting to each host from the main CFEngine server.

Assume a server with the following ip : 192.168.56.150
Assume a client with the following ip : 192.168.56.152

Client side

The initial promises on the client will need to configure the cf-serverd to run on it, and try to fetch its real promises from the policy server :

Note that the client trusts keys from the server

Server side

On the server, you’d have the following promise for the server component, authorizing hosts to connect, but not trusting their keys

Note: only the server itself is accepted on trust, hosts from the subnetwork 192.168.56.* can connect but their keys are not automatically trusted, and their DNS name is not deemed as reliable.

First execution (without prior key exchange)

If the agent on the client tries to connect to the server, without previous key exchange, you’ll have the following output on the server :

To relieve the burden of copying keys with scp, or the risk of trusking keys of every hosts, you can do a manual key exchange, from the server, using the cf-runagent interactive mode

Interactive key exchange

The interactive key exchange will happen from the server to the client. It will ask for the user to trust the key, and execute the remote promises of the client (in this case, the initial promises fetch the real promises from the server)

Here we accepted the key of 192.168.56.152 on the server, and the client could connect to download its new promises, and then apply them

Note: To prevent any risks, the new promises should not have 192.168.56.150 in the trustkeyfrom

Note 2: Since the version 3.2.0, if you are willing to automatically accept keys from the clients on the servers, you don’t need to copy any promises on the client, the bootstrap procedure from the Nova edition has been backported in the community edition; and it uses its own embedded promises