Secret#
NAME#
Kernel::System::Crypt::Secret - encrypt/decrypt secrets stored in Kernel/Config.pm
DESCRIPTION#
Some credentials (e.g. DatabasePw, the various LDAP SearchUserPwsettings) must be read before SysConfig is available and therefore have to be
stored literally in Kernel/Config.pm. This module allows such values to be
stored as real, key-based ciphertext instead of plain text.
An encrypted value looks like this and can be pasted directly into Kernel/Config.pm in place of the plain text value:
{AES256:<base64 IV>:<base64 ciphertext and authentication tag>}
Values are encrypted with AES-256 in GCM mode, so a wrong key or a manipulated value is always detected by Decrypt().
Use bin/znuny.Console.pl Maint::Secret::Encrypt to create one.
Values that are not wrapped in {AES256:...} are returned unchanged by
Decrypt(), so this can safely be called on any config value, encrypted or
not.
Encryption key#
The encryption key is derived from a passphrase which is deliberately NOT stored in Kernel/Config.pm (otherwise nothing would be gained). It is read from, in order of precedence:
The
ZNUNY_CONFIG_SECRET_KEYenvironment variable.
A file whose path is configured via
$Self->{ConfigSecretKeyFile}in Kernel/Config.pm. This file should live outside the web root, be owned
by the webserver user and have permissions 0600.
Use bin/znuny.Console.pl Maint::Secret::KeyGenerate to create a new
random passphrase.
Threat model#
This protects secrets at rest in Kernel/Config.pm (e.g. against being accidentally committed to version control, included in backups, or read by someone who can view the file but not the key). It does NOT protect against an attacker who can read arbitrary files as the webserver user, since that user needs access to the key at runtime as well. Keep the key file (or the environment variable) at least as well protected as Kernel/Config.pmitself, ideally better (e.g. excluded from routine backups/dumps of the config directory).
Requirements#
Encryption/decryption requires the CPAN module CryptX (for
Crypt::AuthEnc::GCM), which is not bundled with Znuny. Install it e.g. via
cpanm CryptX or your OS package manager. Random IVs and keys are generated
with Crypt::URandom, which is bundled with Znuny.
Values are UTF-8 encoded before encryption, so any character can be used.
Encrypt()#
Encrypts a plain text value for storage in Kernel/Config.pm.
my $CipherText = $SecretObject->Encrypt(
Value => 'some-pass',
);
Returns undef and logs an error if no key is configured or CryptX is not
installed.
Decrypt()#
Decrypts a value previously created by Encrypt(). Values that are not
wrapped as {AES256:...} are returned unchanged, so this is safe to call
unconditionally on any config value.
my $PlainText = $SecretObject->Decrypt(
Value => $ConfigObject->Get('DatabasePw'),
);
GenerateKey()#
Generates a new random passphrase suitable for use as the encryption key (as an environment variable value or the content of a key file).
my $Passphrase = $SecretObject->GenerateKey();