New in version 1.3.0.
Bcfg2 supports encrypting some data on the disk, which can help protect sensitive data from other people who need access to the Bcfg2 repository but are perhaps not authorized to see all data. It supports multiple passphrases, which can be used to enforce separations between teams, environments, etc. Use of the encryption feature requires M2Crypto 0.18 or newer.
Note
This feature is not intended to secure the files against a malicious attacker who has gained access to your Bcfg2 server, as the encryption passphrases are held in plaintext in bcfg2.conf. This is only intended to make it easier to use a single Bcfg2 repository with multiple admins who should not necessarily have access to each other’s sensitive data.
Two types of data can be encrypted:
In general, Properties encryption is preferred for a few reasons:
Encrypting and decrypting Cfg and Properties files can be done with the bcfg2-crypt tool, which mostly tries to do the right thing. I.e., it encrypts plaintext files, decrypts encrypted files, and automatically discovers if a file is Cfg or Properties. Its usage is thus generally very simple, e.g.:
bcfg2-crypt foo.conf
bcfg2-crypt foo.xml
Since the behavior of bcfg2-crypt varies significantly depending on whether you are dealing with a Cfg or Properties files, these are documented separately below. It’s also well worthwhile to familiarize yourself with the man page for bcfg2-crypt.
To encrypt a Cfg file, you can simply run:
bcfg2-crypt foo.conf
This will write the encrypted data to foo.conf.crypt. Once you are satisfied that the file has been encrypted as you wish, you can remove the plaintext version, or you can use the --remove flag of bcfg2-crypt.
To decrypt a file, simply run bcfg2-crypt again:
bcfg2-crypt foo.conf.crypt
On Cfg files, bcfg2-crypt is more-or-less equivalent to the following commands (encryption and decryption, respectively):
openssl enc -aes-256-cbc -k <passphrase> -in foo.conf \
-out foo.conf.crypt -a
openssl enc -d -aes-256-cbc -k <passphrase> -in foo.conf.crypt \
-out foo.conf -a
Those commands can be used in lieu of bcfg2-crypt if you hate convenience.
To encrypt or decrypt a properties file, simply run:
bcfg2-crypt foo.xml
If the top-level tag of a Properties file is not <Properties>, then you need to use the --properties flag to bcfg2-crypt:
bcfg2-crypt --properties foo.xml
The first time you run bcfg2-crypt on a Properties file, it will encrypt all character data of all elements. Additionally, it will add encrypted="<key name>" to each element that has encrypted character data. It also adds encryption="true" to the top-level <Properties> tag as a flag to the server that it should try to decrypt the data in that file. (If you are using Properties schemas, you will need to make sure to add support for these attributes.) On subsequent runs, only those elements flagged with encrypted="*" are encrypted or decrypted.
To decrypt a Properties file, simply re-run bcfg2-crypt:
bcfg2-crypt foo.xml
This decrypts the encrypted elements, but it does not remove the encrypted attribute; this way, you can decrypt a Properties file, modify the contents, and then simply re-run bcfg2-crypt to encrypt it again. If you added elements that you also want to be encrypted, you can either add the encrypted attribute to them manually, or run:
bcfg2-crypt --xpath '*' foo.xml
You can also use the --xpath option to specify more restrictive XPath expressions to only encrypt a subset of elements, or to encrypt different elements with different passphrases. Alternatively, you can manally set the encrypted attribute on various elements and bcfg2-crypt will automatically do the right thing. You can also run bcfg2-crypt in interactive mode to interactively select which attributes should be encrypted:
bcfg2-crypt -I foo.xml
If you want to use different passphrases within a single Properties file, you must manually set the encrypted attribute.
To configure encryption, add a [encryption] section to bcfg2.conf with any number of name-passphrase pairs.
For instance:
[encryption]
foo_team=P4ssphr4se
bar_team=Pa55phra5e
Note
The name of a passphrase cannot be algorithm or decrypt, which are reserved for other configuration options.
This would define two separate encryption passphrases, presumably for use by two separate teams. The passphrase names are completely arbitrary.
Note that this does entail a chicken-and-egg problem. In order for the Bcfg2 server to be able to decrypt encrypted files, the passphrases must exist in bcfg2.conf in plaintext; but, if you’re encrypting data, presumably you don’t want to include those plaintext passphrases in your Bcfg2 repository, so you’ll want to encrypt bcfg2.conf. The best way to solve this is:
The first (manual) step breaks the mutual dependency.
By default, Bcfg2 uses the AES-256-CBC cipher algorithm. If you wish to change this, you can set the algorithm option in the [encryption] section of bcfg2.conf:
[encryption]
algorithm = bf_cbc
The value of algorithm must be a valid OpenSSL cipher algorithm according the naming model of the Python M2Crypto module. To get a list of valid algorithms, you can run:
openssl list-cipher-algorithms | grep -v ' => ' | \
tr 'A-Z-' 'a-z_' | sort -u
By default, Bcfg2 expects to be able to decrypt every encrypted datum. Depending on how encryption is implemented at your site, though, that may not be possible. (For instance, if you use encryption to protect data for your production environment from your staging Bcfg2 server, then you would not expect the staging server to be able to decrypt everything.) In this case, you want to enable lax decryption in the [encryption] section of bcfg2.conf:
[encryption]
decrypt = lax
This causes a failed decrypt to produce a warning only, not an error.
This can be overridden by individual XML files by setting decrypt="strict" on the top-level tag (or, vice-versa; if strict is the default an XML file can specify decrypt="lax".
Bcfg2.Encryption provides a number of convenience methods for handling encryption in Bcfg2. See Bcfg2 Data Encryption for more details.
Default cipher algorithm. To get a full list of valid algorithms, you can run:
openssl list-cipher-algorithms | grep -v ' => ' | \
tr 'A-Z-' 'a-z_' | sort -u
The config option used to store the algorithm
The config option used to store the decryption strictness
The config file section encryption options and passphrases are stored in
Constant representing the decryption operation for M2Crypto.EVP.Cipher, which uses a simple integer. This makes our code more readable.
Constant representing the encryption operation for M2Crypto.EVP.Cipher, which uses a simple integer. This makes our code more readable.
Default initialization vector. For best security, you should use a unique IV for each message. ssl_encrypt() does this in an automated fashion.
Convenience method to decrypt the given encrypted string by trying the given passphrases or all passphrases (as returned by get_passphrases()) sequentially until one is found that works.
Either passphrases or setup must be provided.
Parameters: | |
---|---|
Returns: | string - The decrypted data |
Raises : | M2Crypto.EVP.EVPError, if the data cannot be decrypted |
Get the cipher algorithm from the config file. This is used in case someone uses the OpenSSL algorithm name (e.g., “AES-256-CBC”) instead of the M2Crypto name (e.g., “aes_256_cbc”), and to handle errors in a sensible way and deduplicate this code.
Parameters: | setup (Bcfg2.Options.OptionParser) – The Bcfg2 option set to extract passphrases from |
---|---|
Returns: | dict - a dict of <passphrase name>: <passphrase> |
Get all candidate encryption passphrases from the config file.
Parameters: | setup (Bcfg2.Options.OptionParser) – The Bcfg2 option set to extract passphrases from |
---|---|
Returns: | dict - a dict of <passphrase name>: <passphrase> |
Decrypt openssl-encrypted data. This can decrypt data encrypted by ssl_encrypt(), or openssl enc. It performs a base64 decode first if the data is base64 encoded, and automatically determines the salt and initialization vector (both of which are embedded in the encrypted data).
Parameters: | |
---|---|
Returns: | string - The decrypted data |
Encrypt data in a format that is openssl compatible.
Parameters: | |
---|---|
Returns: | string - The base64-encoded, salted, encrypted string. The string includes a trailing newline to make it fully compatible with openssl command-line tools. |
Decrypt a string with a key. For a higher-level decryption interface, see ssl_decrypt().
Parameters: | |
---|---|
Returns: | string - The decrypted data |
Encrypt a string with a key. For a higher-level encryption interface, see ssl_encrypt().
Parameters: | |
---|---|
Returns: | string - The decrypted data |