Browse Source

Update inaccurate details in JWS specification

Originally, when we were designing the implementation for a JWT
provider, we thought we would be able to use multiple signature
support in the JWS specification to allow tokens to have multiple
signatures. This would allow operators to specify multiple private
keys when rotating old/compromised keys off of a keystone server.

While that information is clearly documentedin the JWS specification:

  https://tools.ietf.org/html/rfc7515#section-7

Support for signing tokens with multiple private keys doesn't exist
yet in the library we're consuming for JWT (PyJWT).

This commit updates the specification with those details and attempts
to preserve the context of why we're not taking a multi-signature
approach right now. I've opened an issue in the upstream library we
consume to track the discussion:

  https://github.com/jpadilla/pyjwt/issues/390

bp json-web-tokens

Change-Id: I3c1d431241fab79d7c3feefeb978a977487e7bc0
Lance Bragstad 3 months ago
parent
commit
312c034e9b
1 changed files with 35 additions and 19 deletions
  1. 35
    19
      specs/keystone/stein/json-web-tokens.rst

+ 35
- 19
specs/keystone/stein/json-web-tokens.rst View File

@@ -148,7 +148,6 @@ Users will request and present tokens in exactly the same way they currently do
148 148
 with Fernet tokens. There is no need to add or change any APIs.
149 149
 
150 150
 .. _`JSON Web Token standard`: https://tools.ietf.org/html/rfc7519
151
-.. _`JWS`: https://tools.ietf.org/html/rfc7515
152 151
 .. _`JWE`: https://tools.ietf.org/html/rfc7516
153 152
 .. _`registered claims`: https://tools.ietf.org/html/rfc7519#section-4.1
154 153
 .. _`Python libraries`: https://jwt.io/#libraries
@@ -168,28 +167,42 @@ key with a special name, in order to ensure tokens can be validated during the
168 167
 rotation process. This won't be required with JWT and the following steps
169 168
 should be sufficient to perform key rotation without token invalidation due to
170 169
 missing signing keys. Assume the following steps are being performed on three
171
-different API servers, named `K1`, `K2`, and  `K3`, that need to validate
170
+different API servers, named `A`, `B`, and  `C`, that need to validate
172 171
 tokens issued by each other.
173 172
 
174
-1. A key pair is created for each API server. `K1.private`, `K1.pub` for
175
-   `K1`, `K2.private`, `K2.pub` for `K2`, and `K3.private`, `K3.pub` for `K3`.
176
-2. A copy of each public key is transferred to each API server. `K1`, `K2`, and
177
-   `K3` all have copies of `K1.pub`, `K2.pub`, and `K3.pub`.
173
+1. A key pair is created for each API server. `A.priv`, `A.pub` for `A`,
174
+   `B.priv`, `B.pub` for `B`, and `C.priv`, `C.pub` for `C`.
175
+2. A copy of each public key is transferred to each API server. `A`, `B`, and
176
+   `C` all have copies of `A.pub`, `B.pub`, and `C.pub`.
178 177
 
179 178
 At this point, tokens issued from any API server can be validated anywhere. In
180
-the event a single API server needs to rotate keypairs:
181
-
182
-1. A new key pair is created for `K1` called `K1-new.private` and `K1-new.pub`.
183
-   `K1` is configured to start signing tokens with both `K1.private` and
184
-   `K1-new.private.`
185
-2. `K1-new.pub` is copied to the public key repository of each API server. So
186
-   long as `K2` and `K3` have either `K1.pub` or `K1-new.pub` they can validate
187
-   tokens issued by `K1`.
188
-3. After `K2` and `K3` have been updated with copies of `K1-new.pub`,
189
-   `K1.private` can be removed from `K1` and `K1.pub` can be removed from `K2`
190
-   and `K3`. Tokens that were signed with only `K1.private` are unable to be
191
-   verified and `K1.pub` should only be removed after those tokens have expired
192
-   anyway.
179
+the event a single API server needs to rotate key pairs:
180
+
181
+1. A new key pair is created for `A` called `A'.priv` and `A'.pub`. `A` is not
182
+   configured to start signing tokens with `A'.priv` until all other nodes in
183
+   the cluster have a copy of `A'.pub`.
184
+2. `A'.pub` is copied to the public key repository of each API server. So
185
+   long as `B` and `C` have `A'.pub` they are ready to validate tokens signed
186
+   by the new private key `A'.priv`.
187
+3. After `B` and `C` have been updated with copies of `A'.pub`, server `A` can
188
+   be updated to start signing tokens with the new key `A'.priv`. Once all
189
+   tokens signed with `A.priv` are expired, `A.priv` and `A.pub` can be removed
190
+   from all servers. It is important to allow for a grace period between
191
+   configuring `A` to use `A'.priv` and removing `A.priv` in order to prevent
192
+   the premature invalidation of tokens that haven't expired yet.
193
+
194
+Note that the rotation process could be simplified slightly in step #1. The
195
+`JWS`_ specification goes into detail about serialization and support for
196
+multiple signatures in a single token. See `JWS section 7`_ for more
197
+information. The `PyJWT`_ library does not support multiple signatures on a
198
+single token. If it did, it would be possible to configure server `A` in step
199
+#1 to sign tokens with multiple private keys. Servers `B` and `C` would still
200
+be able to validate tokens from `A` because they have a copy of the public key
201
+(`A.pub`) used to create one of the token's signatures. The rest of the
202
+rotation process remains the same as far as propagating `A'.pub` to the other
203
+servers and eventually configuring `A` to only sign tokens with `A'.priv`. If,
204
+or when, `PyJWT`_ supports this functionality, support for multiple signatures
205
+in the JWS provider can be reconsidered.
193 206
 
194 207
 Traditional asymmetric keys can be revoked using revocation lists. At this time
195 208
 we are not going to support a revocation list implementation for JWT key pairs.
@@ -198,6 +211,9 @@ new keys in and out. Keystone will only use the public keys on disk to validate
198 211
 tokens. Is could change in the future, but for now it keeps the key rotation
199 212
 and key utilities with keystone simpler.
200 213
 
214
+.. _`JWS section 7`: https://tools.ietf.org/html/rfc7515#section-7
215
+.. _`JWS`: https://tools.ietf.org/html/rfc7515
216
+
201 217
 Crypto-Agility & Future Work
202 218
 ----------------------------
203 219
 

Loading…
Cancel
Save