This change introduces support for using an http proxy for egress communication of the OpenID Connect realm.
This commit is contained in:
parent
7a67fb2d04
commit
af9f9d7f03
|
@ -1343,6 +1343,24 @@ id tokens with regards to their creation and expiration times.
|
|||
Specifies whether to populate the {es} user's metadata with the values that are
|
||||
provided by the OpenID Connect claims. Defaults to `true`.
|
||||
|
||||
`http.proxy.host`::
|
||||
Specifies the address of the proxy server that will be used by the internal
|
||||
http client for all back-channel communication to the OpenID Connect Provider
|
||||
endpoints. This includes requests to the Token Endpoint, the Userinfo Endpoint
|
||||
and requests to fetch the JSON Web Key Set from the OP if `op.jwkset_path` is
|
||||
set as a URL.
|
||||
|
||||
`http.proxy.scheme`::
|
||||
Specifies the protocol to use to connect to the proxy server that will be
|
||||
used by the http client for all back-channel communication to the OpenID
|
||||
Connect Provider endpoints. Defaults to `http`. Allowed values are
|
||||
`http` or `https`.
|
||||
|
||||
`http.proxy.port`::
|
||||
Specifies the port of the proxy server that will be used by the http
|
||||
client for all backchannel communication to the OpenID Connect Provider
|
||||
endpoints. Defaults to `80`.
|
||||
|
||||
`http.connect_timeout`::
|
||||
Controls the behavior of the http client used for back-channel communication to
|
||||
the OpenID Connect Provider endpoints. Specifies the timeout until a connection
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.core.security.authc.oidc;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
@ -19,7 +20,9 @@ import java.net.URISyntaxException;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -139,6 +142,48 @@ public class OpenIdConnectRealmSettings {
|
|||
public static final Setting.AffixSetting<Integer> HTTP_MAX_ENDPOINT_CONNECTIONS
|
||||
= Setting.affixKeySetting(RealmSettings.realmSettingPrefix(TYPE), "http.max_endpoint_connections",
|
||||
key -> Setting.intSetting(key, 200, Setting.Property.NodeScope));
|
||||
public static final Setting.AffixSetting<String> HTTP_PROXY_HOST
|
||||
= Setting.affixKeySetting(RealmSettings.realmSettingPrefix(TYPE), "http.proxy.host",
|
||||
key -> Setting.simpleString(key, new Setting.Validator<String>() {
|
||||
@Override
|
||||
public void validate(String value) {
|
||||
// There is no point in validating the hostname in itself without the scheme and port
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(String value, Map<Setting<?>, Object> settings) {
|
||||
final String namespace = HTTP_PROXY_HOST.getNamespace(HTTP_PROXY_HOST.getConcreteSetting(key));
|
||||
final Setting<Integer> portSetting = HTTP_PROXY_PORT.getConcreteSettingForNamespace(namespace);
|
||||
final Integer port = (Integer) settings.get(portSetting);
|
||||
final Setting<String> schemeSetting = HTTP_PROXY_SCHEME.getConcreteSettingForNamespace(namespace);
|
||||
final String scheme = (String) settings.get(schemeSetting);
|
||||
try {
|
||||
new HttpHost(value, port, scheme);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("HTTP host for hostname [" + value + "] (from [" + key + "])," +
|
||||
" port [" + port + "] (from [" + portSetting.getKey() + "]) and " +
|
||||
"scheme [" + scheme + "] (from ([" + schemeSetting.getKey() + "]) is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Setting<?>> settings() {
|
||||
final String namespace = HTTP_PROXY_HOST.getNamespace(HTTP_PROXY_HOST.getConcreteSetting(key));
|
||||
final List<Setting<?>> settings = Arrays.asList(HTTP_PROXY_PORT.getConcreteSettingForNamespace(namespace),
|
||||
HTTP_PROXY_SCHEME.getConcreteSettingForNamespace(namespace));
|
||||
return settings.iterator();
|
||||
}
|
||||
}, Setting.Property.NodeScope));
|
||||
public static final Setting.AffixSetting<Integer> HTTP_PROXY_PORT
|
||||
= Setting.affixKeySetting(RealmSettings.realmSettingPrefix(TYPE), "http.proxy.port",
|
||||
key -> Setting.intSetting(key, 80, 1, 65535, Setting.Property.NodeScope), () -> HTTP_PROXY_HOST);
|
||||
public static final Setting.AffixSetting<String> HTTP_PROXY_SCHEME
|
||||
= Setting.affixKeySetting(RealmSettings.realmSettingPrefix(TYPE), "http.proxy.scheme",
|
||||
key -> Setting.simpleString(key, "http", value -> {
|
||||
if (value.equals("http") == false && value.equals("https") == false) {
|
||||
throw new IllegalArgumentException("Invalid value [" + value + "] for [" + key + "]. Only `http` or `https` are allowed.");
|
||||
}
|
||||
}, Setting.Property.NodeScope));
|
||||
|
||||
public static final ClaimSetting PRINCIPAL_CLAIM = new ClaimSetting("principal");
|
||||
public static final ClaimSetting GROUPS_CLAIM = new ClaimSetting("groups");
|
||||
|
@ -151,7 +196,8 @@ public class OpenIdConnectRealmSettings {
|
|||
RP_CLIENT_ID, RP_REDIRECT_URI, RP_RESPONSE_TYPE, RP_REQUESTED_SCOPES, RP_CLIENT_SECRET, RP_SIGNATURE_ALGORITHM,
|
||||
RP_POST_LOGOUT_REDIRECT_URI, OP_AUTHORIZATION_ENDPOINT, OP_TOKEN_ENDPOINT, OP_USERINFO_ENDPOINT,
|
||||
OP_ENDSESSION_ENDPOINT, OP_ISSUER, OP_JWKSET_PATH, POPULATE_USER_METADATA, HTTP_CONNECT_TIMEOUT, HTTP_CONNECTION_READ_TIMEOUT,
|
||||
HTTP_SOCKET_TIMEOUT, HTTP_MAX_CONNECTIONS, HTTP_MAX_ENDPOINT_CONNECTIONS, ALLOWED_CLOCK_SKEW);
|
||||
HTTP_SOCKET_TIMEOUT, HTTP_MAX_CONNECTIONS, HTTP_MAX_ENDPOINT_CONNECTIONS, HTTP_PROXY_HOST, HTTP_PROXY_PORT,
|
||||
HTTP_PROXY_SCHEME, ALLOWED_CLOCK_SKEW);
|
||||
set.addAll(DelegatedAuthorizationSettings.getSettings(TYPE));
|
||||
set.addAll(RealmSettings.getStandardSettings(TYPE));
|
||||
set.addAll(SSLConfigurationSettings.getRealmSettings(TYPE));
|
||||
|
|
|
@ -42,6 +42,7 @@ import net.minidev.json.JSONObject;
|
|||
import org.apache.commons.codec.Charsets;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
|
@ -56,6 +57,7 @@ import org.apache.http.config.RegistryBuilder;
|
|||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.impl.auth.BasicScheme;
|
||||
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClients;
|
||||
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
|
||||
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
|
||||
|
@ -112,6 +114,9 @@ import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectReal
|
|||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_CONNECT_TIMEOUT;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_MAX_CONNECTIONS;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_MAX_ENDPOINT_CONNECTIONS;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_PROXY_HOST;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_PROXY_PORT;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_PROXY_SCHEME;
|
||||
import static org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings.HTTP_SOCKET_TIMEOUT;
|
||||
|
||||
/**
|
||||
|
@ -579,10 +584,14 @@ public class OpenIdConnectAuthenticator {
|
|||
.setConnectTimeout(Math.toIntExact(realmConfig.getSetting(HTTP_CONNECT_TIMEOUT).getMillis()))
|
||||
.setConnectionRequestTimeout(Math.toIntExact(realmConfig.getSetting(HTTP_CONNECTION_READ_TIMEOUT).getSeconds()))
|
||||
.setSocketTimeout(Math.toIntExact(realmConfig.getSetting(HTTP_SOCKET_TIMEOUT).getMillis())).build();
|
||||
CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
|
||||
HttpAsyncClientBuilder httpAsyncClientBuilder = HttpAsyncClients.custom()
|
||||
.setConnectionManager(connectionManager)
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
.build();
|
||||
.setDefaultRequestConfig(requestConfig);
|
||||
if (realmConfig.hasSetting(HTTP_PROXY_HOST)) {
|
||||
httpAsyncClientBuilder.setProxy(new HttpHost(realmConfig.getSetting(HTTP_PROXY_HOST),
|
||||
realmConfig.getSetting(HTTP_PROXY_PORT), realmConfig.getSetting(HTTP_PROXY_SCHEME)));
|
||||
}
|
||||
CloseableHttpAsyncClient httpAsyncClient = httpAsyncClientBuilder.build();
|
||||
httpAsyncClient.start();
|
||||
return httpAsyncClient;
|
||||
});
|
||||
|
|
|
@ -262,9 +262,9 @@ public class OpenIdConnectRealm extends Realm implements Releasable {
|
|||
}
|
||||
final ResponseType responseType;
|
||||
try {
|
||||
// This should never happen as it's already validated in the settings
|
||||
responseType = ResponseType.parse(require(config, RP_RESPONSE_TYPE));
|
||||
} catch (ParseException e) {
|
||||
// This should never happen as it's already validated in the settings
|
||||
throw new SettingsException("Invalid value for " + RP_RESPONSE_TYPE.getKey(), e);
|
||||
}
|
||||
|
||||
|
|
|
@ -263,6 +263,69 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_SECRET)));
|
||||
}
|
||||
|
||||
public void testInvalidProxySchemeThrowsError() {
|
||||
final Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_JWKSET_PATH), "https://op.example.com/jwks.json")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_HOST), "proxyhostname.org")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_SCHEME), "invalid");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
buildConfig(settingsBuilder.build()).getSetting(OpenIdConnectRealmSettings.HTTP_PROXY_SCHEME);
|
||||
});
|
||||
assertThat(exception.getMessage(),
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_SCHEME)));
|
||||
}
|
||||
|
||||
public void testInvalidProxyPortThrowsError() {
|
||||
final Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_JWKSET_PATH), "https://op.example.com/jwks.json")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_HOST), "proxyhostname.org")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_PORT), 123456);
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
buildConfig(settingsBuilder.build()).getSetting(OpenIdConnectRealmSettings.HTTP_PROXY_PORT);
|
||||
});
|
||||
assertThat(exception.getMessage(),
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_PORT)));
|
||||
}
|
||||
|
||||
public void testInvalidProxyHostThrowsError() {
|
||||
final Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_JWKSET_PATH), "https://op.example.com/jwks.json")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_HOST), "proxy hostname.org")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_PORT), 8080);
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
buildConfig(settingsBuilder.build()).getSetting(OpenIdConnectRealmSettings.HTTP_PROXY_HOST);
|
||||
});
|
||||
assertThat(exception.getMessage(), Matchers.allOf(
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_HOST)),
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_PORT)),
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.HTTP_PROXY_SCHEME))
|
||||
));
|
||||
}
|
||||
|
||||
private MockSecureSettings getSecureSettings() {
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_SECRET),
|
||||
|
|
|
@ -12,13 +12,15 @@ dependencies {
|
|||
}
|
||||
testFixtures.useFixture ":x-pack:test:idp-fixture", "oidc-provider"
|
||||
|
||||
String ephemeralPort;
|
||||
String ephemeralOpPort
|
||||
String ephemeralProxyPort
|
||||
task setupPorts {
|
||||
// Don't attempt to get ephemeral ports when Docker is not available
|
||||
onlyIf { idpFixtureProject.postProcessFixture.state.skipped == false }
|
||||
dependsOn idpFixtureProject.postProcessFixture
|
||||
doLast {
|
||||
ephemeralPort = idpFixtureProject.postProcessFixture.ext."test.fixtures.oidc-provider.tcp.8080"
|
||||
ephemeralOpPort = idpFixtureProject.postProcessFixture.ext."test.fixtures.oidc-provider.tcp.8080"
|
||||
ephemeralProxyPort = idpFixtureProject.postProcessFixture.ext."test.fixtures.http-proxy.tcp.8888"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +39,9 @@ testClusters.integTest {
|
|||
// OpenID Connect Realm 1 configured for authorization grant flow
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.order', '2'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.issuer', 'http://localhost:8080'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.authorization_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id-login" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.token_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id/token" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id/userinfo" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.authorization_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id-login" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.token_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/token" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/userinfo" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.op.jwkset_path', 'op-jwks.json'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.rp.redirect_uri', 'https://my.fantastic.rp/cb'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id.rp.client_id', 'https://my.elasticsearch.org/rp'
|
||||
|
@ -52,9 +54,9 @@ testClusters.integTest {
|
|||
// OpenID Connect Realm 2 configured for implicit flow
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.order', '3'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.issuer', 'http://localhost:8080'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.authorization_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id-login" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.token_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id/token" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id/userinfo" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.authorization_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id-login" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.token_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/token" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/userinfo" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.jwkset_path', 'op-jwks.json'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.redirect_uri', 'https://my.fantastic.rp/cb'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.client_id', 'elasticsearch-rp'
|
||||
|
@ -64,8 +66,24 @@ testClusters.integTest {
|
|||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.name', 'name'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.mail', 'email'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.groups', 'groups'
|
||||
// OpenID Connect Realm 3 configured to use a proxy
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.order', '4'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.op.issuer', 'http://localhost:8080'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.op.authorization_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id-login" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.op.token_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/token" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralOpPort}/c2id/userinfo" }
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.op.jwkset_path', 'op-jwks.json'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.rp.redirect_uri', 'https://my.fantastic.rp/cb'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.rp.client_id', 'https://my.elasticsearch.org/rp'
|
||||
keystore 'xpack.security.authc.realms.oidc.c2id-proxy.rp.client_secret', 'b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.rp.response_type', 'code'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.claims.principal', 'sub'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.claims.name', 'name'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.claims.mail', 'email'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.claims.groups', 'groups'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.http.proxy.host', '127.0.0.1'
|
||||
setting 'xpack.security.authc.realms.oidc.c2id-proxy.http.proxy.port', {"${ephemeralProxyPort}"}
|
||||
setting 'xpack.ml.enabled', 'false'
|
||||
|
||||
extraConfigFile 'op-jwks.json', idpFixtureProject.file("oidc/op-jwks.json")
|
||||
|
||||
user username: "test_admin", password: "x-pack-test-password"
|
||||
|
|
|
@ -64,6 +64,7 @@ public class OpenIdConnectAuthIT extends ESRestTestCase {
|
|||
|
||||
private static final String REALM_NAME = "c2id";
|
||||
private static final String REALM_NAME_IMPLICIT = "c2id-implicit";
|
||||
private static final String REALM_NAME_PROXY = "c2id-proxy";
|
||||
private static final String FACILITATOR_PASSWORD = "f@cilit@t0r";
|
||||
private static final String REGISTRATION_URL = "http://127.0.0.1:" + getEphemeralPortFromProperty("8080") + "/c2id/clients";
|
||||
private static final String LOGIN_API = "http://127.0.0.1:" + getEphemeralPortFromProperty("8080") + "/c2id-login/api/";
|
||||
|
@ -244,22 +245,29 @@ public class OpenIdConnectAuthIT extends ESRestTestCase {
|
|||
public void testAuthenticateWithCodeFlow() throws Exception {
|
||||
final PrepareAuthResponse prepareAuthResponse = getRedirectedFromFacilitator(REALM_NAME);
|
||||
final String redirectUri = authenticateAtOP(prepareAuthResponse.getAuthUri());
|
||||
final String realm = randomBoolean() ? null : prepareAuthResponse.getRealm();
|
||||
Tuple<String, String> tokens = completeAuthentication(redirectUri, prepareAuthResponse.getState(),
|
||||
prepareAuthResponse.getNonce(), realm);
|
||||
prepareAuthResponse.getNonce(), REALM_NAME);
|
||||
verifyElasticsearchAccessTokenForCodeFlow(tokens.v1());
|
||||
}
|
||||
|
||||
public void testAuthenticateWithImplicitFlow() throws Exception {
|
||||
final PrepareAuthResponse prepareAuthResponse = getRedirectedFromFacilitator(REALM_NAME_IMPLICIT);
|
||||
final String redirectUri = authenticateAtOP(prepareAuthResponse.getAuthUri());
|
||||
final String realm = randomBoolean() ? null : prepareAuthResponse.getRealm();
|
||||
|
||||
Tuple<String, String> tokens = completeAuthentication(redirectUri, prepareAuthResponse.getState(),
|
||||
prepareAuthResponse.getNonce(), realm);
|
||||
prepareAuthResponse.getNonce(), REALM_NAME_IMPLICIT);
|
||||
verifyElasticsearchAccessTokenForImplicitFlow(tokens.v1());
|
||||
}
|
||||
|
||||
public void testAuthenticateWithCodeFlowUsingHttpProxy() throws Exception {
|
||||
final PrepareAuthResponse prepareAuthResponse = getRedirectedFromFacilitator(REALM_NAME_PROXY);
|
||||
final String redirectUri = authenticateAtOP(prepareAuthResponse.getAuthUri());
|
||||
|
||||
Tuple<String, String> tokens = completeAuthentication(redirectUri, prepareAuthResponse.getState(),
|
||||
prepareAuthResponse.getNonce(), REALM_NAME_PROXY);
|
||||
verifyElasticsearchAccessTokenForCodeFlow(tokens.v1());
|
||||
}
|
||||
|
||||
public void testAuthenticateWithCodeFlowFailsForWrongRealm() throws Exception {
|
||||
final PrepareAuthResponse prepareAuthResponse = getRedirectedFromFacilitator(REALM_NAME);
|
||||
final String redirectUri = authenticateAtOP(prepareAuthResponse.getAuthUri());
|
||||
|
@ -377,7 +385,10 @@ public class OpenIdConnectAuthIT extends ESRestTestCase {
|
|||
createRoleMappingRequest.setJsonEntity("{ \"roles\" : [\"kibana_admin\"]," +
|
||||
"\"enabled\": true," +
|
||||
"\"rules\": {" +
|
||||
"\"field\": { \"realm.name\": \"" + REALM_NAME + "\"}" +
|
||||
" \"any\" : [" +
|
||||
" {\"field\": { \"realm.name\": \"" + REALM_NAME + "\"} }," +
|
||||
" {\"field\": { \"realm.name\": \"" + REALM_NAME_PROXY + "\"} }" +
|
||||
" ]" +
|
||||
"}" +
|
||||
"}");
|
||||
adminClient().performRequest(createRoleMappingRequest);
|
||||
|
@ -409,13 +420,11 @@ public class OpenIdConnectAuthIT extends ESRestTestCase {
|
|||
private URI authUri;
|
||||
private String state;
|
||||
private String nonce;
|
||||
private String realm;
|
||||
|
||||
PrepareAuthResponse(URI authUri, String state, String nonce, @Nullable String realm) {
|
||||
this.authUri = authUri;
|
||||
this.state = state;
|
||||
this.nonce = nonce;
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
URI getAuthUri() {
|
||||
|
@ -430,6 +439,5 @@ public class OpenIdConnectAuthIT extends ESRestTestCase {
|
|||
return nonce;
|
||||
}
|
||||
|
||||
String getRealm() { return realm;}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,16 @@ services:
|
|||
|
||||
oidc-provider:
|
||||
image: "c2id/c2id-server:7.8"
|
||||
depends_on:
|
||||
- http-proxy
|
||||
ports:
|
||||
- "8080"
|
||||
volumes:
|
||||
- ./oidc/override.properties:/etc/c2id/override.properties
|
||||
- ./oidc/override.properties:/etc/c2id/override.properties
|
||||
|
||||
http-proxy:
|
||||
image: "nginx:latest"
|
||||
volumes:
|
||||
- ./oidc/nginx.conf:/etc/nginx/nginx.conf
|
||||
ports:
|
||||
- "8888"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
worker_processes 1;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
http {
|
||||
server {
|
||||
# Acts as a simple forward http proxy for the OIDC realm configuration
|
||||
listen 8888;
|
||||
location / {
|
||||
# oidc-provider is another container so we need to rewrite `127.0.0.1:ephemeralPort` with `oidc-provider:8080`
|
||||
# so that nginx can access that
|
||||
resolver 127.0.0.11;
|
||||
set $ophost "oidc-provider:8080";
|
||||
proxy_pass http://$ophost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue