Add JWS token provider documentation
Add documentation that advertise support for JWS tokens. bp json-web-tokens Change-Id: If1700c53674ad98b54f572a73b5d4350c7837ab6
This commit is contained in:
parent
96adccd0ec
commit
950e7d1f6d
|
@ -0,0 +1,72 @@
|
|||
================
|
||||
JWS key rotation
|
||||
================
|
||||
|
||||
The JWS token provider issues tokens using asymmetric signing. This document
|
||||
attempts to describe how to manage key pairs in a deployment of keystone nodes
|
||||
that need to validate tokens issued by one another.
|
||||
|
||||
The inherent benefit of using asymmetric keys is that each keystone server
|
||||
generates it's own key pair. The private key is used to sign tokens. Anyone
|
||||
with access to the public key has the ability to verify the token signature.
|
||||
This is a critical step in validating tokens across a cluster of keystone
|
||||
nodes.
|
||||
|
||||
It is necessary for operators to sync public keys across all keystone nodes in
|
||||
the deployment. Each keystone server will need a corresponding public key for
|
||||
every node. This only applies to public keys. Private keys should never leave
|
||||
the server they are generated from.
|
||||
|
||||
Initial setup
|
||||
-------------
|
||||
|
||||
Before a deployment of keystone servers can issue JWT tokens, each server must
|
||||
set ``keystone.conf [token] provider = jws``. Additionally, each API server
|
||||
must have its own asymmetric key pair either generated manually or using
|
||||
``keystone-manage create_jws_keypair``. If you're generating the key pairs
|
||||
manually, they must be usable with the ``ES256`` JSON Web Algorithm (`JWA`_). It
|
||||
is worth noting that the ``keystone-manage create_jws_keypair`` command line
|
||||
utility will create an appropriate key pair, but it will not automatically
|
||||
deploy it to the key repository locations defined in ``keystone.conf
|
||||
[jwt_tokens]``. It is up to operators to move these files accordingly and
|
||||
resolve possible file name conflicts.
|
||||
|
||||
After generating a key pair, the public key from each API server must be shared
|
||||
with every other API server in the deployment. Ensure the private key used to
|
||||
sign JWS tokens is readable by the process running keystone and available in
|
||||
the ``keystone.conf [jwt_tokens] jws_private_key_repository`` location.
|
||||
Keystone will automatically use a key named ``private.pem`` to sign tokens and
|
||||
ignore all other keys in the repository. To validate tokens, keystone will
|
||||
iterate all available public keys in ``keystone.conf [jwt_tokens]
|
||||
jws_public_key_repository``. At a minimum, this repository needs to have the
|
||||
corresponding public key to the ``private.pem`` key found in ``keystone.conf
|
||||
[jwt_tokens] jws_private_key_repository``.
|
||||
|
||||
.. _`JWA`: https://tools.ietf.org/html/rfc7518
|
||||
|
||||
Continued operations
|
||||
--------------------
|
||||
|
||||
Depending on the security requirements for your deployment, you might need to
|
||||
rotate out an existing key pair. To do so without prematurely invalidating
|
||||
tokens, follow these steps:
|
||||
|
||||
1. Generate a new asymmetric key pair for a given keystone API server (see
|
||||
``keystone-manage create_jws_keypair`` for more details)
|
||||
2. Copy or sync the newly generated public key to the public key repositories
|
||||
of all other keystone API servers, the public key should be placed in
|
||||
``keystone.conf [jwt_tokens] jws_public_key_repository``
|
||||
3. Copy the new private key to the private key repository on the API server
|
||||
you're performing the rotation on and make sure it's named ``private.pem``,
|
||||
at this point the server will start signing tokens with the new private key
|
||||
and all other keystone API servers will be able to validate those tokens
|
||||
since they already have a copy of the public key from step #2
|
||||
4. At this point, you must wait until the last tokens signed with the old
|
||||
private key have expired before you can remove the old corresponding public
|
||||
keys from each keystone API server, note this should be a minimum of
|
||||
``keystone.conf [token] expiration``
|
||||
5. Once you're confident all tokens signed with the old private key are
|
||||
expired, it is safe to remove the old corresponding public key from each API
|
||||
server in the deployment, which is important in case the original private
|
||||
key was compromised and prevents attackers from using it craft their own
|
||||
tokens
|
|
@ -31,3 +31,16 @@ Fernet
|
|||
|
||||
Fernet tokens are bearer tokens. They must be protected from unnecessary
|
||||
disclosure to prevent unauthorized access.
|
||||
|
||||
JWS
|
||||
``jws`` tokens do not need to be persisted at all, but require that you
|
||||
configure an asymmetric key pair to sign and validate tokens. The key pair can
|
||||
be generated using ``keystone-manage create_jws_keypair`` or it can be
|
||||
generated out-of-band manually so long as it is compatible with the JWT
|
||||
``ES256`` Elliptic Curve Digital Signature Algorithm (ECDSA) using a P-256
|
||||
curve and a SHA-256 hash algorithm.
|
||||
|
||||
.. warning::
|
||||
|
||||
JWS tokens are bearer tokens. They must be protected from unnecessary
|
||||
disclosure to prevent unauthorized access.
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
# drivers should maintain their own equivalent document, and merge it with this
|
||||
# when their code merges into core.
|
||||
driver-impl-fernet=Fernet tokens
|
||||
driver-impl-jws=JWS tokens
|
||||
|
||||
[operation.create_unscoped_token]
|
||||
title=Create unscoped token
|
||||
|
@ -65,6 +66,7 @@ notes=All token providers must be capable of issuing tokens without an explicit
|
|||
cli=openstack --os-username=<username> --os-user-domain-name=<domain>
|
||||
--os-password=<password> token issue
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.create_system_token]
|
||||
title=Create system-scoped token
|
||||
|
@ -73,6 +75,7 @@ notes=All token providers must be capable of issuing system-scoped tokens.
|
|||
cli=openstack --os-username=<username> --os-user-domain-name=<domain>
|
||||
--os-system-scope all token issue
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.create_project_scoped_token]
|
||||
title=Create project-scoped token
|
||||
|
@ -82,6 +85,7 @@ cli=openstack --os-username=<username> --os-user-domain-name=<domain>
|
|||
--os-password=<password> --os-project-name=<project>
|
||||
--os-project-domain-name=<domain> token issue
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.create_domain_scoped_token]
|
||||
title=Create domain-scoped token
|
||||
|
@ -91,6 +95,7 @@ notes=Domain-scoped tokens are not required for all use cases, and for some use
|
|||
cli=openstack --os-username=<username> --os-user-domain-name=<domain>
|
||||
--os-password=<password> --os-domain-name=<domain> token issue
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.create_trust_scoped_token]
|
||||
title=Create trust-scoped token
|
||||
|
@ -100,6 +105,7 @@ notes=Tokens scoped to a trust convey only the user impersonation and
|
|||
cli=openstack --os-username=<username> --os-user-domain-name=<domain>
|
||||
--os-password=<password> --os-trust-id=<trust> token issue
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.create_token_using_oauth]
|
||||
title=Create a token given an OAuth access token
|
||||
|
@ -107,6 +113,7 @@ status=optional
|
|||
notes=OAuth access tokens can be exchanged for keystone tokens.
|
||||
cli=
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[operation.revoke_token]
|
||||
title=Revoke a token
|
||||
|
@ -117,6 +124,7 @@ notes=Tokens may be individually revoked, such as when a user logs out of
|
|||
revoked token was previously used to create additional tokens).
|
||||
cli=openstack token revoke
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[feature.online_validation]
|
||||
title=Online validation
|
||||
|
@ -125,6 +133,7 @@ notes=Keystone must be able to validate the tokens that it issues when
|
|||
presented with a token that it previously issued.
|
||||
cli=
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
||||
[feature.offline_validation]
|
||||
title=Offline validation
|
||||
|
@ -134,6 +143,7 @@ notes=Services using Keystone for authentication may want to validate tokens
|
|||
performance and scalability.
|
||||
cli=
|
||||
driver-impl-fernet=missing
|
||||
driver-impl-jws=missing
|
||||
|
||||
[feature.non_persistent]
|
||||
title=Non-persistent
|
||||
|
@ -144,3 +154,4 @@ notes=If a token format does not require persistence (such as to a SQL
|
|||
operations such as `keystone-manage token_flush`.
|
||||
cli=
|
||||
driver-impl-fernet=complete
|
||||
driver-impl-jws=complete
|
||||
|
|
|
@ -77,8 +77,8 @@ Token providers
|
|||
---------------
|
||||
|
||||
The token type issued by keystone is configurable through the
|
||||
``/etc/keystone/keystone.conf`` file. Currently, the only supported token
|
||||
provider is ``fernet``.
|
||||
``/etc/keystone/keystone.conf`` file. Currently, there are two supported token
|
||||
providers, ``fernet`` and ``jws``.
|
||||
|
||||
Fernet tokens
|
||||
~~~~~~~~~~~~~
|
||||
|
@ -93,4 +93,36 @@ fernet tokens. Like UUID tokens, fernet tokens must be passed back to the
|
|||
Identity service in order to validate them. For more information on the fernet
|
||||
token type, see the :doc:`fernet-token-faq`.
|
||||
|
||||
A deployment might consider using the fernet provider as opposed to JWS tokens
|
||||
if they are concerned about public expose of the payload used to build tokens.
|
||||
|
||||
JWS tokens
|
||||
~~~~~~~~~~
|
||||
|
||||
The JSON Web Signature (JWS) token format is a type of JSON Web Token (JWT) and
|
||||
it was implemented in the Stein release. JWS tokens are signed, meaning the
|
||||
information used to build the token ID is not opaque to users and can it can be
|
||||
decoded by anyone. JWS tokens are ephemeral, or non-persistent, which means
|
||||
they won't bloat the database or require replication across nodes. Since the
|
||||
JWS token provider uses asymmetric keys, the tokens are signed with private
|
||||
keys and validated with public keys. The JWS token provider implementation
|
||||
only supports the ``ES256`` JSON Web Algorithm (JWA), which is an Elliptic
|
||||
Curve Digital Signature Algorithm (ECDSA) using the P-256 curve and a SHA-256
|
||||
hash algorithm.
|
||||
|
||||
A deployment might consider using JWS tokens as opposed to fernet tokens if
|
||||
there are security concerns about sharing symmetric encryption keys across
|
||||
hosts. Note that a major difference between the two providers is that JWS
|
||||
tokens are not opaque and can be decoded by anyone with the token ID. Fernet
|
||||
tokens are opaque in that the token ID is ciphertext. Despite the JWS token
|
||||
payload being readable by anyone, keystone reserves the right to make backwards
|
||||
incompatible changes to the token payload itself, which is not an API contract.
|
||||
We only recommend validating the token against keystone's authentication API to
|
||||
inspect its associated metadata. We strongly discourage relying on decoded
|
||||
payloads for information about tokens.
|
||||
|
||||
More information about JWTs can be found in the `specification`_.
|
||||
|
||||
.. _`specification`: https://tools.ietf.org/html/rfc7519
|
||||
|
||||
.. support_matrix:: token-support-matrix.ini
|
||||
|
|
|
@ -9,4 +9,5 @@ Everything you need to know about keystone tokens.
|
|||
|
||||
tokens-overview
|
||||
fernet-token-faq
|
||||
jws-key-rotation
|
||||
token-provider
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
[`blueprint json-web-tokens <https://blueprints.launchpad.net/keystone/+spec/json-web-tokens>`_]
|
||||
Keystone now supports a JSON Web Signature (JWS) token provider in addition
|
||||
to fernet tokens. Fernet token remain the default token provider. Full
|
||||
details can be found in the `specification
|
||||
<http://specs.openstack.org/openstack/keystone-specs/specs/keystone/stein/json-web-tokens.html>`_.
|
Loading…
Reference in New Issue