[7.x] Add http proxy support for OIDC realm (#57039) (#57584)

This change introduces support for using an http proxy for egress
communication of the OpenID Connect realm.
This commit is contained in:
Ioannis Kakavas 2020-06-04 20:51:00 +03:00 committed by GitHub
parent 7a67fb2d04
commit af9f9d7f03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 212 additions and 23 deletions

View File

@ -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

View File

@ -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));

View File

@ -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;
});

View File

@ -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);
}

View File

@ -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),

View File

@ -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"

View File

@ -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;}
}
}

View File

@ -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"

View File

@ -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;
}
}
}