blob: f888908edc23ab56574cc90ee566b6d518803947 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.ldap.conf;
import com.fasterxml.jackson.annotation.JsonFormat;
import static com.fasterxml.jackson.annotation.JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.properties.GuacamoleProperty;
/**
* LDAPConfiguration implementation that is annotated for deserialization by
* Jackson.
*/
public class JacksonLDAPConfiguration implements LDAPConfiguration {
/**
* The regular expressions that match all users that should be routed to
* the LDAP server represented by this configuration.
*/
@JsonProperty("match-usernames")
@JsonFormat(with = ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<Pattern> matchUsernames;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_HOSTNAME}. If
* not set within the YAML, this will be null.
*/
@JsonProperty("hostname")
private String hostname;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_PORT}. If not
* set within the YAML, this will be null.
*/
@JsonProperty("port")
private Integer port;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_USERNAME_ATTRIBUTES}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("username-attribute")
@JsonFormat(with = ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<String> usernameAttributes;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_USER_BASE_DN}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("user-base-dn")
private String userBaseDn;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_CONFIG_BASE_DN}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("config-base-dn")
private String configBaseDn;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_GROUP_BASE_DN}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("group-base-dn")
private String groupBaseDn;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_GROUP_NAME_ATTRIBUTES}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("group-name-attribute")
@JsonFormat(with = ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<String> groupNameAttributes;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_SEARCH_BIND_DN}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("search-bind-dn")
private String searchBindDn;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_SEARCH_BIND_PASSWORD}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("search-bind-password")
private String searchBindPassword;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_ENCRYPTION_METHOD}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("encryption-method")
private String encryptionMethod;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_MAX_SEARCH_RESULTS}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("max-search-results")
private Integer maxSearchResults;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_DEREFERENCE_ALIASES}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("dereference-aliases")
private String dereferenceAliases;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_FOLLOW_REFERRALS}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("follow-referrals")
private Boolean followReferrals;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_MAX_REFERRAL_HOPS}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("max-referral-hops")
private Integer maxReferralHops;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_USER_SEARCH_FILTER}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("user-search-filter")
private String userSearchFilter;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_GROUP_SEARCH_FILTER}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("group-search-filter")
private String groupSearchFilter;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_OPERATION_TIMEOUT}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("operation-timeout")
private Integer operationTimeout;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_NETWORK_TIMEOUT}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("network-timeout")
private Integer networkTimeout;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_USER_ATTRIBUTES}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("user-attributes")
@JsonFormat(with = ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<String> userAttributes;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_MEMBER_ATTRIBUTE}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("member-attribute")
private String memberAttribute;
/**
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_MEMBER_ATTRIBUTE_TYPE}.
* If not set within the YAML, this will be null.
*/
@JsonProperty("member-attribute-type")
private String memberAttributeType;
/**
* The default configuration options for all parameters.
*/
private LDAPConfiguration defaultConfig = new DefaultLDAPConfiguration();
/**
* Supplier of default values for LDAP configurations. Unlike
* {@link java.util.function.Supplier}, the {@link #get()} function of
* DefaultSupplier may throw a {@link GuacamoleException}.
*
* @param <T>
* The type of value returned by this DefaultSupplier.
*/
@FunctionalInterface
private interface DefaultSupplier<T> {
/**
* Returns the value supplied by this DefaultSupplier. The value
* returned is not cached and may be non-deterministic.
*
* @return
* The value supplied by this DefaultSupplier.
*
* @throws GuacamoleException
* If an error occurs while producing/retrieving the value.
*/
T get() throws GuacamoleException;
}
/**
* Returns the given value, if non-null. If null, the given default value
* is returned.
*
* @param <T>
* The type of value accepted and returned.
*
* @param value
* The possibly null value to return if non-null.
*
* @param defaultValue
* A function which supplies the value to return if the provided value
* is null.
*
* @return
* The provided value, if non-null, otherwise the provided default
* value.
*
* @throws GuacamoleException
* If an error occurs while producing/retrieving the default value.
*/
private <T> T withDefault(T value, DefaultSupplier<T> defaultValue)
throws GuacamoleException {
return value != null ? value : defaultValue.get();
}
/**
* Parses and returns the given value, if non-null. If null, the given
* default value is returned.
*
* @param <T>
* The type of value accepted and returned.
*
* @param property
* The GuacamoleProperty implementation to use to parse the provided
* String value.
*
* @param value
* The possibly null value to return if non-null.
*
* @param defaultValue
* A function which supplies the value to return if the provided value
* is null.
*
* @return
* The provided value, if non-null, otherwise the provided default
* value.
*
* @throws GuacamoleException
* If an error occurs while producing/retrieving the default value.
*/
private <T> T withDefault(GuacamoleProperty<T> property, String value,
DefaultSupplier<T> defaultValue)
throws GuacamoleException {
return withDefault(property.parseValue(value), defaultValue);
}
/**
* Sets the LDAPConfiguration that should be used for the default values of
* any configuration options omitted from the YAML. If not set, an instance
* of {@link DefaultLDAPConfiguration} will be used.
*
* @param defaultConfig
* The LDAPConfiguration to use for the default values of any omitted
* configuration options.
*/
public void setDefaults(LDAPConfiguration defaultConfig) {
this.defaultConfig = defaultConfig;
}
@Override
public String appliesTo(String username) throws GuacamoleException {
// Match any user by default
if (matchUsernames == null || matchUsernames.isEmpty())
return username;
for (Pattern pattern : matchUsernames) {
Matcher matcher = pattern.matcher(username);
if (matcher.matches())
return matcher.groupCount() >= 1 ? matcher.group(1) : username;
}
return null;
}
@Override
public String getServerHostname() throws GuacamoleException {
return withDefault(hostname, defaultConfig::getServerHostname);
}
@Override
public int getServerPort() throws GuacamoleException {
return withDefault(port, () -> getEncryptionMethod().DEFAULT_PORT);
}
@Override
public List<String> getUsernameAttributes() throws GuacamoleException {
return withDefault(usernameAttributes, defaultConfig::getUsernameAttributes);
}
@Override
public Dn getUserBaseDN() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_USER_BASE_DN,
userBaseDn, defaultConfig::getUserBaseDN);
}
@Override
public Dn getConfigurationBaseDN() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_CONFIG_BASE_DN,
configBaseDn, defaultConfig::getConfigurationBaseDN);
}
@Override
public List<String> getGroupNameAttributes() throws GuacamoleException {
return withDefault(groupNameAttributes, defaultConfig::getGroupNameAttributes);
}
@Override
public Dn getGroupBaseDN() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_GROUP_BASE_DN,
groupBaseDn, defaultConfig::getGroupBaseDN);
}
@Override
public String getSearchBindDN() throws GuacamoleException {
return withDefault(searchBindDn, defaultConfig::getSearchBindDN);
}
@Override
public String getSearchBindPassword() throws GuacamoleException {
return withDefault(searchBindPassword, defaultConfig::getSearchBindPassword);
}
@Override
public EncryptionMethod getEncryptionMethod() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_ENCRYPTION_METHOD,
encryptionMethod, defaultConfig::getEncryptionMethod);
}
@Override
public int getMaxResults() throws GuacamoleException {
return withDefault(maxSearchResults, defaultConfig::getMaxResults);
}
@Override
public AliasDerefMode getDereferenceAliases() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_DEREFERENCE_ALIASES,
dereferenceAliases, defaultConfig::getDereferenceAliases);
}
@Override
public boolean getFollowReferrals() throws GuacamoleException {
return withDefault(followReferrals, defaultConfig::getFollowReferrals);
}
@Override
public int getMaxReferralHops() throws GuacamoleException {
return withDefault(maxReferralHops, defaultConfig::getMaxReferralHops);
}
@Override
public ExprNode getUserSearchFilter() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_USER_SEARCH_FILTER,
userSearchFilter, defaultConfig::getUserSearchFilter);
}
@Override
public ExprNode getGroupSearchFilter() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_GROUP_SEARCH_FILTER,
groupSearchFilter, defaultConfig::getGroupSearchFilter);
}
@Override
public int getOperationTimeout() throws GuacamoleException {
return withDefault(operationTimeout, defaultConfig::getOperationTimeout);
}
@Override
public int getNetworkTimeout() throws GuacamoleException {
return withDefault(networkTimeout, defaultConfig::getNetworkTimeout);
}
@Override
public List<String> getAttributes() throws GuacamoleException {
return withDefault(userAttributes, defaultConfig::getAttributes);
}
@Override
public String getMemberAttribute() throws GuacamoleException {
return withDefault(memberAttribute, defaultConfig::getMemberAttribute);
}
@Override
public MemberAttributeType getMemberAttributeType() throws GuacamoleException {
return withDefault(LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE_TYPE,
memberAttributeType, defaultConfig::getMemberAttributeType);
}
}