mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-957: Support reading multiple LDAP server configurations from "ldap-servers.yml".
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
com.fasterxml.jackson.core:jackson-databind:jar:2.12.2
|
com.fasterxml.jackson.core:jackson-databind:jar:2.12.2
|
||||||
com.fasterxml.jackson.core:jackson-core:jar:2.12.2
|
com.fasterxml.jackson.core:jackson-core:jar:2.12.2
|
||||||
com.fasterxml.jackson.core:jackson-annotations:jar:2.12.2
|
com.fasterxml.jackson.core:jackson-annotations:jar:2.12.2
|
||||||
|
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.12.2
|
||||||
com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.12.2
|
com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.12.2
|
||||||
|
8
doc/licenses/snakeyaml-1.27/README
Normal file
8
doc/licenses/snakeyaml-1.27/README
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
SnakeYAML (https://bitbucket.org/asomov/snakeyaml/)
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
Version: 1.27
|
||||||
|
From: 'Andrey Somov' (https://bitbucket.org/asomov/)
|
||||||
|
License(s):
|
||||||
|
Apache v2.0
|
||||||
|
|
1
doc/licenses/snakeyaml-1.27/dep-coordinates.txt
Normal file
1
doc/licenses/snakeyaml-1.27/dep-coordinates.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
org.yaml:snakeyaml:jar:1.27
|
@@ -60,6 +60,16 @@
|
|||||||
<artifactId>guice</artifactId>
|
<artifactId>guice</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Jackson and YAML support -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||||
|
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@@ -196,7 +196,7 @@ public class AuthenticationProviderService {
|
|||||||
String password) throws GuacamoleException {
|
String password) throws GuacamoleException {
|
||||||
|
|
||||||
// Get relevant LDAP configurations for user
|
// Get relevant LDAP configurations for user
|
||||||
Collection<LDAPConfiguration> configs = confService.getLDAPConfigurations(username);
|
Collection<? extends LDAPConfiguration> configs = confService.getLDAPConfigurations(username);
|
||||||
if (configs.isEmpty()) {
|
if (configs.isEmpty()) {
|
||||||
logger.info("User \"{}\" does not map to any defined LDAP configurations.", username);
|
logger.info("User \"{}\" does not map to any defined LDAP configurations.", username);
|
||||||
return null;
|
return null;
|
||||||
|
@@ -19,17 +19,41 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.ldap.conf;
|
package org.apache.guacamole.auth.ldap.conf;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for retrieving configuration information regarding LDAP servers.
|
* Service for retrieving configuration information regarding LDAP servers.
|
||||||
*/
|
*/
|
||||||
public class ConfigurationService {
|
public class ConfigurationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ConfigurationService.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ObjectMapper for deserializing YAML.
|
||||||
|
*/
|
||||||
|
private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the file within GUACAMOLE_HOME that defines each available
|
||||||
|
* LDAP server (if not using guacamole.properties).
|
||||||
|
*/
|
||||||
|
private static final String LDAP_SERVERS_YML = "ldap-servers.yml";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Guacamole server environment.
|
* The Guacamole server environment.
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +78,25 @@ public class ConfigurationService {
|
|||||||
* If the configuration information of the LDAP servers related to the
|
* If the configuration information of the LDAP servers related to the
|
||||||
* user having the given username cannot be retrieved due to an error.
|
* user having the given username cannot be retrieved due to an error.
|
||||||
*/
|
*/
|
||||||
public Collection<LDAPConfiguration> getLDAPConfigurations(String username) throws GuacamoleException {
|
public Collection<? extends LDAPConfiguration> getLDAPConfigurations(String username) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Read configuration from YAML, if available
|
||||||
|
File ldapServers = new File(environment.getGuacamoleHome(), LDAP_SERVERS_YML);
|
||||||
|
if (ldapServers.exists()) {
|
||||||
|
try {
|
||||||
|
logger.debug("Reading LDAP configuration from \"{}\"...", ldapServers);
|
||||||
|
return mapper.readValue(ldapServers, new TypeReference<Collection<JacksonLDAPConfiguration>>() {});
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
logger.error("\"{}\" could not be read/parsed: {}", ldapServers, e.getMessage());
|
||||||
|
throw new GuacamoleServerException("Cannot read LDAP configuration from \"" + ldapServers + "\"", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use guacamole.properties if not using YAML
|
||||||
|
logger.debug("Reading LDAP configuration from guacamole.properties...");
|
||||||
return Collections.singletonList(new EnvironmentLDAPConfiguration(environment));
|
return Collections.singletonList(new EnvironmentLDAPConfiguration(environment));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* 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.JsonProperty;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.directory.api.ldap.model.filter.ExprNode;
|
||||||
|
import org.apache.directory.api.ldap.model.filter.PresenceNode;
|
||||||
|
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.GuacamoleServerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDAPConfiguration implementation that is annotated for deserialization by
|
||||||
|
* Jackson.
|
||||||
|
*/
|
||||||
|
public class JacksonLDAPConfiguration implements LDAPConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
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")
|
||||||
|
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_USER_ATTRIBUTES}.
|
||||||
|
* If not set within the YAML, this will be null.
|
||||||
|
*/
|
||||||
|
@JsonProperty("user-attributes")
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerHostname() {
|
||||||
|
return hostname != null ? hostname : "localhost";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getServerPort() throws GuacamoleException {
|
||||||
|
return port != null ? port : getEncryptionMethod().DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getUsernameAttributes() {
|
||||||
|
return usernameAttributes != null ? usernameAttributes : Collections.singletonList("uid");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dn getUserBaseDN() throws GuacamoleException {
|
||||||
|
|
||||||
|
Dn parsedDn = LDAPGuacamoleProperties.LDAP_USER_BASE_DN.parseValue(userBaseDn);
|
||||||
|
if (parsedDn == null)
|
||||||
|
throw new GuacamoleServerException("The \"user-base-dn\" property is required for all LDAP servers.");
|
||||||
|
|
||||||
|
return parsedDn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dn getConfigurationBaseDN() throws GuacamoleException {
|
||||||
|
return LDAPGuacamoleProperties.LDAP_CONFIG_BASE_DN.parseValue(configBaseDn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getGroupNameAttributes() throws GuacamoleException {
|
||||||
|
return groupNameAttributes != null ? groupNameAttributes : Collections.singletonList("cn");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dn getGroupBaseDN() throws GuacamoleException {
|
||||||
|
return LDAPGuacamoleProperties.LDAP_GROUP_BASE_DN.parseValue(groupBaseDn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSearchBindDN() throws GuacamoleException {
|
||||||
|
return searchBindDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSearchBindPassword() throws GuacamoleException {
|
||||||
|
return searchBindPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EncryptionMethod getEncryptionMethod() throws GuacamoleException {
|
||||||
|
|
||||||
|
EncryptionMethod parsedMethod = LDAPGuacamoleProperties.LDAP_ENCRYPTION_METHOD.parseValue(encryptionMethod);
|
||||||
|
if (parsedMethod == null)
|
||||||
|
return EncryptionMethod.NONE;
|
||||||
|
|
||||||
|
return parsedMethod;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxResults() throws GuacamoleException {
|
||||||
|
return maxSearchResults != null ? maxSearchResults : 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasDerefMode getDereferenceAliases() throws GuacamoleException {
|
||||||
|
|
||||||
|
AliasDerefMode parsedMode = LDAPGuacamoleProperties.LDAP_DEREFERENCE_ALIASES.parseValue(dereferenceAliases);
|
||||||
|
if (parsedMode == null)
|
||||||
|
return AliasDerefMode.NEVER_DEREF_ALIASES;
|
||||||
|
|
||||||
|
return parsedMode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFollowReferrals() throws GuacamoleException {
|
||||||
|
return followReferrals != null ? followReferrals : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxReferralHops() throws GuacamoleException {
|
||||||
|
return maxReferralHops != null ? maxReferralHops : 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExprNode getUserSearchFilter() throws GuacamoleException {
|
||||||
|
|
||||||
|
ExprNode parsedFilter = LDAPGuacamoleProperties.LDAP_USER_SEARCH_FILTER.parseValue(userSearchFilter);
|
||||||
|
if (parsedFilter == null)
|
||||||
|
return new PresenceNode("objectClass");
|
||||||
|
|
||||||
|
return parsedFilter;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExprNode getGroupSearchFilter() throws GuacamoleException {
|
||||||
|
|
||||||
|
ExprNode parsedFilter = LDAPGuacamoleProperties.LDAP_GROUP_SEARCH_FILTER.parseValue(groupSearchFilter);
|
||||||
|
if (parsedFilter == null)
|
||||||
|
return new PresenceNode("objectClass");
|
||||||
|
|
||||||
|
return parsedFilter;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOperationTimeout() throws GuacamoleException {
|
||||||
|
return operationTimeout != null ? operationTimeout : 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAttributes() throws GuacamoleException {
|
||||||
|
return userAttributes != null ? userAttributes : Collections.<String>emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMemberAttribute() throws GuacamoleException {
|
||||||
|
return memberAttribute != null ? memberAttribute : "member";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MemberAttributeType getMemberAttributeType()
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
MemberAttributeType parsedType = LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE_TYPE.parseValue(memberAttributeType);
|
||||||
|
if (parsedType == null)
|
||||||
|
return MemberAttributeType.DN;
|
||||||
|
|
||||||
|
return parsedType;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
5
pom.xml
5
pom.xml
@@ -377,6 +377,11 @@
|
|||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>${jackson.version}</version>
|
<version>${jackson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||||
|
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.module</groupId>
|
<groupId>com.fasterxml.jackson.module</groupId>
|
||||||
<artifactId>jackson-module-jaxb-annotations</artifactId>
|
<artifactId>jackson-module-jaxb-annotations</artifactId>
|
||||||
|
Reference in New Issue
Block a user