From 450af91be9c98a0dec0e7853891e8e132eaaec01 Mon Sep 17 00:00:00 2001 From: Magnus Lewis-Smith Date: Wed, 23 Oct 2019 10:48:22 +0100 Subject: [PATCH] GUACAMOLE-300: Support posixGroup in LDAP Authentication and Group-based Session Admission reset/rebase/squash a chaos of commits: - implement user/group membership search using Apache Directory Ldap module instead of JLDAP - Retrieve user's group membership if specified by username rather than DN - New enum 'MemberAttributeType' - New GuacamoleProperty 'MemberAttributeTypeProperty' - New configuration property 'ldap-member-attribute-type' Specifies what the field specified by 'ldap-member-attribute' actually contains -- "dn" (default) or "uid" or ... --- .../auth/ldap/conf/ConfigurationService.java | 18 +++++++ .../ldap/conf/LDAPGuacamoleProperties.java | 11 ++++ .../auth/ldap/conf/MemberAttributeType.java | 34 ++++++++++++ .../conf/MemberAttributeTypeProperty.java | 53 +++++++++++++++++++ .../auth/ldap/group/UserGroupService.java | 31 ++++++++++- 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeType.java create mode 100644 extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeTypeProperty.java diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/ConfigurationService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/ConfigurationService.java index 588c60d4c..86da90304 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/ConfigurationService.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/ConfigurationService.java @@ -373,4 +373,22 @@ public class ConfigurationService { ); } + /** + * Returns whether the LDAP attribute used to enumerate members in a group + * specifies UID or DN. + * + * @return + * The type of data contained in the LDAP attribute used to enumerate + * members in a group, as configured in guacamole.properties + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public MemberAttributeType getMemberAttributeType() throws GuacamoleException { + return environment.getProperty( + LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE_TYPE, + MemberAttributeType.DN + ); + } + } diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java index e5f44f0b7..7fd6ceff9 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java @@ -255,4 +255,15 @@ public class LDAPGuacamoleProperties { public String getName() { return "ldap-member-attribute"; } }; + + /** + * Specify the type of data contained in 'ldap-member-attribute' + */ + public static final MemberAttributeTypeProperty LDAP_MEMBER_ATTRIBUTE_TYPE = new MemberAttributeTypeProperty() { + + @Override + public String getName() { return "ldap-member-attribute-type"; } + + }; + } diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeType.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeType.java new file mode 100644 index 000000000..49418b79f --- /dev/null +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeType.java @@ -0,0 +1,34 @@ +/* + * 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; + +/** + * All possible means of describing membership within LDAP group directory records. + */ +public enum MemberAttributeType { + /** + * group membership is specified by DN + */ + DN, + /** + * group membership is specified by usercode + */ + UID; +} diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeTypeProperty.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeTypeProperty.java new file mode 100644 index 000000000..892441e42 --- /dev/null +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/MemberAttributeTypeProperty.java @@ -0,0 +1,53 @@ +/* + * 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 org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleServerException; +import org.apache.guacamole.properties.GuacamoleProperty; + +/** + * A GuacamoleProperty whose value is a MemberAttributeType. The possible + * strings "dn" or "uid" are mapped to their values as a MemberAttributeType + * enum. Anything else results in a parse error. + */ +public abstract class MemberAttributeTypeProperty implements GuacamoleProperty { + + @Override + public MemberAttributeType parseValue(String value) throws GuacamoleException { + + // If no value provided, return null. + if (value == null) + return null; + + // dn + if (value.equals("dn")) + return MemberAttributeType.DN; + + // uid + if (value.equals("uid")) + return MemberAttributeType.UID; + + // The provided value is not legal + throw new GuacamoleServerException("Member attribute type must be one of \"dn\" or \"uid\"."); + + } + +} diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/group/UserGroupService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/group/UserGroupService.java index 0628006dd..a08502b18 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/group/UserGroupService.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/group/UserGroupService.java @@ -35,6 +35,7 @@ import org.apache.directory.api.ldap.model.filter.PresenceNode; import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.guacamole.auth.ldap.conf.ConfigurationService; +import org.apache.guacamole.auth.ldap.conf.MemberAttributeType; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.ldap.ObjectQueryService; import org.apache.guacamole.net.auth.UserGroup; @@ -176,6 +177,34 @@ public class UserGroupService { if (groupBaseDN == null) return Collections.emptyList(); + // memberAttribute specified in properties could contain DN or username + MemberAttributeType memberAttributeType = confService.getMemberAttributeType(); + String userIDorDN = userDN.toString(); + if (memberAttributeType == MemberAttributeType.UID) { + // Retrieve user objects with userDN + List userEntries = queryService.search( + ldapConnection, + userDN, + confService.getUserSearchFilter(), + 0); + // ... there can surely only be one + if (userEntries.size() != 1) { + logger.warn("user DN \"{}\" does not return unique value and will be ignored", + userDN.toString()); + } else { + // determine unique identifier for user + Entry userEntry = userEntries.get(0); + Collection userAttributes = confService.getUsernameAttributes(); + try { + userIDorDN = queryService.getIdentifier(userEntry, userAttributes); + } + catch (LdapInvalidAttributeValueException e) { + logger.error("User group missing identifier: {}", e.getMessage()); + logger.debug("LDAP exception while getting group identifier.", e); + } + } + } + // Get all groups the user is a member of starting at the groupBaseDN, // excluding guacConfigGroups return queryService.search( @@ -183,7 +212,7 @@ public class UserGroupService { groupBaseDN, getGroupSearchFilter(), Collections.singleton(confService.getMemberAttribute()), - userDN.toString() + userIDorDN ); }