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]
|
[ldap]
|
||||||
url = "ldap://localhost,ldap://backup.localhost"
|
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