77
88import org .elasticsearch .common .settings .SecureString ;
99import org .elasticsearch .common .settings .Setting ;
10+ import org .elasticsearch .common .unit .TimeValue ;
1011import org .elasticsearch .common .util .set .Sets ;
12+ import org .elasticsearch .xpack .core .security .authc .RealmConfig ;
1113import org .elasticsearch .xpack .core .security .authc .RealmSettings ;
1214import org .elasticsearch .xpack .core .security .authc .support .DelegatedAuthorizationSettings ;
15+ import org .elasticsearch .xpack .core .ssl .SSLConfigurationSettings ;
1316
1417import java .net .URI ;
1518import java .net .URISyntaxException ;
19+ import java .util .Arrays ;
20+ import java .util .Collection ;
1621import java .util .Collections ;
1722import java .util .List ;
1823import java .util .Set ;
@@ -24,25 +29,64 @@ public class OpenIdConnectRealmSettings {
2429 private OpenIdConnectRealmSettings () {
2530 }
2631
32+ private static final List <String > signingAlgorithms = 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" );
2735 public static final String TYPE = "oidc" ;
2836
29- public static final Setting .AffixSetting <String > OP_NAME
30- = RealmSettings .simpleString (TYPE , "op.name" , Setting .Property .NodeScope );
3137 public static final Setting .AffixSetting <String > RP_CLIENT_ID
3238 = RealmSettings .simpleString (TYPE , "rp.client_id" , Setting .Property .NodeScope );
3339 public static final Setting .AffixSetting <SecureString > RP_CLIENT_SECRET
3440 = RealmSettings .secureString (TYPE , "rp.client_secret" );
3541 public static final Setting .AffixSetting <String > RP_REDIRECT_URI
36- = 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 ));
3750 public static final Setting .AffixSetting <String > RP_RESPONSE_TYPE
38- = 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_VERIFICATION_ALGORITHM
58+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "rp.signature_verification_algorithm" ,
59+ key -> new Setting <>(key , "RS256" , Function .identity (), v -> {
60+ if (signingAlgorithms .contains (v ) == false ) {
61+ throw new IllegalArgumentException (
62+ "Invalid value [" + v + "] for [" + key + "]. Allowed values are " + signingAlgorithms + "}]" );
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 );
3971 public static final Setting .AffixSetting <String > OP_AUTHORIZATION_ENDPOINT
40- = 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 ));
4180 public static final Setting .AffixSetting <String > OP_TOKEN_ENDPOINT
42- = 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 ));
4389 public static final Setting .AffixSetting <String > OP_USERINFO_ENDPOINT
44- = RealmSettings .simpleString (TYPE , "op.userinfo_endpoint" , Setting .Property .NodeScope );
45- public static final Setting .AffixSetting <String > OP_ENDSESSION_ENDPOINT
4690 = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "op.userinfo_endpoint" ,
4791 key -> Setting .simpleString (key , v -> {
4892 try {
@@ -51,18 +95,105 @@ private OpenIdConnectRealmSettings() {
5195 throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
5296 }
5397 }, Setting .Property .NodeScope ));
98+ public static final Setting .AffixSetting <String > OP_ENDSESSION_ENDPOINT
99+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "op.endsession_endpoint" ,
100+ key -> Setting .simpleString (key , v -> {
101+ try {
102+ new URI (v );
103+ } catch (URISyntaxException e ) {
104+ throw new IllegalArgumentException ("Invalid value [" + v + "] for [" + key + "]. Not a valid URI." , e );
105+ }
106+ }, Setting .Property .NodeScope ));
54107 public static final Setting .AffixSetting <String > OP_ISSUER
55108 = RealmSettings .simpleString (TYPE , "op.issuer" , Setting .Property .NodeScope );
56- public static final Setting .AffixSetting <List <String >> RP_REQUESTED_SCOPES = Setting .affixKeySetting (
57- RealmSettings .realmSettingPrefix (TYPE ), "rp.requested_scopes" ,
58- key -> Setting .listSetting (key , Collections .singletonList ("openid" ), Function .identity (), Setting .Property .NodeScope ));
109+ public static final Setting .AffixSetting <String > OP_JWKSET_PATH
110+ = RealmSettings .simpleString (TYPE , "op.jwkset_path" , Setting .Property .NodeScope );
111+
112+ public static final Setting .AffixSetting <TimeValue > ALLOWED_CLOCK_SKEW
113+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "allowed_clock_skew" ,
114+ key -> Setting .timeSetting (key , TimeValue .timeValueSeconds (60 ), Setting .Property .NodeScope ));
115+ public static final Setting .AffixSetting <Boolean > POPULATE_USER_METADATA = Setting .affixKeySetting (
116+ RealmSettings .realmSettingPrefix (TYPE ), "populate_user_metadata" ,
117+ key -> Setting .boolSetting (key , true , Setting .Property .NodeScope ));
118+ private static final TimeValue DEFAULT_TIMEOUT = TimeValue .timeValueSeconds (5 );
119+ public static final Setting .AffixSetting <TimeValue > HTTP_CONNECT_TIMEOUT
120+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.connect_timeout" ,
121+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
122+ public static final Setting .AffixSetting <TimeValue > HTTP_CONNECTION_READ_TIMEOUT
123+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.connection_read_timeout" ,
124+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
125+ public static final Setting .AffixSetting <TimeValue > HTTP_SOCKET_TIMEOUT
126+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.socket_timeout" ,
127+ key -> Setting .timeSetting (key , DEFAULT_TIMEOUT , Setting .Property .NodeScope ));
128+ public static final Setting .AffixSetting <Integer > HTTP_MAX_CONNECTIONS
129+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.max_connections" ,
130+ key -> Setting .intSetting (key , 200 , Setting .Property .NodeScope ));
131+ public static final Setting .AffixSetting <Integer > HTTP_MAX_ENDPOINT_CONNECTIONS
132+ = Setting .affixKeySetting (RealmSettings .realmSettingPrefix (TYPE ), "http.max_endpoint_connections" ,
133+ key -> Setting .intSetting (key , 200 , Setting .Property .NodeScope ));
134+
135+ public static final ClaimSetting PRINCIPAL_CLAIM = new ClaimSetting ("principal" );
136+ public static final ClaimSetting GROUPS_CLAIM = new ClaimSetting ("groups" );
137+ public static final ClaimSetting NAME_CLAIM = new ClaimSetting ("name" );
138+ public static final ClaimSetting DN_CLAIM = new ClaimSetting ("dn" );
139+ public static final ClaimSetting MAIL_CLAIM = new ClaimSetting ("mail" );
59140
60141 public static Set <Setting .AffixSetting <?>> getSettings () {
61142 final Set <Setting .AffixSetting <?>> set = Sets .newHashSet (
62- OP_NAME , RP_CLIENT_ID , RP_REDIRECT_URI , RP_RESPONSE_TYPE , RP_REQUESTED_SCOPES , RP_CLIENT_SECRET ,
63- OP_AUTHORIZATION_ENDPOINT , OP_TOKEN_ENDPOINT , OP_USERINFO_ENDPOINT , OP_ISSUER );
143+ RP_CLIENT_ID , RP_REDIRECT_URI , RP_RESPONSE_TYPE , RP_REQUESTED_SCOPES , RP_CLIENT_SECRET , RP_SIGNATURE_VERIFICATION_ALGORITHM ,
144+ OP_NAME , OP_AUTHORIZATION_ENDPOINT , OP_TOKEN_ENDPOINT , OP_USERINFO_ENDPOINT , OP_ENDSESSION_ENDPOINT , OP_ISSUER ,
145+ OP_JWKSET_PATH , HTTP_CONNECT_TIMEOUT , HTTP_CONNECTION_READ_TIMEOUT , HTTP_SOCKET_TIMEOUT , HTTP_MAX_CONNECTIONS ,
146+ HTTP_MAX_ENDPOINT_CONNECTIONS , ALLOWED_CLOCK_SKEW );
64147 set .addAll (DelegatedAuthorizationSettings .getSettings (TYPE ));
65148 set .addAll (RealmSettings .getStandardSettings (TYPE ));
149+ set .addAll (SSLConfigurationSettings .getRealmSettings (TYPE ));
150+ set .addAll (PRINCIPAL_CLAIM .settings ());
151+ set .addAll (GROUPS_CLAIM .settings ());
152+ set .addAll (DN_CLAIM .settings ());
153+ set .addAll (NAME_CLAIM .settings ());
154+ set .addAll (MAIL_CLAIM .settings ());
66155 return set ;
67156 }
157+
158+
159+ /**
160+ * 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
161+ * response.
162+ * Each claim has 2 settings:
163+ * <ul>
164+ * <li>The name of the OpenID Connect claim to use</li>
165+ * <li>An optional java pattern (regex) to apply to that claim value in order to extract the substring that should be used.</li>
166+ * </ul>
167+ * For example, the Elasticsearch User Principal could be configured to come from the OpenID Connect standard claim "email",
168+ * and extract only the local-part of the user's email address (i.e. the name before the '@').
169+ * This class encapsulates those 2 settings.
170+ */
171+ public static final class ClaimSetting {
172+ public static final String CLAIMS_PREFIX = "claims." ;
173+ public static final String CLAIM_PATTERNS_PREFIX = "claim_patterns." ;
174+
175+ private final Setting .AffixSetting <String > claim ;
176+ private final Setting .AffixSetting <String > pattern ;
177+
178+ public ClaimSetting (String name ) {
179+ claim = RealmSettings .simpleString (TYPE , CLAIMS_PREFIX + name , Setting .Property .NodeScope );
180+ pattern = RealmSettings .simpleString (TYPE , CLAIM_PATTERNS_PREFIX + name , Setting .Property .NodeScope );
181+ }
182+
183+ public Collection <Setting .AffixSetting <?>> settings () {
184+ return Arrays .asList (getClaim (), getPattern ());
185+ }
186+
187+ public String name (RealmConfig config ) {
188+ return getClaim ().getConcreteSettingForNamespace (config .name ()).getKey ();
189+ }
190+
191+ public Setting .AffixSetting <String > getClaim () {
192+ return claim ;
193+ }
194+
195+ public Setting .AffixSetting <String > getPattern () {
196+ return pattern ;
197+ }
198+ }
68199}
0 commit comments