Document credential encryption
Add documentation on how credential encryption work and a release note. bp credential-encryption Change-Id: Ib06c86a17e585f43bfa8aedf3d5e89d3163cc9da
This commit is contained in:
parent
7a82aa8a6d
commit
0e7ab57241
@ -1813,3 +1813,123 @@ example:
|
||||
|
||||
[ldap]
|
||||
url = "ldap://localhost,ldap://backup.localhost"
|
||||
|
||||
|
||||
Credential Encryption
|
||||
=====================
|
||||
|
||||
As of the Newton release, keystone encrypts all credentials stored in the
|
||||
default ``sql`` backend. Credentials are encrypted with the same mechanism used
|
||||
to encrypt Fernet tokens, ``fernet``. Keystone provides only one type of
|
||||
credential encryption but the encryption provider is pluggable in the event
|
||||
you wish to supply a custom implementation.
|
||||
|
||||
This document details how credential encryption works, how to migrate existing
|
||||
credentials in a deployment, and how to manage encryption keys for credentials.
|
||||
|
||||
Configuring credential encryption
|
||||
---------------------------------
|
||||
|
||||
The configuration for credential encryption is straightforward. There are only
|
||||
two configuration options needed:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[credential]
|
||||
provider = fernet
|
||||
key_repository = /etc/keystone/credential-keys/
|
||||
|
||||
``[credential] provider`` defaults to the only option supplied by keystone,
|
||||
``fernet``. There is no reason to change this option unless you wish to provide
|
||||
a custom credential encryption implementation. The ``[credential]
|
||||
key_repository`` location is a requirement of using ``fernet`` but will default
|
||||
to the ``/etc/keystone/credential-keys/`` directory. Both ``[credential]
|
||||
key_repository`` and ``[fernet_tokens] key_repository`` define locations for
|
||||
keys used to encrypt things. One holds the keys to encrypt and decrypt
|
||||
credentials and the other holds keys to encrypt and decrypt tokens. It is
|
||||
imperative that these repositories are managed separately and they must not
|
||||
share keys. Meaning they cannot share the same directory path. The
|
||||
``[credential] key_repository`` is only allowed to have three keys. This is not
|
||||
configurable and allows for credentials to be re-encrypted periodically with a
|
||||
new encryption key for the sake of security.
|
||||
|
||||
How credential encryption works
|
||||
-------------------------------
|
||||
|
||||
The implementation of this feature did not change any existing credential API
|
||||
contracts. All changes are transparent to the user unless you're inspecting the
|
||||
credential backend directly.
|
||||
|
||||
When creating a credential, keystone will encrypt the ``blob`` attribute before
|
||||
persisting it to the backend. Keystone will also store a hash of the key that
|
||||
was used to encrypt the information in that credential. Since Fernet is used to
|
||||
encrypt credentials, a key repository consists of multiple keys. Keeping track
|
||||
of which key was used to encrypt each credential is an important part of
|
||||
encryption key management. Why this is important is detailed later in the
|
||||
`Encryption key management` section.
|
||||
|
||||
When updating an existing credential's ``blob`` attribute, keystone will encrypt
|
||||
the new ``blob`` and update the key hash.
|
||||
|
||||
When listing or showing credentials, all ``blob`` attributes are decrypted in
|
||||
the response. Neither the cipher text, nor the hash of the key used to encrypt
|
||||
the ``blob`` are exposed through the API. Furthermore, the key is only used
|
||||
internally to keystone.
|
||||
|
||||
Encrypting existing credentials
|
||||
-------------------------------
|
||||
|
||||
When upgrading a Mitaka deployment to Newton, three database migrations will
|
||||
ensure all credentials are encrypted. The process is as follows:
|
||||
|
||||
1. An additive schema change is made to create the new ``encrypted_blob`` and
|
||||
``key_hash`` columns in the existing ``credential`` table using
|
||||
``keystone-manage db_sync --expand``.
|
||||
2. A data migration will loop through all existing credentials, encrypt each
|
||||
``blob`` and store the result in the new ``encrypted_blob`` column. The hash
|
||||
of the key used is also written to the ``key_hash`` column for that specific
|
||||
credential. This step is done using ``keystone-manage db_sync --migrate``.
|
||||
3. A contractive schema will remove the ``blob`` column that held the plain
|
||||
text representations of the credential using ``keystone-manage db_sync
|
||||
--contract``. This should only be done after all nodes in the deployment are
|
||||
running Newton. If any Mitaka nodes are running after the database is
|
||||
contracted, they won't be able to read credentials since they are looking
|
||||
for the ``blob`` column that no longer exists.
|
||||
|
||||
If performing a rolling upgrade, please note that a limited service outage will
|
||||
take affect during this migration. When the migration is in place, credentials
|
||||
will become read-only until the database is contracted. After the contract
|
||||
phase is complete, credentials will be writeable to the backend. A
|
||||
``[credential] key_repository`` location must be specified through
|
||||
configuration and bootstrapped with keys using ``keystone-manage
|
||||
credential_setup`` prior to migrating any existing credentials.
|
||||
|
||||
Encryption key management
|
||||
-------------------------
|
||||
|
||||
Key management of ``[credential] key_repository`` is handled with three
|
||||
``keystone-manage`` commands:
|
||||
|
||||
1. ``keystone-manage credential_setup``
|
||||
2. ``keystone-manage credential_rotate``
|
||||
3. ``keystone-manage credential_migrate``
|
||||
|
||||
``keystone-manage credential_setup`` will populate ``[credential]
|
||||
key_repository`` with new encryption keys. This must be done in order for
|
||||
credential encryption to work. This step should only be done once.
|
||||
|
||||
``keystone-manage credential_rotate`` will create and rotate a new encryption
|
||||
key in the ``[credential] key_repository``. This will only be done if all
|
||||
credential key hashes match the hash of the current primary key. If any
|
||||
credential has been encrypted with an older key, or secondary key, the rotation
|
||||
will fail. Failing the rotation is necessary to prevent overrotation, which
|
||||
would leave some credentials indecipherable since the key used to encrypt it
|
||||
no longer exists. If this step fails, it is possible to forcibly re-key all
|
||||
credentials using the same primary key with ``keystone-manage
|
||||
credential_migrate``.
|
||||
|
||||
``keystone-manage credential_migrate`` will check the backend for credentials
|
||||
whose key hash doesn't match the hash of the current primary key. Any
|
||||
credentials with a key hash mismatching the current primary key will be
|
||||
re-encrypted with the current primary key. The new cipher text and key hash
|
||||
will be updated in the backend.
|
||||
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
upgrade:
|
||||
- Keystone now supports encrypted credentials at rest.
|
||||
In order to upgrade successfully to Newton, deployers
|
||||
must encrypt all credentials currently stored before
|
||||
contracting the database. Deployers must run
|
||||
`keystone-manage credential_setup` in order to use the
|
||||
credential API within Newton, or finish the upgrade
|
||||
from Mitaka to Newton. This will result in a service
|
||||
outage for the credential API where credentials will
|
||||
be read-only for the duration of the upgrade process.
|
||||
Once the database is contracted credentials will be
|
||||
writeable again. Database contraction phases only
|
||||
apply to rolling upgrades.
|
Loading…
Reference in New Issue
Block a user