From c9b7140eb95538c534f9139ffd360c9e5cddbdc0 Mon Sep 17 00:00:00 2001 From: Matthias Harter Date: Sat, 31 Oct 2020 10:26:37 +0100 Subject: [PATCH] added searchRecursive property in ldap config --- .../security/ldap/LdapSecurityRealmTest.java | 7 ++++ .../security/ldap/SearchRecursiveTest.java | 33 +++++++++++++++++++ .../search-recursive/application.properties | 12 +++++++ .../elytron/security/ldap/LdapRecorder.java | 14 +++++--- .../ldap/config/IdentityMappingConfig.java | 7 ++++ .../ldap/src/main/resources/quarkus-io.ldif | 17 ++++++++++ 6 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/SearchRecursiveTest.java create mode 100644 extensions/elytron-security-ldap/deployment/src/test/resources/search-recursive/application.properties diff --git a/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/LdapSecurityRealmTest.java b/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/LdapSecurityRealmTest.java index ed589a1af7aed..95c5d47be5cb3 100644 --- a/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/LdapSecurityRealmTest.java +++ b/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/LdapSecurityRealmTest.java @@ -32,6 +32,13 @@ public void testSecureAccessFailure() { .statusCode(401); } + @Test() + public void testNotSearchingRecursiveFailure() { + RestAssured.given().auth().preemptive().basic("subUser", "subUserPassword") + .when().get("/servlet-secured").then() + .statusCode(401); + } + @Test() public void testSecureRoleFailure() { RestAssured.given().auth().preemptive().basic("noRoleUser", "noRoleUserPassword") diff --git a/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/SearchRecursiveTest.java b/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/SearchRecursiveTest.java new file mode 100644 index 0000000000000..b90805c2937c7 --- /dev/null +++ b/extensions/elytron-security-ldap/deployment/src/test/java/io/quarkus/elytron/security/ldap/SearchRecursiveTest.java @@ -0,0 +1,33 @@ +package io.quarkus.elytron.security.ldap; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.elytron.security.ldap.rest.SingleRoleSecuredServlet; +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.ldap.LdapServerTestResource; +import io.restassured.RestAssured; + +@QuarkusTestResource(LdapServerTestResource.class) +public class SearchRecursiveTest { + + protected static Class[] testClasses = { + SingleRoleSecuredServlet.class + }; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(testClasses) + .addAsResource("search-recursive/application.properties", "application.properties")); + + @Test() + public void testNotSearchingRecursiveFailure() { + RestAssured.given().auth().preemptive().basic("subUser", "subUserPassword") + .when().get("/servlet-secured").then() + .statusCode(200); + } +} diff --git a/extensions/elytron-security-ldap/deployment/src/test/resources/search-recursive/application.properties b/extensions/elytron-security-ldap/deployment/src/test/resources/search-recursive/application.properties new file mode 100644 index 0000000000000..7d5ab1814eaf5 --- /dev/null +++ b/extensions/elytron-security-ldap/deployment/src/test/resources/search-recursive/application.properties @@ -0,0 +1,12 @@ +quarkus.security.ldap.enabled=true + +quarkus.security.ldap.dir-context.principal=uid=admin,ou=system +quarkus.security.ldap.dir-context.url=ldap://127.0.0.1:10389 +quarkus.security.ldap.dir-context.password=secret + +quarkus.security.ldap.identity-mapping.search-recursive=true +quarkus.security.ldap.identity-mapping.search-base-dn=ou=Users,dc=quarkus,dc=io + +quarkus.security.ldap.identity-mapping.attribute-mappings."0".from=cn +quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter=(member=uid={0},ou=SubUsers,ou=Users,dc=quarkus,dc=io) +quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou=Roles,dc=quarkus,dc=io diff --git a/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/LdapRecorder.java b/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/LdapRecorder.java index fcef51078e622..ad09c9e98a34a 100644 --- a/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/LdapRecorder.java +++ b/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/LdapRecorder.java @@ -29,19 +29,25 @@ public class LdapRecorder { * @return runtime value wrapper for the SecurityRealm */ public RuntimeValue createRealm(LdapSecurityRealmRuntimeConfig runtimeConfig) { - LdapSecurityRealmBuilder builder = LdapSecurityRealmBuilder.builder() + LdapSecurityRealmBuilder.IdentityMappingBuilder identityMappingBuilder = LdapSecurityRealmBuilder.builder() .setDirContextSupplier(createDirContextSupplier(runtimeConfig.dirContext)) - .identityMapping() + .identityMapping(); + + if (runtimeConfig.identityMapping.searchRecursive) { + identityMappingBuilder.searchRecursive(); + } + + LdapSecurityRealmBuilder ldapSecurityRealmBuilder = identityMappingBuilder .map(createAttributeMappings(runtimeConfig.identityMapping)) .setRdnIdentifier(runtimeConfig.identityMapping.rdnIdentifier) .setSearchDn(runtimeConfig.identityMapping.searchBaseDn) .build(); if (runtimeConfig.directVerification) { - builder.addDirectEvidenceVerification(false); + ldapSecurityRealmBuilder.addDirectEvidenceVerification(false); } - return new RuntimeValue<>(builder.build()); + return new RuntimeValue<>(ldapSecurityRealmBuilder.build()); } private ExceptionSupplier createDirContextSupplier(DirContextConfig dirContext) { diff --git a/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/config/IdentityMappingConfig.java b/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/config/IdentityMappingConfig.java index 1846c259df185..db7b13acba608 100644 --- a/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/config/IdentityMappingConfig.java +++ b/extensions/elytron-security-ldap/runtime/src/main/java/io/quarkus/elytron/security/ldap/config/IdentityMappingConfig.java @@ -20,6 +20,12 @@ public class IdentityMappingConfig { @ConfigItem public String searchBaseDn; + /** + * If the child nodes are also searched for identities + */ + @ConfigItem(defaultValue = "false") + public boolean searchRecursive; + /** * The configs how we get from the attribute to the Role */ @@ -31,6 +37,7 @@ public String toString() { return "IdentityMappingConfig{" + "rdnIdentifier='" + rdnIdentifier + '\'' + ", searchBaseDn='" + searchBaseDn + '\'' + + ", searchRecursive=" + searchRecursive + ", attributeMappings=" + attributeMappings + '}'; } diff --git a/test-framework/ldap/src/main/resources/quarkus-io.ldif b/test-framework/ldap/src/main/resources/quarkus-io.ldif index 71ba910323c2c..cbe108e20e6c3 100644 --- a/test-framework/ldap/src/main/resources/quarkus-io.ldif +++ b/test-framework/ldap/src/main/resources/quarkus-io.ldif @@ -41,6 +41,22 @@ sn: adminUser uid: adminUser userPassword: adminUserPassword +# A sub OU of Users + +dn: ou=SubUsers,ou=Users,dc=quarkus,dc=io +objectclass: organizationalUnit +objectclass: top +ou: SubUsers + +dn: uid=subUser,ou=SubUsers,ou=Users,dc=quarkus,dc=io +objectclass: top +objectclass: person +objectclass: inetOrgPerson +cn: SubUser +sn: subUser +uid: subUser +userpassword: subUserPassword + #The roles OU @@ -56,6 +72,7 @@ objectClass: top objectClass: groupOfNames cn: standardRole member: uid=standardUser,ou=Users,dc=quarkus,dc=io +member: uid=subUser,ou=SubUsers,ou=Users,dc=quarkus,dc=io dn: cn=adminRole,ou=Roles,dc=quarkus,dc=io objectClass: top