Fail early when rp.client_secret is missing in OIDC realm (#42256)
rp.client_secret is a required secure setting. Make sure we fail with a SettingsException and a clear, actionable message when building the realm, if the setting is missing.
This commit is contained in:
parent
ccdc0e6b3e
commit
aab97f1311
|
@ -247,6 +247,10 @@ public class OpenIdConnectRealm extends Realm implements Releasable {
|
|||
}
|
||||
final ClientID clientId = new ClientID(require(config, RP_CLIENT_ID));
|
||||
final SecureString clientSecret = config.getSetting(RP_CLIENT_SECRET);
|
||||
if (clientSecret.length() == 0) {
|
||||
throw new SettingsException("The configuration setting [" + RealmSettings.getFullSettingKey(config, RP_CLIENT_SECRET)
|
||||
+ "] is required");
|
||||
}
|
||||
final ResponseType responseType;
|
||||
try {
|
||||
// This should never happen as it's already validated in the settings
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.authc;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateAction;
|
||||
|
@ -52,8 +53,12 @@ public class SecurityRealmSettingsTests extends SecurityIntegTestCase {
|
|||
final Path jwkSet = createTempFile("jwkset", "json");
|
||||
OpenIdConnectTestCase.writeJwkSetToFile(jwkSet);
|
||||
|
||||
final Settings existingSettings = super.nodeSettings(nodeOrdinal);
|
||||
MockSecureSettings mockSecureSettings =
|
||||
(MockSecureSettings) Settings.builder().put(existingSettings).getSecureSettings();
|
||||
mockSecureSettings.setString("xpack.security.authc.realms.oidc.oidc1.rp.client_secret", randomAlphaOfLength(12));
|
||||
settings = Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal).filter(s -> s.startsWith("xpack.security.authc.realms.") == false))
|
||||
.put(existingSettings.filter(s -> s.startsWith("xpack.security.authc.realms.") == false), false)
|
||||
.put("xpack.security.authc.token.enabled", true)
|
||||
.put("xpack.security.authc.realms.file.file1.order", 1)
|
||||
.put("xpack.security.authc.realms.native.native1.order", 2)
|
||||
|
@ -80,6 +85,7 @@ public class SecurityRealmSettingsTests extends SecurityIntegTestCase {
|
|||
.put("xpack.security.authc.realms.oidc.oidc1.rp.client_id", "my_client")
|
||||
.put("xpack.security.authc.realms.oidc.oidc1.rp.response_type", "code")
|
||||
.put("xpack.security.authc.realms.oidc.oidc1.claims.principal", "sub")
|
||||
.setSecureSettings(mockSecureSettings)
|
||||
.build();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.xpack.security.authc.oidc;
|
||||
|
||||
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
@ -42,6 +43,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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), "hybrid");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -58,6 +60,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -75,6 +78,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -91,6 +95,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -108,6 +113,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -123,6 +129,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -139,6 +146,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -155,6 +163,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -171,6 +180,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.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_RESPONSE_TYPE), "code");
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -189,6 +199,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.putList(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REQUESTED_SCOPES),
|
||||
Arrays.asList("openid", "scope1", "scope2"));
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -209,6 +220,7 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.putList(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REQUESTED_SCOPES),
|
||||
Arrays.asList("openid", "scope1", "scope2"));
|
||||
settingsBuilder.setSecureSettings(getSecureSettings());
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
|
@ -218,6 +230,30 @@ public class OpenIdConnectRealmSettingsTests extends ESTestCase {
|
|||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.NAME_CLAIM.getPattern())));
|
||||
}
|
||||
|
||||
public void testMissingClientSecretThrowsError() {
|
||||
final Settings.Builder settingsBuilder = Settings.builder()
|
||||
.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.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
|
||||
.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");
|
||||
SettingsException exception = expectThrows(SettingsException.class, () -> {
|
||||
new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
|
||||
});
|
||||
assertThat(exception.getMessage(),
|
||||
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_SECRET)));
|
||||
}
|
||||
|
||||
private MockSecureSettings getSecureSettings() {
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_SECRET),
|
||||
randomAlphaOfLengthBetween(12, 18));
|
||||
return secureSettings;
|
||||
}
|
||||
|
||||
private RealmConfig buildConfig(Settings realmSettings) {
|
||||
final Settings settings = Settings.builder()
|
||||
.put("path.home", createTempDir())
|
||||
|
|
|
@ -165,7 +165,8 @@ public class OpenIdConnectRealmTests extends OpenIdConnectTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.putList(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REQUESTED_SCOPES),
|
||||
Arrays.asList("scope1", "scope2"));
|
||||
Arrays.asList("scope1", "scope2"))
|
||||
.setSecureSettings(getSecureSettings());
|
||||
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build(), threadContext), null,
|
||||
null);
|
||||
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
|
||||
|
@ -187,7 +188,8 @@ public class OpenIdConnectRealmTests extends OpenIdConnectTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.putList(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REQUESTED_SCOPES),
|
||||
Arrays.asList("openid", "scope1", "scope2"));
|
||||
Arrays.asList("openid", "scope1", "scope2"))
|
||||
.setSecureSettings(getSecureSettings());
|
||||
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build(), threadContext), null,
|
||||
null);
|
||||
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
|
||||
|
@ -207,7 +209,9 @@ public class OpenIdConnectRealmTests extends OpenIdConnectTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com/cb")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.setSecureSettings(getSecureSettings());
|
||||
;
|
||||
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build(), threadContext), null,
|
||||
null);
|
||||
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
|
||||
|
@ -237,7 +241,9 @@ public class OpenIdConnectRealmTests extends OpenIdConnectTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com/cb")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.setSecureSettings(getSecureSettings());
|
||||
;
|
||||
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build(), threadContext), null,
|
||||
null);
|
||||
final String state = new State().getValue();
|
||||
|
@ -257,7 +263,9 @@ public class OpenIdConnectRealmTests extends OpenIdConnectTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com/cb")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code")
|
||||
.setSecureSettings(getSecureSettings());
|
||||
;
|
||||
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build(), threadContext), null,
|
||||
null);
|
||||
final String state = new State().getValue();
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.nimbusds.jwt.JWT;
|
|||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import com.nimbusds.jwt.SignedJWT;
|
||||
import com.nimbusds.openid.connect.sdk.Nonce;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
|
@ -50,7 +51,15 @@ public abstract class OpenIdConnectTestCase extends ESTestCase {
|
|||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.GROUPS_CLAIM.getClaim()), "groups")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.MAIL_CLAIM.getClaim()), "mail")
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.NAME_CLAIM.getClaim()), "name");
|
||||
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.NAME_CLAIM.getClaim()), "name")
|
||||
.setSecureSettings(getSecureSettings());
|
||||
}
|
||||
|
||||
protected static MockSecureSettings getSecureSettings() {
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_SECRET),
|
||||
randomAlphaOfLengthBetween(12, 18));
|
||||
return secureSettings;
|
||||
}
|
||||
|
||||
protected JWT generateIdToken(String subject, String audience, String issuer) throws Exception {
|
||||
|
|
Loading…
Reference in New Issue