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.
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 basic types of data can be encrypted:
In general, Properties encryption is preferred for a few reasons:
Other types of data that can be encrypted are:
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:
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:
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:
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:
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.
[encryption] foo_team=P4ssphr4se bar_team=Pa55phra5e
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] lax_decryption = true
This causes a failed decrypt to produce a warning only, not an error.
This can be overridden by individual XML files by setting lax_decryption="false" on the top-level tag (or, vice-versa; if strict is the default an XML file can specify lax_decryption="true".
Note that you could, for instance, set lax decryption by default, and then disable it on individual files.
Bcfg2.Server.Encryption provides a number of convenience methods for handling encryption in Bcfg2. See Bcfg2 Data Encryption for more details.
The bcfg2-crypt CLI
Decrypt Cfg files
decrypt the given file, returning the plaintext data
encryptor class for Cfg files
Generic decryption/encryption interface base object
Get the filename where data should be written
write data to disk
Constant representing the decryption operation for M2Crypto.EVP.Cipher, which uses a simple integer. This makes our code more readable.
Exception raised when decryption fails.
decrypt the file, returning the encrypted data
Constant representing the encryption operation for M2Crypto.EVP.Cipher, which uses a simple integer. This makes our code more readable.
Exception raised when encryption fails.
encrypt the file, returning the encrypted data
Default initialization vector. For best security, you should use a unique IV for each message. ssl_encrypt() does this in an automated fashion.
Exception raised when there’s a problem determining the passphrase to encrypt or decrypt with
Mixin to provide some common methods for Properties crypto
decryptor class for Properties files
encryptor class for Properties files
Convenience method to decrypt the given encrypted string by trying the given passphrases or all passphrases sequentially until one is found that works.
string - The decrypted data
M2Crypto.EVP.EVPError, if the data cannot be decrypted
Make a best guess if the value is encrypted or not. This just checks to see if val is a base64-encoded string whose content starts with “Salted__”, so it may have (rare) false positives. It will not have false negatives.
Render an XML element for error output. This prefixes the line number and removes children for nicer display.
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).
string - The decrypted data
Encrypt data in a format that is openssl compatible.
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().
string - The decrypted data
Encrypt a string with a key. For a higher-level encryption interface, see ssl_encrypt().
string - The decrypted data