Details
-
Type:
Task
-
Status: Done
-
Priority:
Medium
-
Resolution: Fixed
-
Affects Version/s: None
-
Component/s: cf-secret
-
Labels:None
-
Story Points:13
-
Epic Link:
Description
Jon Henrik Bjørnstad has kindly re-licensed cf-keycrypt so that we can vendor it.
https://github.com/cfengineers-net/cf-keycrypt/pull/5
https://github.com/cfengineers-net/cf-keycrypt/commit/c89ea91b07a69e4ec2f70fdbd5fc07d791b461a8
There 2 main ways to use cf-keycrypt.
1. Encrypt for a particular node
On policy hub:
hub# cf-keycrypt -H 192.168.1.20 -i /path/to/plain_input_file -o /path/to/encrypted_output_file
-H will look in lastseen database to find the public key it has recorded for a particular ip address.
This file can then be made accessible on the policy hub and copied over to the client in question. You could even
put it in masterfiles if you want.
On the client to decrypt:
client# cf-keycrypt -d /var/cfengine/ppkeys/localhost.pub -i /path/to/encrypted_input_file -o /path/to/plain_output_file
Only the client with the corresponding private key will be able to decrypt.
2. Encrypt for a particular group of nodes
Create a public/private keypair for the group on the policy hub:
hub# cf-key -f /path/to/keyfiles/securitygroup1
You will then have securitygroup1.priv and securitygroup1.pub under /path/to/keyfiles. You can then distribute the private key to all nodes of part of that group, potentially by using encryption per node as described above. Or you could use admit rules in cf-serverd on the policy hub.
You can now use cf-keycrypt to encrypt for the group
On policy hub:
hub# cf-keycrypt -e /path/to/keyfiles/securitygroup1.pub -i /path/to/plain_input_file -o /path/to/encrypted_output_file
On the hosts holding the private key:
client# cf-keycrypt -d /path/to/keyfiles/securitygroup1.pub -i /path/to/encrypted_input_file -o /path/to/plain_output_file
The following two examples is mainly for use with commands promises in CFEngine as follows:
commands:
"/var/cfengine/libexec/cf-keycrypt -e /path/to/keyfiles/securitygroup1.pub -i /path/to/plain_input_file -o /path/to/encrypted_output_file";
But you could potentially also use it to read encrypted data into memory as the following example shows.
hub# cat /tmp/data.json { "key1": "value1" }
hub# cf-keycrypt -H 192.168.1.20 -i /tmp/data.json -o /tmp/data.json.crypt
Then you could use it directly in policy like this:
cf-keycrypt.cf:
body common control { bundlesequence => { "cf_keycrypt" }; } bundle agent cf_keycrypt { vars: "secret_data" data => parsejson( execresult( "$(sys.workdir)/libexec/cf-keycrypt -d $(sys.workdir)/ppkeys/localhost.priv -i /tmp/data.json.crypt -o -", "noshell" ) ); reports: cfengine_3:: "$(secret_data[key1])"; }
client# cf-agent -K -f cf-keycrypt.cf R: value1
How to test
Testing encryption/decryption with a specific key
1) Generate a key with cf-key
cf-key /tmp/mykey
2) Encrypt a file using the key
cf-keycrypt -e /tmp/mykey.pub -i /path/to/plain -o /path/to/encrypted
3) Decrypt the file
cf-keycrypt -d /tmp/mykey.pub -i /path/to/encrypted -o /path/to/newplain
4) Compare the file before and after encryption
diff /path/to/plain /path/to/newplain
Testing encryption based on a hosts IP
For this test IP should be derived from the localhost.
1) Encrypt a file using the key
cf-keycrypt -H IP -i /path/to/plain -o /path/to/encrypted
2) Decrypt the file
cf-keycrypt -d /tmp/mykey.pub -i /path/to/encrypted -o /path/to/newplain
3) Compare the file before and after encryption
diff /path/to/plain /path/to/newplain
Testing encryption based on a hosts name
For this test HOSTANME should be derived from the localhost.
1) Encrypt a file using the key
cf-keycrypt -H HOSTNAME -i /path/to/plain -o /path/to/encrypted
2) Decrypt the file
cf-keycrypt -d /tmp/mykey.pub -i /path/to/encrypted -o /path/to/newplain
3) Compare the file before and after encryption
diff /path/to/plain /path/to/newplain
Attachments
Issue Links
- blocks
-
CFE-3271 Add support for multi-host/multi-key encryption to cf-keycrypt
-
- Done
-