External Role Mapping V2- Step by Step Guide
External Role mapping is a new feature introduced in Apigee Edge 4.18.01 that allows you to map your corporate ldap groups to Apigee Edge roles. This is available only in Private cloud.
This article explains step by step guide to setting up External Role Mapping in Apigee Edge. I assume you have setup Apigee Edge private cloud 4.18.01.
Step 0 : External(Corp) LDAP Setup
Let’s assume the external LDAP DSE looks like as shown below :
In this example, the BASE DN is dc=tech-brief,dc=apigee-demo,dc=net. There are three groups sysadmin, Eng and BusDev defined in LDAP and users are associated with these groups.
For ex , the BusDev attributes would look like this :
Similarly a test5@apigee-demo.net user attributes looks like this :
I have also created sysadmin for Apigee Edge - opdk@apigee.com as a user in External LDAP. For simplicity, I have kept the ldap password for opdk@apigee.com same as that I had set during Apigee Edge setup.
Step 1 :Setup Apigee Edge with external LDAP authentication
For External Role mapping to work, you need to first setup Apigee Edge with External LDAP authentication. You can refer here for more details about how to set up.
To setup external ldap authentication, add following properties in /opt/apigee/customer/application/management-server.properties
conf_security_authentication.user.store=externalized.authentication
## Required to enable the external authorization feature. Do not change it.
conf_security_externalized.authentication.implementation.class=com.apigee.rbac.impl.LdapAuthenticatorImpl
conf_security_externalized.authentication.bind.direct.type=false
## The next seven properties are needed regardless of direct or indirect binding. You need to configure these per your external LDAP installation.
## The IP or domain for your external LDAP instance.
conf_security_externalized.authentication.server.url=ldap://tech-brief-ldap.apigee-demo.net:389
## Replace with your external LDAP server version.
conf_security_externalized.authentication.server.version=3
## Set the server timeout in milliseconds.
conf_security_externalized.authentication.server.conn.timeout=50000
conf_security_externalized.authentication.user.store.baseDN=dc=tech-brief,dc=apigee-demo,dc=net
## Do not change this search string. It is used internally.
conf_security_externalized.authentication.user.store.search.query=(&(${userAttribute}=${userId}))
conf_security_externalized.authentication.user.store.user.attribute=mail
conf_security_externalized.authentication.user.store.user.email.attribute=mail
conf_security_externalized.authentication.indirect.bind.server.admin.dn=mail=opdk@apigee.com,ou=users,ou=global,dc=tech-brief,dc=apigee-demo,dc=net
conf_security_externalized.authentication.indirect.bind.server.admin.password=XXXXXXX
conf_security_externalized.authentication.indirect.bind.server.admin.password.encrypted=false
Restart management server to take affect these properties. This will setup external apigee edge with External LDAP authentication with indirect binding. I assume that opdk@apigee.com is sysadmin for Apigee Edge and that user is also present in External LDAP.
Test the external LDAP authentication by logging with LDAP password of users created in Apigee Edge.
Step 2 : Java Rolemapper Implementation
Create a Java class that implements ExternalRoleMapperServiceV2 interface. Refer here for more details.
An example java class is given below
package com.customer.authorization.impl;
import com.apigee.authentication.*;
import com.apigee.authorization.namespace.OrganizationNamespace;
import com.apigee.authorization.namespace.SystemNamespace;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Hashtable;
import java.util.HashMap;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
public class ExternalRoleMapperImpl implements ExternalRoleMapperServiceV2{
private static final String DEFAULT_LDAP_INTIAL_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String DEFAULT_AUTHENTICATION_TYPE = "simple";
private static final String DEFAULT_LDAP_URL = "ldap://tech-brief-ldap.apigee-demo.net:389";
private static final String ADMIN_DN = "mail=opdk@apigee.com,ou=users,ou=global,dc=tech-brief,dc=apigee-demo,dc
=net";
private static final String ADMIN_SECRET = "Secret123";
private static final String groupDN = "ou=Group,ou=global,dc=tech-brief,dc=apigee-demo,dc=net";
private static final String GROUP = "Group";
private static final String DEFAULT_ORG = "tech-brief";
private DirContext initialDirContext;
private SearchControls controls = new SearchControls();
@Override
public Collection<NameSpacedRole> getUserRoles(String username, String password, String requestedUsername, NameSpace expectedNamespace) throws ExternalRoleMappingException {
return getUserRoles(requestedUsername, expectedNamespace);
}
@Override
public Collection<NameSpacedRole> getUserRoles(String username, NameSpace expectedNamespace) throws ExternalRoleMappingException {
Collection<NameSpacedRole> roles = new HashSet<>();
String orgName = "tech-brief";
System.out.println("Getting Group");
String userGroupFilter = "(memberUid=uid)";
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
try {
/***************************************************/
/************** Fetch groups for user **************/
/***************************************************/
NamingEnumeration<SearchResult> groupResults = initialDirContext.search(groupDN, userGroupFilter.replace("uid", username), new Object[] { "", "" }, controls);
while (groupResults.hasMoreElements()) {
SearchResult searchResult = groupResults.nextElement();
Attributes attributes = searchResult.getAttributes();
String groupName = attributes.get("cn").get().toString();
if (groupName.equals("BusDev")) {
roles.add(new NameSpacedRole("businessuser",new OrganizationNamespace(orgName)));
} else if (groupName.equals("Eng")) {
roles.add(new NameSpacedRole("user",new OrganizationNamespace(orgName)));
} else if (groupName.equals("sysadmin")) {
roles.add(new NameSpacedRole("orgadmin",new OrganizationNamespace(orgName)));
roles.add(new NameSpacedRole("sysadmin",SystemNamespace.get()));
} else {
roles.add(new NameSpacedRole("user", new OrganizationNamespace(orgName)));
}
//groups.add(groupName);
}
} catch (NamingException e) {
e.printStackTrace();
throw new ExternalTeamMappingException(e);
}
return roles;
}
@Override
public Collection<String> getUsersForRole(String roleName, NameSpace expectedNamespace) throws ExternalRoleMappingException {
//Collection<String> members = new HashSet<>();
Collection<String> users = new HashSet<>();
String groupName="";
if (roleName.equalsIgnoreCase("sysadmin")) {
groupName = "sysadmin";
} else if(roleName.equalsIgnoreCase("orgadmin")) {
groupName = "sysadmin";
} else if (roleName.equalsIgnoreCase("user")) {
groupName = "Eng";
} else if (roleName.equalsIgnoreCase("businessuser")) {
groupName = "BusDev";
}
String groupFilter = "(cn=groupName)";
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
try{
NamingEnumeration<SearchResult> groupResults = initialDirContext.search(groupDN, groupFilter.replace("groupName", groupName), new Object[] { "", "" }, controls);
while (groupResults.hasMoreElements()) {
SearchResult searchResult = groupResults.nextElement();
Attributes attributes = searchResult.getAttributes();
if (attributes.get("memberUid") == null) {
continue;
}
NamingEnumeration<?> memberUids = attributes.get("memberUid").getAll();
while (memberUids.hasMoreElements()) {
users.add(memberUids.next().toString());
}
}
} catch (NamingException e) {
e.printStackTrace();
throw new ExternalTeamMappingException(e);
}
return users;
}
@Override
public void start(ConfigBean configBean) throws ConnectionException {
Hashtable<String, String> environment = new Hashtable<>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_LDAP_INTIAL_CONTEXT_FACTORY);
environment.put(Context.SECURITY_AUTHENTICATION, DEFAULT_AUTHENTICATION_TYPE);
environment.put(Context.SECURITY_PRINCIPAL, ADMIN_DN);
environment.put(Context.SECURITY_CREDENTIALS, ADMIN_SECRET);
environment.put(Context.PROVIDER_URL, DEFAULT_LDAP_URL);
// connect to LDAP
try {
initialDirContext = new InitialDirContext(environment);
} catch (NamingException e) {
e.printStackTrace();
}
}
@Override
public void stop() throws Exception {
}
@Override
public Collection<NameSpacedRole> getUserRoles(String username, String password, NameSpace expectedNamespace) throws ExternalRoleMappingException {
return getUserRoles(username, expectedNamespace);
}
}
We are mapping Eng group of LDAP to users role and BusDev group to businessuser role of Apigee Edge. You can write complex mapping by overriding these methods.We have initialized LDAPContext with external LDAP details and overridden two methods - getUserRoles and getUserForRoles.
Take this code sample from above and put in a following directory structure in management server
Compile the code and create jar files and move the created jar file to /opt/apigee/edge-management-server/lib/thirdparty/
$ cd tech-brief/java
$ javac -d bin -sourcepath src -cp /opt/apigee/edge-management-server/lib/infra/libraries/authentication-1.0.0.jar src/com/customer/authorization/impl/ExternalRoleMapperImpl.java
$ cd bin
$ jar cvf externalrolemapper.jar *
$ mv externalrolemapper.jar /opt/apigee/edge-management-server/lib/thirdparty/externalrolemapper.jar
Step 3 : Setup External Role Mapping Settings in Management Server
The next step is to update management-server.properties you had set in step 1 to support External Authorization
Add following properties in /opt/apigee/customer/application/management-server.properties
conf_security_externalized.authentication.role.mapper.enabled=trueconf_security_externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl
Restart Management Server
Step 4 : How to Test
- Add a user say test9@apigee-demo.net in External LDAP and associate it with Eng Group.
- Login Apigee Edge UI with Org Admin credentials.
- Add a user test9@apigee-demo.net from Admin->Users console and assign it to Org Admin Role. This step adds new user in Apigee Edge.
- Remove Users Role from that Org so that the new user doesn’t have any associated role.
Logout and try logging Apigee Edge with new user (test9@apigee-demo.net). test9 now is associated with Users role of Apigee Edge.



