Skip to content

Commit

Permalink
feat(elytron-ldap): Docs and test mapping of LDAP groups to local roles
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvavrik committed Jan 14, 2025
1 parent cfd2a75 commit d0e6e24
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 11 deletions.
12 changes: 12 additions & 0 deletions docs/src/main/asciidoc/security-ldap.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou=

The `elytron-security-ldap` extension requires a dir-context and an identity-mapping with at least one attribute-mapping to authenticate the user and its identity.

=== Map LDAP groups to `SecurityIdentity` roles

Previously described application configuration showed how to map `CN` attribute of the LDAP Distinguished Name group to a Quarkus `SecurityIdentity` role.
More specifically, the `standardRole` CN was mapped to a `SecurityIdentity` role and thus allowed access to the `UserResource#me` endpoint.
However, required `SecurityIdentity` roles may differ between applications and you may need to map LDAP groups to local `SecurityIdentity` roles like in the example below:

[source,properties]
----
quarkus.http.auth.roles-mapping."standardRole"=user <1>
----
<1> Map the `standardRole` role to the application-specific `SecurityIdentity` role `user`.

== Testing the Application

The application is now protected and the identities are provided by our LDAP server.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.SecurityContext;

@Path("/api")
@ApplicationScoped
Expand All @@ -45,4 +47,11 @@ public String forbidden() {
return "authorized";
}

@GET
@Path("/requiresRootRole")
@RolesAllowed("root")
public String getPrincipalName(@Context SecurityContext securityContext) {
return securityContext.getUserPrincipal().getName();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou=
quarkus.security.ldap.cache.enabled=true
quarkus.security.ldap.cache.max-age=60s
quarkus.security.ldap.cache.size=10

quarkus.http.auth.roles-mapping."adminRole"=root

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import org.junit.jupiter.api.Test;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.sdk.LDAPException;

import io.quarkus.test.common.WithTestResource;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.ldap.LdapServerTestResource;
import io.restassured.RestAssured;

@WithTestResource(LdapServerTestResource.class)
@QuarkusTest
class ElytronSecurityLdapTest {

Expand Down Expand Up @@ -96,9 +98,31 @@ void admin_role_not_authorized() {
.statusCode(403);
}

@Test()
@Test
@Order(8)
void standard_role_authenticated_cached() throws LDAPException {
void testMappingOfLdapGroupsToIdentityRoles() {
// LDAP groups are added as SecurityIdentity roles
// according to the quarkus.security.ldap.identity-mapping.attribute-mappings
// this test verifies that LDAP groups can be remapped to application-specific SecurityIdentity roles
// role 'adminRole' comes from 'cn' and we remapped it to 'root'
RestAssured.given()
.auth().preemptive().basic("standardUser", "standardUserPassword")
.when()
.get("/api/requiresRootRole")
.then()
.statusCode(403);
RestAssured.given()
.auth().preemptive().basic("adminUser", "adminUserPassword")
.when()
.get("/api/requiresRootRole")
.then()
.statusCode(200)
.body(containsString("adminUser")); // that is uid
}

@Test
@Order(9)
void standard_role_authenticated_cached() {
RestAssured.given()
.redirects().follow(false)
.when()
Expand Down

0 comments on commit d0e6e24

Please sign in to comment.