[java-identity-provider] branch maint-3.4 updated: IDP-1491 Detect and use JNDI LDAP properties.

Daniel Fisher dfisher at vt.edu
Sun Sep 8 23:27:21 EDT 2019


This is an automated email from the git hooks/post-receive script.

dfisher pushed a commit to branch maint-3.4
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=42748e1bd987cedde684e2546df9ef9489cdef6b

The following commit(s) were added to refs/heads/maint-3.4 by this push:
       new  42748e1   IDP-1491 Detect and use JNDI LDAP properties.
42748e1 is described below

commit 42748e1bd987cedde684e2546df9ef9489cdef6b
Author: Daniel Fisher <dfisher at vt.edu>
AuthorDate: Sun Sep 8 23:21:49 2019 -0400

    IDP-1491 Detect and use JNDI LDAP properties.
    
    If JNDI properties for binary attributes or derefAliases are detected, set those values on the search request.
    Update the resolver schema to include BinaryAttributes element and derefAlises attribute.
---
 .../dc/ldap/impl/LDAPDataConnectorParser.java      | 39 +++++++++++-
 .../dc/ldap/LDAPDataConnectorParserTest.java       | 74 +++++++++++++++++++++-
 .../spring/dc/ldap/ldapDataConnectorTest.ldif      | 24 +++++++
 .../resolver/ldap-attribute-resolver-v2-jndi.xml   | 34 ++++++++++
 .../ldap/resolver/ldap-attribute-resolver-v2.xml   |  8 ++-
 .../schema/shibboleth-attribute-resolver.xsd       | 27 ++++++++
 6 files changed, 198 insertions(+), 8 deletions(-)

diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
index 1f9b680..6e8d7db 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
@@ -28,6 +28,7 @@ import org.ldaptive.BindConnectionInitializer;
 import org.ldaptive.ConnectionConfig;
 import org.ldaptive.Credential;
 import org.ldaptive.DefaultConnectionFactory;
+import org.ldaptive.DerefAliases;
 import org.ldaptive.SearchExecutor;
 import org.ldaptive.SearchFilter;
 import org.ldaptive.SearchRequest;
@@ -196,7 +197,7 @@ public class LDAPDataConnectorParser extends AbstractWarningDataConnectorParser
             builder.addPropertyValue("connectionFactory", connectionFactory.getBeanDefinition());
         }
 
-        final BeanDefinition searchExecutor = v2Parser.createSearchExecutor();
+        final BeanDefinition searchExecutor = v2Parser.createSearchExecutor(props);
         builder.addPropertyValue("searchExecutor", searchExecutor);
 
         final String mappingStrategyID = AttributeSupport.getAttributeValue(config, new QName("mappingStrategyRef"));
@@ -474,13 +475,16 @@ public class LDAPDataConnectorParser extends AbstractWarningDataConnectorParser
 
         /**
          * Creates a new search executor bean definition from a v2 XML configuration.
-         * 
+         *
+         * @param props ldap properties
+         *
          * @return search executor bean definition
          */
         // CheckStyle: CyclomaticComplexity OFF
-        @Nonnull public BeanDefinition createSearchExecutor() {
+        @Nonnull public BeanDefinition createSearchExecutor(final ManagedMap<String, String> props) {
             final String baseDn = AttributeSupport.getAttributeValue(configElement, new QName("baseDN"));
             final String searchScope = AttributeSupport.getAttributeValue(configElement, new QName("searchScope"));
+            final String derefAliases = AttributeSupport.getAttributeValue(configElement, new QName("derefAliases"));
             final String searchTimeLimit =
                     AttributeSupport.getAttributeValue(configElement, new QName("searchTimeLimit"));
             final String maxResultSize = AttributeSupport.getAttributeValue(configElement, new QName("maxResultSize"));
@@ -495,6 +499,12 @@ public class LDAPDataConnectorParser extends AbstractWarningDataConnectorParser
             if (searchScope != null) {
                 searchExecutor.addPropertyValue("searchScope", searchScope);
             }
+            if (derefAliases != null) {
+                searchExecutor.addPropertyValue("derefAliases", derefAliases);
+            } else if (props.containsKey("java.naming.ldap.derefAliases")) {
+                searchExecutor.addPropertyValue(
+                  "derefAliases", props.get("java.naming.ldap.derefAliases").toUpperCase());
+            }
             if (searchTimeLimit != null) {
                 final BeanDefinitionBuilder duration =
                         BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
@@ -533,6 +543,29 @@ public class LDAPDataConnectorParser extends AbstractWarningDataConnectorParser
                 searchExecutor.addPropertyValue("returnAttributes", returnAttrs.getBeanDefinition());
             }
 
+            final List<Element> binaryAttrsElements = ElementSupport.getChildElements(configElement,
+              new QName(DataConnectorNamespaceHandler.NAMESPACE, "BinaryAttributes"));
+            binaryAttrsElements.addAll(ElementSupport.getChildElements(configElement,
+              new QName(AttributeResolverNamespaceHandler.NAMESPACE, "BinaryAttributes")));
+
+            if (!binaryAttrsElements.isEmpty()) {
+                if (binaryAttrsElements.size() > 1) {
+                    log.warn("{} Only one <BinaryAttributes> element can be specified; "+
+                      "only the first has been consulted.", getLogPrefix());
+                }
+                final Element binaryAttrsElement = binaryAttrsElements.get(0);
+
+                final BeanDefinitionBuilder binaryAttrs =
+                  BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildStringList");
+                binaryAttrs.addConstructorArgValue(ElementSupport.getElementContentAsString(binaryAttrsElement));
+                searchExecutor.addPropertyValue("binaryAttributes", binaryAttrs.getBeanDefinition());
+            } else if (props.containsKey("java.naming.ldap.attributes.binary")) {
+                final BeanDefinitionBuilder binaryAttrs =
+                  BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildStringList");
+                binaryAttrs.addConstructorArgValue(props.get("java.naming.ldap.attributes.binary"));
+                searchExecutor.addPropertyValue("binaryAttributes", binaryAttrs.getBeanDefinition());
+            }
+
             return searchExecutor.getBeanDefinition();
         }
 
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
index 2458d20..90eff01 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
@@ -27,7 +27,9 @@ import java.util.Map;
 import org.ldaptive.BindConnectionInitializer;
 import org.ldaptive.ConnectionConfig;
 import org.ldaptive.DefaultConnectionFactory;
+import org.ldaptive.DerefAliases;
 import org.ldaptive.SearchExecutor;
+import org.ldaptive.SearchScope;
 import org.ldaptive.pool.BlockingConnectionPool;
 import org.ldaptive.pool.IdlePruneStrategy;
 import org.ldaptive.pool.PoolConfig;
@@ -163,6 +165,8 @@ public class LDAPDataConnectorParserTest {
                         TestSources.SP_ENTITY_ID);
         final Map<String, IdPAttribute> attrs = dataConnector.resolve(context);
         Assert.assertNotNull(attrs);
+        Assert.assertEquals(2, attrs.size());
+        Assert.assertEquals(attrs.get("employeeNumber").getValues().get(0).getValue(), "C2J20hMNp7NlUwQ+");
         Assert.assertNotNull(attrs.get("entryDN"));
     }
 
@@ -194,8 +198,6 @@ public class LDAPDataConnectorParserTest {
         doTest(dataConnector);
     }
 
-
-
     @Test public void v2MinimalConfig() throws Exception {
         final LDAPDataConnector dataConnector =
                 getLdapDataConnector(new String[] {"net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-minimal.xml"});
@@ -329,6 +331,74 @@ public class LDAPDataConnectorParserTest {
         Assert.assertNotNull(attrs.get("entryDN"));
     }
 
+    @Test public void v2JndiConfig() throws Exception {
+        final LDAPDataConnector dataConnector =
+          getLdapDataConnector(new String[] {"net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml"});
+        Assert.assertNotNull(dataConnector);
+        AssertJUnit.assertEquals(300000, dataConnector.getNoRetryDelay());
+        final DefaultConnectionFactory connFactory = (DefaultConnectionFactory) dataConnector.getConnectionFactory();
+        AssertJUnit.assertNotNull(connFactory);
+
+        final ConnectionConfig connConfig = connFactory.getConnectionConfig();
+        AssertJUnit.assertNotNull(connConfig);
+        AssertJUnit.assertEquals("ldap://localhost:10389", connConfig.getLdapUrl());
+        AssertJUnit.assertEquals(false, connConfig.getUseSSL());
+        AssertJUnit.assertEquals(true, connConfig.getUseStartTLS());
+        final BindConnectionInitializer connInitializer = (BindConnectionInitializer) connConfig.getConnectionInitializer();
+        AssertJUnit.assertEquals("cn=Directory Manager", connInitializer.getBindDn());
+        AssertJUnit.assertEquals("password", connInitializer.getBindCredential().getString());
+        AssertJUnit.assertEquals(2000, connConfig.getConnectTimeout());
+        AssertJUnit.assertEquals(4000, connConfig.getResponseTimeout());
+
+        final SslConfig sslConfig = connFactory.getConnectionConfig().getSslConfig();
+        AssertJUnit.assertNotNull(sslConfig);
+        final CredentialConfig credentialConfig = sslConfig.getCredentialConfig();
+        AssertJUnit.assertNotNull(credentialConfig);
+
+        final ProviderConfig providerConfig = connFactory.getProvider().getProviderConfig();
+        AssertJUnit.assertNotNull(providerConfig);
+        AssertJUnit.assertEquals("value1", providerConfig.getProperties().get("name1"));
+        AssertJUnit.assertEquals("finding", providerConfig.getProperties().get("java.naming.ldap.derefAliases"));
+        AssertJUnit.assertEquals("jpegPhoto employeeNumber", providerConfig.getProperties().get("java.naming.ldap.attributes.binary"));
+
+        final SearchExecutor searchExecutor = dataConnector.getSearchExecutor();
+        AssertJUnit.assertNotNull(searchExecutor);
+        AssertJUnit.assertEquals("ou=people,dc=shibboleth,dc=net", searchExecutor.getBaseDn());
+        AssertJUnit.assertNull(searchExecutor.getSearchFilter());
+        AssertJUnit.assertEquals(7000, searchExecutor.getTimeLimit());
+        AssertJUnit.assertEquals(SearchScope.SUBTREE, searchExecutor.getSearchScope());
+        AssertJUnit.assertEquals(DerefAliases.FINDING, searchExecutor.getDerefAliases());
+        AssertJUnit.assertArrayEquals(new String[] {"jpegPhoto", "employeeNumber"}, searchExecutor.getBinaryAttributes());
+
+        final ConnectionFactoryValidator validator = (ConnectionFactoryValidator) dataConnector.getValidator();
+        AssertJUnit.assertNotNull(validator);
+        AssertJUnit.assertTrue(validator.isThrowValidateError());
+        AssertJUnit.assertNotNull(validator.getConnectionFactory());
+
+        final ExecutableSearchBuilder searchBuilder = dataConnector.getExecutableSearchBuilder();
+        AssertJUnit.assertNotNull(searchBuilder);
+
+        final StringAttributeValueMappingStrategy mappingStrategy =(StringAttributeValueMappingStrategy) dataConnector.getMappingStrategy();
+        AssertJUnit.assertNotNull(mappingStrategy);
+        AssertJUnit.assertTrue(mappingStrategy.isNoResultAnError());
+        AssertJUnit.assertTrue(mappingStrategy.isMultipleResultsAnError());
+
+        AssertJUnit.assertNull(dataConnector.getResultsCache());
+
+        dataConnector.initialize();
+        final AttributeResolutionContext context =
+          TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
+            TestSources.SP_ENTITY_ID);
+        final Map<String, IdPAttribute> attrs = dataConnector.resolve(context);
+        Assert.assertNotNull(attrs);
+        Assert.assertEquals(5, attrs.size());
+        Assert.assertNotNull(attrs.get("cn"));
+        Assert.assertNotNull(attrs.get("sn"));
+        Assert.assertNotNull(attrs.get("jpegPhoto"));
+        Assert.assertEquals(attrs.get("employeeNumber").getValues().get(0).getValue(), "C2J20hMNp7NlUwQ+");
+        Assert.assertNotNull(attrs.get("entryDN"));
+    }
+
     @Test public void v2PropsConfig() throws Exception {
         final Resource props = new ClassPathResource("net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties");
         final LDAPDataConnector dataConnector =
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldapDataConnectorTest.ldif b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldapDataConnectorTest.ldif
index 7c48f70..ccb33d3 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldapDataConnectorTest.ldif
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldapDataConnectorTest.ldif
@@ -21,6 +21,30 @@ homephone: 555-111-2222
 mail: peter.principal at shibboleth.net
 mail: peterprincipal at shibboleth.net
 description: test principal
+employeeNumber:: C2J20hMNp7NlUwQ+
+jpegPhoto:: /9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAAB
+ AAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAAB
+ AAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAA
+ AAGgAwAEAAAAAQAAAAEAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAA
+ OEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/CABEIAAEAAQMBIgACEQEDEQH/
+ xAAfAAABBQEBAQEBAQAAAAAAAAADAgQBBQAGBwgJCgv/xADDEAABAwMCBAMEBgQH
+ BgQIBnMBAgADEQQSIQUxEyIQBkFRMhRhcSMHgSCRQhWhUjOxJGIwFsFy0UOSNIII
+ 4VNAJWMXNfCTc6JQRLKD8SZUNmSUdMJg0oSjGHDiJ0U3ZbNVdaSVw4Xy00Z2gONH
+ Vma0CQoZGigpKjg5OkhJSldYWVpnaGlqd3h5eoaHiImKkJaXmJmaoKWmp6ipqrC1
+ tre4ubrAxMXGx8jJytDU1dbX2Nna4OTl5ufo6erz9PX29/j5+v/EAB8BAAMBAQEB
+ AQEBAQEAAAAAAAECAAMEBQYHCAkKC//EAMMRAAICAQMDAwIDBQIFAgQEhwEAAhED
+ EBIhBCAxQRMFMCIyURRABjMjYUIVcVI0gVAkkaFDsRYHYjVT8NElYMFE4XLxF4Jj
+ NnAmRVSSJ6LSCAkKGBkaKCkqNzg5OkZHSElKVVZXWFlaZGVmZ2hpanN0dXZ3eHl6
+ gIOEhYaHiImKkJOUlZaXmJmaoKOkpaanqKmqsLKztLW2t7i5usDCw8TFxsfIycrQ
+ 09TV1tfY2drg4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwAEAgMDAwIEAwMDBAQEBAUJ
+ BgUFBQULCAgGCQ0LDQ0NCwwMDhAUEQ4PEw8MDBIYEhMVFhcXFw4RGRsZFhoUFhcW
+ /9sAQwEEBAQFBQUKBgYKFg8MDxYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW
+ FhYWFhYWFhYWFhYWFhYWFhYWFhYW/9oADAMBAAIRAxEAAAH2XbY7/wD/2gAIAQEA
+ AQUCf//aAAgBAxEBPwF//9oACAECEQE/AX//2gAIAQEABj8Cf//EADMQAQADAAIC
+ AgICAwEBAAACCwERACExQVFhcYGRobHB8NEQ4fEgMEBQYHCAkKCwwNDg/9oACAEB
+ AAE/Ib//2gAMAwEAAhEDEQAAEAP/xAAzEQEBAQADAAECBQUBAQABAQkBABEhMRBB
+ UWEgcfCRgaGx0cHh8TBAUGBwgJCgsMDQ4P/aAAgBAxEBPxC//9oACAECEQE/EL//
+ 2gAIAQEAAT8Qv//Z
 
 dn: cn=Paul Principal,ou=people,dc=shibboleth,dc=net
 objectclass: inetOrgPerson
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml
new file mode 100644
index 0000000..0d0942c
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="urn:mace:shibboleth:2.0:security"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd
+                            urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd">
+
+    <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
+        ldapURL="ldap://localhost:10389"
+        baseDN="ou=people,dc=shibboleth,dc=net"
+        principal="cn=Directory Manager"
+        principalCredential="password"
+        useStartTLS="true"
+        searchTimeLimit="PT7S"
+        noResultIsError="true"
+        multipleResultsIsError="true"
+        noRetryDelay="PT5M"
+        trustFile="net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap.crt"
+        connectTimeout="PT2S"
+        responseTimeout="PT4S">
+        
+        <LDAPProperty name="name1" value="value1"/>
+        <LDAPProperty name="java.naming.ldap.attributes.binary" value="jpegPhoto employeeNumber"/>
+        <LDAPProperty name="java.naming.ldap.derefAliases" value="finding"/>
+
+        <ReturnAttributes>cn sn jpegPhoto employeeNumber</ReturnAttributes>
+
+        <FilterTemplate>
+            <![CDATA[
+                (uid=${resolutionContext.principal})
+            ]]>
+        </FilterTemplate>
+        
+    </DataConnector>
+    
+</AttributeResolver>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
index 19746a5..6230745 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
@@ -61,12 +61,14 @@
 
         <LDAPProperty name="name2" value="value2"/>
                 
-        <ReturnAttributes>a b g t</ReturnAttributes>
+        <ReturnAttributes>a b g t employeeNumber</ReturnAttributes>
         
         <LDAPProperty name="name1" value="value1"/>
         
-        <ReturnAttributes>a b g t</ReturnAttributes>
-        
+        <ReturnAttributes>a b g t employeeNumber</ReturnAttributes>
+
+        <BinaryAttributes>g employeeNumber</BinaryAttributes>
+
         <FilterTemplate>
             <![CDATA[
                 (uid=${resolutionContext.principal})
diff --git a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index 332ab58..4cb0edc 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -970,6 +970,13 @@
                             </documentation>
                         </annotation>
                     </element>
+                    <element name="BinaryAttributes" type="string" minOccurs="0">
+                        <annotation>
+                            <documentation>
+                                A space separated list of attributes whose values should be encoded.
+                            </documentation>
+                        </annotation>
+                    </element>
                     <element name="LDAPProperty" type="resolver:PropertyType">
                         <annotation>
                             <documentation>
@@ -1051,6 +1058,14 @@
                         </documentation>
                     </annotation>
                 </attribute>
+                <attribute name="derefAliases" type="resolver:DerefAliasesType">
+                    <annotation>
+                        <documentation>
+                            The LDAP alias dereference behavior. Acceptable values are NEVER, SEARCHING, FINDING, ALWAYS.
+                            Default value is NEVER.
+                        </documentation>
+                    </annotation>
+                </attribute>
                 <attribute name="useStartTLS" type="string">
                     <annotation>
                         <documentation>
@@ -1748,6 +1763,18 @@
         </restriction>
     </simpleType>
 
+    <simpleType name="DerefAliasesType">
+        <annotation>
+            <documentation>How to dereference aliases.</documentation>
+        </annotation>
+        <restriction base="string">
+            <enumeration value="NEVER"/>
+            <enumeration value="SEARCHING"/>
+            <enumeration value="FINDING"/>
+            <enumeration value="ALWAYS"/>
+        </restriction>
+    </simpleType>
+
     <complexType name="LdapPoolConfigType">
         <attribute name="minPoolSize" type="string">
             <annotation>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list