1
1
[role="xpack"]
2
- [[jwt-realm]]
2
+ [[jwt-auth- realm]]
3
3
=== JWT authentication
4
4
5
5
beta::[]
@@ -40,22 +40,17 @@ way to enable OIDC authentication in {kib}.
40
40
[[jwt-realm-configuration]]
41
41
==== Configure {es} to use a JWT realm
42
42
43
- To use JWT authentication, you create the realm in the `elasticsearch.yml` file
43
+ To use JWT authentication, create the realm in the `elasticsearch.yml` file
44
44
to configure it within the {es} authentication chain.
45
45
46
46
The JWT realm has a few mandatory settings, plus optional settings that are
47
- described in <<ref-jwt-settings,JWT realm settings>>. The following example
48
- includes the most common settings. After defining settings, use the
49
- {ref}/elasticsearch-keystore.html[`elasticsearch-keystore`] tool to store
50
- values in the {es} keystore.
51
-
52
- NOTE: The example values are not intended for every use case, and are included
53
- only to highlight some common settings for this realm.
47
+ described in <<ref-jwt-settings,JWT realm settings>>.
54
48
55
- Client authentication is enabled by default for the JWT realms. Disabling client
56
- authentication is possible, but strongly discouraged.
49
+ NOTE: Client authentication is enabled by default for the JWT realms. Disabling
50
+ client authentication is possible, but strongly discouraged.
57
51
58
- . Add your JWT realm to the `elasticsearch.yml` file:
52
+ . Add your JWT realm to the `elasticsearch.yml` file. The following example
53
+ includes the most common settings, which are not intended for every use case:
59
54
+
60
55
--
61
56
[source,yaml]
@@ -97,36 +92,41 @@ verify the signature of the JWT from the JWT issuer.
97
92
`pkc_jwkset_path`::
98
93
The file path to a JSON Web Key Set (JWKS) containing the public key material
99
94
that the JWT realm uses to verify JWT signatures. If a path is provided,
100
- then it is resolved relative to the {es} configuration directory.
95
+ then it is resolved relative to the {es} configuration directory. In {ecloud},
96
+ use an absolute path starting with `/app/config/`.
101
97
102
98
`claims.principal`::
103
99
The name of the JWT claim that contains the user's principal (username).
104
100
105
101
--
106
102
107
- . Store the `shared_secret` value for `client_authentication.type`:
103
+ . After defining settings, use the
104
+ {ref}/elasticsearch-keystore.html[`elasticsearch-keystore`] tool to store
105
+ values for secure settings in the {es} keystore.
106
+
107
+ .. Store the `shared_secret` value for `client_authentication.type`:
108
108
+
109
109
[source,shell]
110
110
----
111
111
bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret
112
112
----
113
113
114
- . Store the HMAC keys for `allowed_signature_algorithms`, which use the HMAC
114
+ .. Store the HMAC keys for `allowed_signature_algorithms`, which use the HMAC
115
115
SHA-256 algorithm `HS256` in the example:
116
116
+
117
117
[source,shell]
118
118
----
119
119
bin/elasticsearch-keystore add-file xpack.security.authc.realms.jwt.jwt1.hmac_jwkset <path> <1>
120
120
----
121
121
<1> Path to a JWKS, which is a resource for a set of JSON-encoded secret keys.
122
- The file can be removed after the contents are loaded into the {es} keystore setting .
122
+ The file can be removed after you load the contents into the {es} keystore.
123
123
+
124
124
[NOTE]
125
125
====
126
- Using the JWK Set is preferred. However, you can add an HMAC key in string format
126
+ Using the JWKS is preferred. However, you can add an HMAC key in string format
127
127
using the following command. This format is compatible with OIDC HMAC keys, but
128
128
only supports a single key with no attributes. You can only use one HMAC format
129
- simultaneously.
129
+ (either `hmac_jwkset` or `hmac_key`) simultaneously.
130
130
131
131
[source,shell]
132
132
----
@@ -158,12 +158,14 @@ Signature: UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY
158
158
This example illustrates a partial decoding of a JWT. The validity period is
159
159
from 2000 to 2099 (inclusive), as defined by the issue time (`iat`) and
160
160
expiration time (`exp`). JWTs typically have a validity period shorter than
161
- 100 years. The signature in this example is deterministic because the header,
162
- claims, and HMAC key are fixed.
161
+ 100 years, such as 1-2 hours or 1-7 days, not an entire human life.
163
162
164
- The supported JWT encoding is JSON Web Signature (JWS). The JWS `Header` and
165
- `Signature` are validated using OpenID Connect ID Token validation rules. Some
166
- validation is customizable through <<ref-jwt-settings,JWT realm settings>>.
163
+ The signature in this example is deterministic because the header, claims, and
164
+ HMAC key are fixed. JWTs typically have a `nonce` claim to make the signature
165
+ non-deterministic. The supported JWT encoding is JSON Web Signature (JWS), and
166
+ the JWS `Header` and `Signature` are validated using OpenID Connect ID Token
167
+ validation rules. Some validation is customizable through
168
+ <<ref-jwt-settings,JWT realm settings>>.
167
169
168
170
[[jwt-validation-header]]
169
171
===== Header claims
@@ -256,15 +258,18 @@ setting `claims.dn_pattern` to extract a substring value.
256
258
[[jwt-authorization]]
257
259
==== JWT realm authorization
258
260
The JWT realm supports authorization with the create or update role mappings API,
259
- as well as delegating authorization to another realm.
261
+ or delegating authorization to another realm. You cannot use these methods
262
+ simultaneously, so choose whichever works best for your environment.
260
263
261
264
IMPORTANT: You cannot map roles in the JWT realm using the `role_mapping.yml`
262
265
file.
263
266
267
+ [[jwt-authorization-role-mapping]]
264
268
===== Authorizing with the role mapping API
265
269
You can use the
266
270
<<security-api-put-role-mapping,create or update role mappings API>> to define
267
- role mappings in the JWT realm:
271
+ role mappings that determine which roles should be assigned to each user based on
272
+ their username, groups, or other metadata.
268
273
269
274
[source,console]
270
275
----
@@ -301,14 +306,15 @@ boolean values, and collections that are used as the {es} user's metadata.
301
306
These values are key value pairs formatted as
302
307
`metadata.jwt_claim_<key>` = `<value>`.
303
308
309
+ [[jwt-authorization-delegation]]
304
310
===== Delegating JWT authorization to another realm
305
- If you <<authorization_realms,delegate authorization>> to another realm from the
311
+ If you <<authorization_realms,delegate authorization>> to other realms from the
306
312
JWT realm, only the `principal` claim is available for role lookup. When
307
313
delegating the assignment and lookup of roles to another realm from the JWT
308
314
realm, claims for `dn`, `groups`, `mail`, `metadata`, and `name` are not used
309
315
for the {es} user's values. Only the JWT `principal` claim is passed to the
310
- delegated authorization realm . The realm that is delegated for authorization
311
- - not the JWT realm - becomes responsible for populating all of the {es} user's
316
+ delegated authorization realms . The realms that are delegated for authorization
317
+ - not the JWT realm - become responsible for populating all of the {es} user's
312
318
values.
313
319
314
320
The following example shows how you define delegation authorization in the
@@ -344,11 +350,99 @@ If realm `jwt2` successfully authenticates a client with a JWT for principal
344
350
this defined role mapping, the realm can also look up this role mapping rule
345
351
linked to realm `native1`.
346
352
353
+ [[jwt-realm-runas]]
354
+ ===== Applying the `run_as` privilege to JWT realm users
355
+ {es} can retrieve roles for a JWT user through either role mapping or
356
+ delegated authorization. Regardless of which option you choose, you can apply the
357
+ <<run-as-privilege-apply,`run_as` privilege>> to a role so that a user can
358
+ submit authenticated requests to "run as" a different user. To submit requests as
359
+ another user, include the `es-security-runas-user` header in your requests.
360
+ Requests run as if they were issued from that user and {es} uses their roles.
361
+
362
+ For example, let's assume that there's a user with the username `user123_runas`.
363
+ The following request creates a user role named `jwt_role1`, which specifies a
364
+ `run_as` user with the `user123_runas` username. Any user with the `jwt_role1`
365
+ role can issue requests as the specified `run_as` user.
366
+
367
+ [source,console]
368
+ ----
369
+ POST /_security/role/jwt_role1?refresh=true
370
+ {
371
+ "cluster": ["manage"],
372
+ "indices": [ { "names": [ "*" ], "privileges": ["read"] } ],
373
+ "run_as": [ "user123_runas" ],
374
+ "metadata" : { "version" : 1 }
375
+ }
376
+ ----
377
+
378
+ You can then map that role to a user in a specific realm. The following request
379
+ maps the `jwt_role1` role to a user with the username `user2` in the `jwt2` JWT
380
+ realm. This means that {es} will use the `jwt2` realm to authenticate the user
381
+ named `user2`. Because `user2` has a role (the `jwt_role1` role) that includes
382
+ the `run_as` privilege, {es} retrieves the role mappings for the `user123_runas`
383
+ user and uses the roles for that user to submit requests.
384
+
385
+ [source,console]
386
+ ----
387
+ POST /_security/role_mapping/jwt_user1?refresh=true
388
+ {
389
+ "roles": [ "jwt_role1"],
390
+ "rules" : { "all" : [
391
+ { "field": { "realm.name": "jwt2" } },
392
+ { "field": { "username": "user2" } }
393
+ ] },
394
+ "enabled": true,
395
+ "metadata" : { "version" : 1 }
396
+ }
397
+ ----
398
+
399
+ After mapping the roles, you can make an
400
+ <<security-api-authenticate,authenticated call>> to {es} using a JWT and include
401
+ the `ES-Client-Authentication` header:
402
+
403
+ [source,sh]
404
+ ----
405
+ curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" https://localhost:9200/_security/_authenticate
406
+ ----
407
+ // NOTCONSOLE
408
+
409
+ The response includes the user who submitted the request (`user2`), including
410
+ the `jwt_role1` role that you mapped to this user in the JWT realm:
411
+
412
+ [source,sh]
413
+ ----
414
+ {"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"[email protected] ",
415
+ "metadata":{"jwt_claim_email":"[email protected] ","jwt_claim_aud":["es01","es02","es03"],
416
+ "jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm":
417
+ {"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}
418
+ %
419
+ ----
420
+
421
+ If you want to specify a request as the `run_as` user, include the
422
+ the `es-security-runas-user` header with the name of the user that you
423
+ want to submit requests as. The following request uses the `user123_runas` user:
424
+
425
+ [source,sh]
426
+ ----
427
+ curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" -H "es-security-runas-user: user123_runas" https://localhost:9200/_security/_authenticate
428
+ ----
429
+ // NOTCONSOLE
430
+
431
+ In the response, you'll see that the `user123_runas` user submitted the request,
432
+ and {es} used the `jwt_role1` role:
433
+
434
+ [source,sh]
435
+ ----
436
+ {"username":"user123_runas","roles":["jwt_role1"],"full_name":null,"email":null,"metadata":{},
437
+ "enabled":true,"authentication_realm":{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"native",
438
+ "type":"native"},"authentication_type":"realm"}%
439
+ ----
440
+
347
441
[[hmac-oidc-example]]
348
442
==== Authorizing to the JWT realm with an OIDC HMAC key
349
443
The following settings are for a JWT issuer, {es}, and a client of {es}. The
350
- example HMAC key is in an OIDC HMAC compatible format . The key bytes are the
351
- UTF-8 encoding of the UNICODE characters.
444
+ example HMAC key is in an OIDC format that's compatible with HMAC . The key bytes
445
+ are the UTF-8 encoding of the UNICODE characters.
352
446
353
447
IMPORTANT: HMAC UTF-8 keys need to be longer than HMAC random byte keys to
354
448
achieve the same key strength.
@@ -368,21 +462,25 @@ HMAC OIDC: hmac-oidc-key-string-for-hs256-algorithm
368
462
369
463
[[hmac-oidc-example-jwt-realm]]
370
464
===== JWT realm settings
371
- The following settings are for `elasticsearch.yml`.
465
+ To define a JWT realm, add the following realm settings to `elasticsearch.yml`.
372
466
373
467
[source,yaml]
374
468
----
375
- xpack.security.authc.realms.jwt.jwt8.order: 8
469
+ xpack.security.authc.realms.jwt.jwt8.order: 8 <1>
376
470
xpack.security.authc.realms.jwt.jwt8.allowed_issuer: iss8
377
471
xpack.security.authc.realms.jwt.jwt8.allowed_audiences: [aud8]
378
472
xpack.security.authc.realms.jwt.jwt8.allowed_signature_algorithms: [HS256]
379
473
xpack.security.authc.realms.jwt.jwt8.claims.principal: sub
380
474
xpack.security.authc.realms.jwt.jwt8.client_authentication.type: shared_secret
381
475
----
476
+ <1> In {ecloud}, the realm order starts at `2`. `0` and `1` are reserved in the
477
+ realm chain on {ecloud}.
382
478
383
479
===== JWT realm secure settings
384
- The following secure settings are for the
385
- {ref}/elasticsearch-keystore.html[`elasticsearch-keystore`].
480
+ After defining the realm settings, use the
481
+ {ref}/elasticsearch-keystore.html[`elasticsearch-keystore`] tool to add the
482
+ following secure settings to the {es} keystore. In {ecloud}, you define settings
483
+ for the {es} keystore under **Security** in your deployment.
386
484
387
485
[source,yaml]
388
486
----
@@ -413,7 +511,30 @@ The following header settings are for an {es} client.
413
511
414
512
[source,js]
415
513
----
416
- ES-Client-Authentication: SharedSecret client-shared-secret-string
417
514
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY
515
+ ES-Client-Authentication: SharedSecret client-shared-secret-string
516
+ ----
517
+ // NOTCONSOLE
518
+
519
+ You can use this header in a `curl` request to make an authenticated call to
520
+ {es}. Both the bearer token and the client authorization token must be
521
+ specified as separate headers with the `-H` option:
522
+
523
+ [source,sh]
524
+ ----
525
+ curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY" -H "ES-Client-Authentication: SharedSecret client-shared-secret-string" https://localhost:9200/_security/_authenticate
418
526
----
419
527
// NOTCONSOLE
528
+
529
+ If you used role mapping in the JWT realm, the response includes the user's
530
+ `username`, their `roles`, metadata about the user, and the details about the
531
+ JWT realm itself.
532
+
533
+ [source,sh]
534
+ ----
535
+ {"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"[email protected] ",
536
+ "metadata":{"jwt_claim_email":"[email protected] ","jwt_claim_aud":["es01","es02","es03"],
537
+ "jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm":
538
+ {"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}
539
+ %
540
+ ----
0 commit comments