Skip to content

Commit

Permalink
Resolve user attribute names once
Browse files Browse the repository at this point in the history
  • Loading branch information
jfreden committed Nov 27, 2024
1 parent 4a3de6a commit acd4205
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ public static Set<Setting.AffixSetting<?>> getSettings(String type) {
return set;
}

public record UserAttributeNameConfiguration(String principal, String dn, String name, String mail) {
public static UserAttributeNameConfiguration fromConfig(RealmConfig config) {
return new UserAttributeNameConfiguration(
PRINCIPAL_ATTRIBUTE.apply(config.type()).name(config),
DN_ATTRIBUTE.apply(config.type()).name(config),
NAME_ATTRIBUTE.apply(config.type()).name(config),
MAIL_ATTRIBUTE.apply(config.type()).name(config)
);
}
}

/**
* The SAML realm offers a number of settings that rely on attributes that are populate by the Identity Provider in the SAML Response.
* Each attribute has 2 settings:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ public final class SamlRealm extends Realm implements Releasable {
private final Supplier<EntityDescriptor> idpDescriptor;

private final SpConfiguration serviceProvider;
private final SamlRealmSettings.UserAttributeNameConfiguration userAttributeNameConfiguration;
private final SamlAuthnRequestBuilder.NameIDPolicySettings nameIdPolicy;
private final Boolean forceAuthn;
private final boolean useSingleLogout;
Expand Down Expand Up @@ -224,6 +225,8 @@ public static SamlRealm create(
serviceProvider,
maxSkew
);
SamlRealmSettings.UserAttributeNameConfiguration userAttributeNameConfiguration = SamlRealmSettings.UserAttributeNameConfiguration
.fromConfig(config);

final SamlRealm realm = new SamlRealm(
config,
Expand All @@ -232,7 +235,8 @@ public static SamlRealm create(
logoutHandler,
logoutResponseHandler,
idpDescriptor,
serviceProvider
serviceProvider,
userAttributeNameConfiguration
);

// the metadata resolver needs to be destroyed since it runs a timer task in the background and destroying stops it!
Expand All @@ -253,7 +257,8 @@ public SpConfiguration getServiceProvider() {
SamlLogoutRequestHandler logoutHandler,
SamlLogoutResponseHandler logoutResponseHandler,
Supplier<EntityDescriptor> idpDescriptor,
SpConfiguration spConfiguration
SpConfiguration spConfiguration,
SamlRealmSettings.UserAttributeNameConfiguration userAttributeNameConfiguration
) throws Exception {
super(config);

Expand All @@ -268,6 +273,7 @@ public SpConfiguration getServiceProvider() {

this.idpDescriptor = idpDescriptor;
this.serviceProvider = spConfiguration;
this.userAttributeNameConfiguration = userAttributeNameConfiguration;

this.nameIdPolicy = new SamlAuthnRequestBuilder.NameIDPolicySettings(
config.getSetting(NAMEID_FORMAT),
Expand Down Expand Up @@ -556,11 +562,7 @@ public void authenticate(AuthenticationToken authenticationToken, ActionListener
}

private void buildUser(SamlAttributes attributes, ActionListener<AuthenticationResult<User>> baseListener) {
final String principal = resolveSingleValueAttribute(
attributes,
principalAttribute,
PRINCIPAL_ATTRIBUTE.apply(config.type()).name(config)
);
final String principal = resolveSingleValueAttribute(attributes, principalAttribute, userAttributeNameConfiguration.principal());
if (Strings.isNullOrEmpty(principal)) {
final String msg = principalAttribute
+ " not found in saml attributes"
Expand Down Expand Up @@ -606,9 +608,9 @@ private void buildUser(SamlAttributes attributes, ActionListener<AuthenticationR
final Map<String, Object> userMeta = Map.copyOf(userMetaBuilder);

final List<String> groups = groupsAttribute.getAttribute(attributes);
final String dn = resolveSingleValueAttribute(attributes, dnAttribute, DN_ATTRIBUTE.apply(config.type()).name(config));
final String name = resolveSingleValueAttribute(attributes, nameAttribute, NAME_ATTRIBUTE.apply(config.type()).name(config));
final String mail = resolveSingleValueAttribute(attributes, mailAttribute, MAIL_ATTRIBUTE.apply(config.type()).name(config));
final String dn = resolveSingleValueAttribute(attributes, dnAttribute, userAttributeNameConfiguration.dn());
final String name = resolveSingleValueAttribute(attributes, nameAttribute, userAttributeNameConfiguration.name());
final String mail = resolveSingleValueAttribute(attributes, mailAttribute, userAttributeNameConfiguration.mail());
UserRoleMapper.UserData userData = new UserRoleMapper.UserData(principal, dn, groups, userMeta, config);
logger.debug("SAML attribute mapping = [{}]", userData);
roleMapper.resolveRoles(userData, wrappedListener.delegateFailureAndWrap((l, roles) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import org.elasticsearch.core.Nullable;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings;
import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
Expand Down Expand Up @@ -56,7 +57,8 @@ public static SamlRealm buildRealm(RealmConfig realmConfig, @Nullable X509Creden
mock(SamlLogoutRequestHandler.class),
mock(SamlLogoutResponseHandler.class),
() -> idpDescriptor,
spConfiguration
spConfiguration,
mock(SamlRealmSettings.UserAttributeNameConfiguration.class)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,16 @@ public SamlRealm buildRealm(
SpConfiguration sp
) throws Exception {
try {
return new SamlRealm(config, roleMapper, authenticator, logoutHandler, mock(SamlLogoutResponseHandler.class), () -> idp, sp);
return new SamlRealm(
config,
roleMapper,
authenticator,
logoutHandler,
mock(SamlLogoutResponseHandler.class),
() -> idp,
sp,
mock(SamlRealmSettings.UserAttributeNameConfiguration.class)
);
} catch (SettingsException e) {
logger.info(() -> format("Settings are invalid:\n%s", config.settings().toDelimitedString('\n')), e);
throw e;
Expand Down

0 comments on commit acd4205

Please sign in to comment.