
######
Secret
######


****
NAME
****


Kernel::System::Crypt::Secret - encrypt/decrypt secrets stored in Kernel/Config.pm


***********
DESCRIPTION
***********


Some credentials (e.g. \ ``DatabasePw``\ , the various LDAP \ ``SearchUserPw``\ 
settings) 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:


.. code-block:: perl

     {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:


1. The \ ``ZNUNY_CONFIG_SECRET_KEY``\  environment variable.



- 2. 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.pm*\ 
itself, 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.


.. code-block:: perl

     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.


.. code-block:: perl

     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).


.. code-block:: perl

     my $Passphrase = $SecretObject->GenerateKey();




