7
7
8
8
import org .elasticsearch .common .settings .SecureString ;
9
9
import org .elasticsearch .common .settings .Setting ;
10
+ import org .elasticsearch .common .unit .TimeValue ;
10
11
import org .elasticsearch .common .util .set .Sets ;
12
+ import org .elasticsearch .xpack .core .security .authc .RealmConfig ;
11
13
import org .elasticsearch .xpack .core .security .authc .RealmSettings ;
12
14
import org .elasticsearch .xpack .core .security .authc .support .DelegatedAuthorizationSettings ;
15
+ import org .elasticsearch .xpack .core .ssl .SSLConfigurationSettings ;
13
16
17
+ import java .net .URI ;
18
+ import java .net .URISyntaxException ;
19
+ import java .util .Arrays ;
20
+ import java .util .Collection ;
14
21
import java .util .Collections ;
15
22
import java .util .List ;
16
23
import java .util .Set ;
@@ -22,36 +29,161 @@ public class OpenIdConnectRealmSettings {
22
29
private OpenIdConnectRealmSettings () {
23
30
}
24
31
32
+ private static final List <String > signatureAlgorithms = Collections .unmodifiableList (
33
+ Arrays .asList ("HS256" , "HS384" , "HS512" , "RS256" , "RS384" , "RS512" , "ES256" , "ES384" , "ES512" , "PS256" , "PS384" , "PS512" ));
34
+ private static final List <String > responseTypes = Arrays .asList ("code" , "id_token" , "id_token token" );
25
35
public static final String TYPE = "oidc" ;
26
36
27
- public static final Setting .AffixSetting <String > OP_NAME
28
- = RealmSettings .simpleString (TYPE , "op.name" , Setting .Property .NodeScope );
29
37
public static final Setting .AffixSetting <String > RP_CLIENT_ID
30
38
= RealmSettings .simpleString (TYPE , "rp.client_id" , Setting .Property .NodeScope );
31
39
public static final Setting .AffixSetting <SecureString > RP_CLIENT_SECRET
32
40
= RealmSettings .secureString (TYPE , "rp.client_secret" );
33
41
public static final Setting .AffixSetting <String > RP_REDIRECT_URI
34
- = RealmSettings .simpleString (TYPE , "rp.redirect_uri" , Setting .Property .NodeScope );
42
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "rp.redirect_uri" ,
43
+ key -> Setting .simpleString (key , v -> {
44
+ try {
45
+ new URI (v );
46
+ } catch (URISyntaxException e ) {
47
+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
48
+ }
49
+ }, Setting .Property .NodeScope ));
35
50
public static final Setting .AffixSetting <String > RP_RESPONSE_TYPE
36
- = RealmSettings .simpleString (TYPE , "rp.response_type" , Setting .Property .NodeScope );
51
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "rp.response_type" ,
52
+ key -> Setting .simpleString (key , v -> {
53
+ if (responseTypes .contains (v ) == false ) {
54
+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Allowed values are " + responseTypes + "" );
55
+ }
56
+ }, Setting .Property .NodeScope ));
57
+ public static final Setting .AffixSetting <String > RP_SIGNATURE_ALGORITHM
58
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "rp.signature_algorithm" ,
59
+ key -> new Setting <>(key , "RS256" , Function .identity (), v -> {
60
+ if (signatureAlgorithms .contains (v ) == false ) {
61
+ throw new IllegalArgumentException (
62
+ "Invalid value [" + v + "] for [" + key + "]. Allowed values are " + signatureAlgorithms + "}]" );
63
+ }
64
+ }, Setting .Property .NodeScope ));
65
+ public static final Setting .AffixSetting <List <String >> RP_REQUESTED_SCOPES = Setting .affixKeySetting (
66
+ RealmSettings .realmSettingPrefix (TYPE ), "rp.requested_scopes" ,
67
+ key -> Setting .listSetting (key , Collections .singletonList ("openid" ), Function .identity (), Setting .Property .NodeScope ));
68
+
69
+ public static final Setting .AffixSetting <String > OP_NAME
70
+ = RealmSettings .simpleString (TYPE , "op.name" , Setting .Property .NodeScope );
37
71
public static final Setting .AffixSetting <String > OP_AUTHORIZATION_ENDPOINT
38
- = RealmSettings .simpleString (TYPE , "op.authorization_endpoint" , Setting .Property .NodeScope );
72
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "op.authorization_endpoint" ,
73
+ key -> Setting .simpleString (key , v -> {
74
+ try {
75
+ new URI (v );
76
+ } catch (URISyntaxException e ) {
77
+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
78
+ }
79
+ }, Setting .Property .NodeScope ));
39
80
public static final Setting .AffixSetting <String > OP_TOKEN_ENDPOINT
40
- = RealmSettings .simpleString (TYPE , "op.token_endpoint" , Setting .Property .NodeScope );
81
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "op.token_endpoint" ,
82
+ key -> Setting .simpleString (key , v -> {
83
+ try {
84
+ new URI (v );
85
+ } catch (URISyntaxException e ) {
86
+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
87
+ }
88
+ }, Setting .Property .NodeScope ));
41
89
public static final Setting .AffixSetting <String > OP_USERINFO_ENDPOINT
42
- = RealmSettings .simpleString (TYPE , "op.userinfo_endpoint" , Setting .Property .NodeScope );
90
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "op.userinfo_endpoint" ,
91
+ key -> Setting .simpleString (key , v -> {
92
+ try {
93
+ new URI (v );
94
+ } catch (URISyntaxException e ) {
95
+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
96
+ }
97
+ }, Setting .Property .NodeScope ));
43
98
public static final Setting .AffixSetting <String > OP_ISSUER
44
99
= RealmSettings .simpleString (TYPE , "op.issuer" , Setting .Property .NodeScope );
45
- public static final Setting .AffixSetting <List <String >> RP_REQUESTED_SCOPES = Setting .affixKeySetting (
46
- RealmSettings .realmSettingPrefix (TYPE ), "rp.requested_scopes" ,
47
- key -> Setting .listSetting (key , Collections .singletonList ("openid" ), Function .identity (), Setting .Property .NodeScope ));
100
+ public static final Setting .AffixSetting <String > OP_JWKSET_PATH
101
+ = RealmSettings .simpleString (TYPE , "op.jwkset_path" , Setting .Property .NodeScope );
102
+
103
+ public static final Setting .AffixSetting <TimeValue > ALLOWED_CLOCK_SKEW
104
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "allowed_clock_skew" ,
105
+ key -> Setting .timeSetting (key , TimeValue .timeValueSeconds (60 ), Setting .Property .NodeScope ));
106
+ public static final Setting .AffixSetting <Boolean > POPULATE_USER_METADATA = Setting .affixKeySetting (
107
+ RealmSettings .realmSettingPrefix (TYPE ), "populate_user_metadata" ,
108
+ key -> Setting .boolSetting (key , true , Setting .Property .NodeScope ));
109
+ private static final TimeValue DEFAULT_TIMEOUT = TimeValue .timeValueSeconds (5 );
110
+ public static final Setting .AffixSetting <TimeValue > HTTP_CONNECT_TIMEOUT
111
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.connect_timeout" ,
112
+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
113
+ public static final Setting .AffixSetting <TimeValue > HTTP_CONNECTION_READ_TIMEOUT
114
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.connection_read_timeout" ,
115
+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
116
+ public static final Setting .AffixSetting <TimeValue > HTTP_SOCKET_TIMEOUT
117
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.socket_timeout" ,
118
+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
119
+ public static final Setting .AffixSetting <Integer > HTTP_MAX_CONNECTIONS
120
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.max_connections" ,
121
+ key -> Setting .intSetting (key , 200 , Setting .Property .NodeScope ));
122
+ public static final Setting .AffixSetting <Integer > HTTP_MAX_ENDPOINT_CONNECTIONS
123
+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.max_endpoint_connections" ,
124
+ key -> Setting .intSetting (key , 200 , Setting .Property .NodeScope ));
125
+
126
+ public static final ClaimSetting PRINCIPAL_CLAIM = new ClaimSetting ("principal" );
127
+ public static final ClaimSetting GROUPS_CLAIM = new ClaimSetting ("groups" );
128
+ public static final ClaimSetting NAME_CLAIM = new ClaimSetting ("name" );
129
+ public static final ClaimSetting DN_CLAIM = new ClaimSetting ("dn" );
130
+ public static final ClaimSetting MAIL_CLAIM = new ClaimSetting ("mail" );
48
131
49
132
public static Set <Setting .AffixSetting <?>> getSettings () {
50
133
final Set <Setting .AffixSetting <?>> set = Sets .newHashSet (
51
- OP_NAME , RP_CLIENT_ID , RP_REDIRECT_URI , RP_RESPONSE_TYPE , RP_REQUESTED_SCOPES , RP_CLIENT_SECRET ,
52
- OP_AUTHORIZATION_ENDPOINT , OP_TOKEN_ENDPOINT , OP_USERINFO_ENDPOINT , OP_ISSUER );
134
+ RP_CLIENT_ID , RP_REDIRECT_URI , RP_RESPONSE_TYPE , RP_REQUESTED_SCOPES , RP_CLIENT_SECRET , RP_SIGNATURE_ALGORITHM ,
135
+ OP_NAME , OP_AUTHORIZATION_ENDPOINT , OP_TOKEN_ENDPOINT , OP_USERINFO_ENDPOINT , OP_ISSUER , OP_JWKSET_PATH ,
136
+ HTTP_CONNECT_TIMEOUT , HTTP_CONNECTION_READ_TIMEOUT , HTTP_SOCKET_TIMEOUT , HTTP_MAX_CONNECTIONS , HTTP_MAX_ENDPOINT_CONNECTIONS ,
137
+ ALLOWED_CLOCK_SKEW );
53
138
set .addAll (DelegatedAuthorizationSettings .getSettings (TYPE ));
54
139
set .addAll (RealmSettings .getStandardSettings (TYPE ));
140
+ set .addAll (SSLConfigurationSettings .getRealmSettings (TYPE ));
141
+ set .addAll (PRINCIPAL_CLAIM .settings ());
142
+ set .addAll (GROUPS_CLAIM .settings ());
143
+ set .addAll (DN_CLAIM .settings ());
144
+ set .addAll (NAME_CLAIM .settings ());
145
+ set .addAll (MAIL_CLAIM .settings ());
55
146
return set ;
56
147
}
148
+
149
+ /**
150
+ * The OIDC realm offers a number of settings that rely on claim values that are populated by the OP in the ID Token or the User Info
151
+ * response.
152
+ * Each claim has 2 settings:
153
+ * <ul>
154
+ * <li>The name of the OpenID Connect claim to use</li>
155
+ * <li>An optional java pattern (regex) to apply to that claim value in order to extract the substring that should be used.</li>
156
+ * </ul>
157
+ * For example, the Elasticsearch User Principal could be configured to come from the OpenID Connect standard claim "email",
158
+ * and extract only the local-part of the user's email address (i.e. the name before the '@').
159
+ * This class encapsulates those 2 settings.
160
+ */
161
+ public static final class ClaimSetting {
162
+ public static final String CLAIMS_PREFIX = "claims." ;
163
+ public static final String CLAIM_PATTERNS_PREFIX = "claim_patterns." ;
164
+
165
+ private final Setting .AffixSetting <String > claim ;
166
+ private final Setting .AffixSetting <String > pattern ;
167
+
168
+ public ClaimSetting (String name ) {
169
+ claim = RealmSettings .simpleString (TYPE , CLAIMS_PREFIX + name , Setting .Property .NodeScope );
170
+ pattern = RealmSettings .simpleString (TYPE , CLAIM_PATTERNS_PREFIX + name , Setting .Property .NodeScope );
171
+ }
172
+
173
+ public Collection <Setting .AffixSetting <?>> settings () {
174
+ return Arrays .asList (getClaim (), getPattern ());
175
+ }
176
+
177
+ public String name (RealmConfig config ) {
178
+ return getClaim ().getConcreteSettingForNamespace (config .name ()).getKey ();
179
+ }
180
+
181
+ public Setting .AffixSetting <String > getClaim () {
182
+ return claim ;
183
+ }
184
+
185
+ public Setting .AffixSetting <String > getPattern () {
186
+ return pattern ;
187
+ }
188
+ }
57
189
}
0 commit comments