|
@@ -13,9 +13,12 @@ import com.unboundid.ldap.sdk.SearchScope;
|
|
|
|
|
|
import org.apache.logging.log4j.Logger;
|
|
|
import org.elasticsearch.action.ActionListener;
|
|
|
+import org.elasticsearch.common.Strings;
|
|
|
+import org.elasticsearch.core.Nullable;
|
|
|
import org.elasticsearch.core.TimeValue;
|
|
|
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
|
|
|
import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapMetadataResolverSettings;
|
|
|
+import org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySIDUtil;
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collection;
|
|
@@ -24,6 +27,7 @@ import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
|
|
|
import static org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySIDUtil.TOKEN_GROUPS;
|
|
|
import static org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySIDUtil.convertToString;
|
|
@@ -31,17 +35,36 @@ import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.OBJE
|
|
|
import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.searchForEntry;
|
|
|
|
|
|
public class LdapMetadataResolver {
|
|
|
-
|
|
|
private final String[] attributeNames;
|
|
|
private final boolean ignoreReferralErrors;
|
|
|
+ private final String fullNameAttributeName;
|
|
|
+ private final String emailAttributeName;
|
|
|
+ private final String[] allAttributeNamesToResolve;
|
|
|
|
|
|
public LdapMetadataResolver(RealmConfig realmConfig, boolean ignoreReferralErrors) {
|
|
|
- this(realmConfig.getSetting(LdapMetadataResolverSettings.ADDITIONAL_METADATA_SETTING), ignoreReferralErrors);
|
|
|
+ this(
|
|
|
+ realmConfig.getSetting(LdapMetadataResolverSettings.FULL_NAME_SETTING),
|
|
|
+ realmConfig.getSetting(LdapMetadataResolverSettings.EMAIL_SETTING),
|
|
|
+ realmConfig.getSetting(LdapMetadataResolverSettings.ADDITIONAL_METADATA_SETTING),
|
|
|
+ ignoreReferralErrors
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
- LdapMetadataResolver(Collection<String> attributeNames, boolean ignoreReferralErrors) {
|
|
|
+ LdapMetadataResolver(
|
|
|
+ String fullNameAttributeName,
|
|
|
+ String emailAttributeName,
|
|
|
+ Collection<String> attributeNames,
|
|
|
+ boolean ignoreReferralErrors
|
|
|
+ ) {
|
|
|
+ this.fullNameAttributeName = fullNameAttributeName;
|
|
|
+ this.emailAttributeName = emailAttributeName;
|
|
|
this.attributeNames = attributeNames.toArray(new String[attributeNames.size()]);
|
|
|
this.ignoreReferralErrors = ignoreReferralErrors;
|
|
|
+ this.allAttributeNamesToResolve = Stream.concat(
|
|
|
+ Stream.of(this.attributeNames),
|
|
|
+ Stream.of(this.fullNameAttributeName, this.emailAttributeName)
|
|
|
+ ).distinct().toArray(String[]::new);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public String[] attributeNames() {
|
|
@@ -54,12 +77,12 @@ public class LdapMetadataResolver {
|
|
|
TimeValue timeout,
|
|
|
Logger logger,
|
|
|
Collection<Attribute> attributes,
|
|
|
- ActionListener<Map<String, Object>> listener
|
|
|
+ ActionListener<LdapMetadataResult> listener
|
|
|
) {
|
|
|
- if (this.attributeNames.length == 0) {
|
|
|
- listener.onResponse(Map.of());
|
|
|
+ if (Strings.isEmpty(this.fullNameAttributeName) && Strings.isEmpty(this.emailAttributeName) && this.attributeNames.length == 0) {
|
|
|
+ listener.onResponse(LdapMetadataResult.EMPTY);
|
|
|
} else if (attributes != null) {
|
|
|
- listener.onResponse(toMap(name -> findAttribute(attributes, name)));
|
|
|
+ listener.onResponse(toLdapMetadataResult(name -> findAttribute(attributes, name)));
|
|
|
} else {
|
|
|
searchForEntry(
|
|
|
connection,
|
|
@@ -70,12 +93,12 @@ public class LdapMetadataResolver {
|
|
|
ignoreReferralErrors,
|
|
|
ActionListener.wrap((SearchResultEntry entry) -> {
|
|
|
if (entry == null) {
|
|
|
- listener.onResponse(Map.of());
|
|
|
+ listener.onResponse(LdapMetadataResult.EMPTY);
|
|
|
} else {
|
|
|
- listener.onResponse(toMap(entry::getAttribute));
|
|
|
+ listener.onResponse(toLdapMetadataResult(entry::getAttribute));
|
|
|
}
|
|
|
}, listener::onFailure),
|
|
|
- this.attributeNames
|
|
|
+ allAttributeNamesToResolve
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -84,21 +107,59 @@ public class LdapMetadataResolver {
|
|
|
return attributes.stream().filter(attr -> attr.getName().equals(name)).findFirst().orElse(null);
|
|
|
}
|
|
|
|
|
|
- private Map<String, Object> toMap(Function<String, Attribute> attributes) {
|
|
|
- return Arrays.stream(this.attributeNames)
|
|
|
+ public static class LdapMetadataResult {
|
|
|
+
|
|
|
+ public static LdapMetadataResult EMPTY = new LdapMetadataResult(null, null, Map.of());
|
|
|
+
|
|
|
+ private final String fullName;
|
|
|
+ private final String email;
|
|
|
+ private final Map<String, Object> metaData;
|
|
|
+
|
|
|
+ public LdapMetadataResult(@Nullable String fullName, @Nullable String email, Map<String, Object> metaData) {
|
|
|
+ this.fullName = fullName;
|
|
|
+ this.email = email;
|
|
|
+ this.metaData = metaData;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Nullable
|
|
|
+ public String getFullName() {
|
|
|
+ return fullName;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Nullable
|
|
|
+ public String getEmail() {
|
|
|
+ return email;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Object> getMetaData() {
|
|
|
+ return metaData;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Object parseLdapAttributeValue(Attribute attr) {
|
|
|
+ final String[] values = attr.getValues();
|
|
|
+ if (attr.getName().equals(TOKEN_GROUPS)) {
|
|
|
+ return values.length == 1
|
|
|
+ ? convertToString(attr.getValueByteArrays()[0])
|
|
|
+ : Arrays.stream(attr.getValueByteArrays()).map(ActiveDirectorySIDUtil::convertToString).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ return values.length == 1 ? values[0] : List.of(values);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private LdapMetadataResult toLdapMetadataResult(Function<String, Attribute> attributes) {
|
|
|
+ Attribute emailAttribute = attributes.apply(this.emailAttributeName);
|
|
|
+ Attribute fullNameAttribute = attributes.apply(this.fullNameAttributeName);
|
|
|
+
|
|
|
+ Map<String, Object> metaData = Arrays.stream(this.attributeNames)
|
|
|
.map(attributes)
|
|
|
.filter(Objects::nonNull)
|
|
|
- .collect(Collectors.toUnmodifiableMap(attr -> attr.getName(), attr -> {
|
|
|
- final String[] values = attr.getValues();
|
|
|
- if (attr.getName().equals(TOKEN_GROUPS)) {
|
|
|
- return values.length == 1
|
|
|
- ? convertToString(attr.getValueByteArrays()[0])
|
|
|
- : Arrays.stream(attr.getValueByteArrays())
|
|
|
- .map((sidBytes) -> convertToString(sidBytes))
|
|
|
- .collect(Collectors.toList());
|
|
|
- }
|
|
|
- return values.length == 1 ? values[0] : List.of(values);
|
|
|
- }));
|
|
|
- }
|
|
|
+ .collect(Collectors.toUnmodifiableMap(Attribute::getName, LdapMetadataResolver::parseLdapAttributeValue));
|
|
|
|
|
|
+ return new LdapMetadataResult(
|
|
|
+ fullNameAttribute == null ? null : LdapMetadataResolver.parseLdapAttributeValue(fullNameAttribute).toString(),
|
|
|
+ emailAttribute == null ? null : LdapMetadataResolver.parseLdapAttributeValue(emailAttribute).toString(),
|
|
|
+ metaData
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|