Edge for Private Cloud v4.18.01
Mit der externen Rollenzuordnung können Sie Ihre eigenen Gruppen oder Rollen den Rollen und Gruppen der rollenbasierten Zugriffssteuerung (Role-Based Access Control, RBAC) zuordnen, die in Apigee Edge erstellt wurden. Diese Funktion ist nur mit Edge Private Cloud verfügbar.
Neue Funktionen
Der Dienst für die externe Rollenzuordnung für Edge for Private Cloud-Releases vor 4.18.01 wurde verworfen. Release 4.18.01 der externen Rollenzuordnung ist eine aktualisierte Version mit Fehlerkorrekturen und neuen Funktionen:
- Das Problem, dass Sie bei der Authentifizierung von Nutzern, die Zugriff haben sollten, die Antwort „403 Forbidden“ erhalten haben, wurde behoben.
- Der Header X-Apigee-Current-User wird jetzt in der externen Rollenzuordnung unterstützt. Nutzer mit den entsprechenden Zugriffsrechten (sysadmin) können jetzt die Rollen sehen, die einem anderen Nutzer zugewiesen sind.
Vorbereitung
- Sie müssen ein Apigee Private Cloud-Systemadministrator mit globalen Systemadministrator-Anmeldedaten sein, um diese Konfiguration auszuführen.
-
Sie müssen das Stammverzeichnis Ihrer Apigee Edge Private Cloud-Installation kennen. Das Standardstammverzeichnis ist /opt.
Beispiel für eine schrittweise Einrichtung
Eine detaillierte Anleitung zum Einrichten der externen Rollenzuordnung finden Sie in diesem Artikel in den Apigee-Community-Foren.
Standardkonfiguration
Die externe Rollenzuordnung ist standardmäßig deaktiviert.
Externe Rollenzuordnung aktivieren
- Bevor Sie die folgende Konfiguration abschließen können, müssen Sie eine Java-Klasse erstellen, die die ExternalRoleMapperServiceV2-Schnittstelle implementiert, und Ihre Implementierung in den Management Server-Klassenpfad einfügen:
/opt/apigee/edge-management-server/lib/thirdparty/
Weitere Informationen zu dieser Implementierung finden Sie im Abschnitt Über die Beispielimplementierung ExternalRoleMapperImpl weiter unten in diesem Dokument. - Melden Sie sich auf Ihrem Apigee Edge-Verwaltungsserver an und beenden Sie dann den Prozess des Verwaltungsservers:
> /opt/apigee/apigee-service/bin/apigee-service edge-management-server stop - Öffnen Sie /opt/apigee/customer/application/management-server.properties in einem Texteditor. Wenn diese Datei nicht vorhanden ist, erstellen Sie sie.
- Bearbeiten Sie die Attributdatei, um die folgenden Einstellungen vorzunehmen:
# The user store to be used for authentication.
# Verwenden Sie „externalized.authentication“ für den LDAP-Nutzerstore.
# Note that for authorization, we continue to use LDAP.
# Weitere Informationen zum Aktivieren der externen Authentifizierung finden Sie unter Externe Authentifizierung aktivieren.
conf_security_authentication.user.store=externalized.authentication
#Enable the external authorizations role mapper.
conf_security_externalized.authentication.role.mapper.enabled=true conf_security_externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl
Wichtig: Die Implementierungsklasse und der Paketname, auf die in der obigen Konfiguration verwiesen wird (ExternalRoleMapperImpl), sind nur Beispiele. Es handelt sich um eine Klasse, die Sie implementieren müssen und die Sie beliebig benennen können. Weitere Informationen zur Implementierung dieser Klasse finden Sie unten im Abschnitt Beispielimplementierung der Klasse „ExternalRoleMapperImpl“. Diese Klasse müssen Sie implementieren, um Ihre eigenen Gruppen widerzuspiegeln. - Speichern Sie die Datei management-server.properties.
- Prüfen Sie, ob management-server.properties dem Apigee-Nutzer gehört:
> chown apigee:apigee /opt/apigee/customer/application/management-server.properties - Starten Sie den Management Server:
> /opt/apigee/apigee-service/bin/apigee-service edge-management-server start
Externe Autorisierung deaktivieren
So deaktivieren Sie die externe Autorisierung:
- Öffnen Sie /opt/apigee/customer/application/management-server.properties in einem Texteditor. Wenn die Datei nicht vorhanden ist, erstellen Sie sie.
- Ändern Sie den Authentifizierungsnutzerspeicher in ldap:
conf_security_authentication.user.store=ldap - Legen Sie für dieses Attribut den Wert „false“ fest:
conf_security_externalized.authentication.role.mapper.enabled=false - Starten Sie den Management Server neu:
> /opt/apigee/apigee-service/bin/apigee-service edge-management-server start
Beispielimplementierung von ExternalRoleMapperImpl
In der Konfigurationsdatei „security.properties“, die zuvor unter Externe Rollenzuordnung aktivieren beschrieben wurde, finden Sie diese Zeile:
externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl
Diese Klasse implementiert die Schnittstelle „ExternalRoleMapperServiceV2“ und ist erforderlich. Sie müssen eine eigene Implementierung dieser Klasse erstellen, die Ihre jeweiligen Gruppen widerspiegelt. Wenn Sie fertig sind, fügen Sie die kompilierte Klasse in eine JAR-Datei ein und platzieren Sie diese JAR-Datei im Klassenpfad des Management Servers unter:
/opt/apigee/edge-management-server/lib/thirdparty/
Sie können die Klasse und das Paket beliebig benennen, solange sie ExternalRoleMapperServiceV2 implementieren, in Ihrem Klassenpfad zugänglich sind und in der Konfigurationsdatei „management-server.properties“ korrekt referenziert werden.
Im Folgenden finden Sie eine gut kommentierte Beispielimplementierung einer ExternalRoleMapperImpl-Klasse.
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 javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; /** * * Sample Implementation constructed with dummy roles with expected namespaces. */ public class ExternalRoleMapperImpl implements ExternalRoleMapperServiceV2 { InitialDirContext dirContext = null; @Override public void start(ConfigBean arg0) throws ConnectionException { try { // Customer Specific Implementation will override the // ImplementDirContextCreationLogicForSysAdmin method implementation. // Create InitialDirContext based on the system admin user credentials. dirContext = ImplementDirContextCreationLogicForSysAdmin(); } catch (NamingException e) { // TODO Auto-generated catch block throw new ConnectionException(e); } } @Override public void stop() throws Exception { } /** * This method should be replaced with customer's implementation * For given roleName under expectedNamespace, return all users that belongs to this role * @param roleName * @param expectedNamespace * @return All users that belongs to this role. For each user, please return the username/email that is stored in Apigee LDAP * @throws ExternalRoleMappingException */ @Override public Collection<String> getUsersForRole(String roleName, NameSpace expectedNamespace) throws ExternalRoleMappingException { Collection<String> users = new HashSet<>(); if (expectedNamespace instanceof SystemNamespace) { // If requesting all users with sysadmin role if (roleName.equalsIgnoreCase("sysadmin")) { // Add sysadmin's email to results users.add("sysadmin@wacapps.net"); } } else { String orgName = ((OrganizationNamespace) expectedNamespace).getOrganization(); // If requesting all users of engRole in Apigee LDAP if (roleName.equalsIgnoreCase("engRole")) { // Get all users in corresponding groups in customer's LDAP. In this case looking for 'engGroup'; SearchControls controls = new SearchControls(); controls.setSearchScope(1); try { NamingEnumeration<SearchResult> res = dirContext.search("ou=groups,dc=corp,dc=wacapps,dc=net", "cn=engGroup", new Object[]{"",""}, controls); while (res.hasMoreElements()) { SearchResult sr = res.nextElement(); // Add all users into return users.addAll(sr.getAttributes().get("users").getAll()); } } catch (NamingException e) { // Customer needs to handle the exception here } } } return users; } /** * * This method would be implemented by the customer and would be invoked * while including using X-Apigee-Current-User header in request. * * X-Apigee-Current-User allows the customer to login as another user * * Below is the basic example. * * If User has sysadmin role then it's expected to set SystemNameSpace * along with the expected NameSpace. Otherwise role's expectedNameSpace * to be set for the NameSpacedRole. * * Collection<NameSpacedRole> results = new HashSet<NameSpacedRole>(); * * NameSpacedRole sysNameSpace = new NameSpacedRole("sysadmin", * SystemNamespace.get()); * * String orgName = * ((OrganizationNamespace) expectedNameSpace).getOrganization(); * * NameSpacedRole orgNameSpace = new NameSpacedRole ("orgadmin", * expectedNameSpace); * * results.add(sysNameSpace); * * results.add(orgNameSpace); * * * @param username UserA's username * @param password UserA's password * @param requestedUsername UserB's username. Allow UserA to request UserB's userroles with * UserA's credentials when requesting UserB as X-Apigee-Current-User * @param expectedNamespace * @return * @throws ExternalRoleMappingException */ @Override public Collection<NameSpacedRole> getUserRoles(String username, String password, String requestedUsername, NameSpace expectedNamespace) throws ExternalRoleMappingException { /************************************************************/ /******************** Authenticate UserA ********************/ /************************************************************/ // Customer Specific Implementation will override the // ImplementDnameLookupLogic method implementation. // obtain dnName for given username. String dnName = ImplementDnNameLookupLogic(username); // Obtain dnName for given requestedUsername. String requestedDnName = ImplementDnNameLookupLogic(requestedUsername); if (dnName == null || requestedDnName == null) { System.out.println("Error "); } DirContext dirContext = null; try { // Customer Specific Implementation will override the // ImplementDirectoryContextCreationLogic method implementation // Create a directory context with dnName or requestedDnName and password dirContext = ImplementDirectoryContextCreationLogic(); /************************************************/ /*** Map internal groups to apigee-edge roles ***/ /************************************************/ return apigeeEdgeRoleMapper(dirContext, requestedDnName, expectedNamespace); } catch (Exception ex) { ex.printStackTrace(); System.out.println("Error in authenticating User: {}" + new Object[] { username }); } finally { // Customer implementation to close // ActiveDirectory/LDAP context. } return null; } /** * * This method would be implemented by the customer and would be invoked * wihle using username and password for authentication and without the * X-Apigee-Current-User header * * The customer can reuse implementations in * getUserRoles(String username, String password, String requestedUsername, NameSpace expectedNamespace) * by * return getUserRoles(username, password, username, expectedNamespace) * in implementations. * * or the customer can provide new implementations as shown below. */ @Override public Collection<NameSpacedRole> getUserRoles(String username, String password, NameSpace expectedNamespace) throws ExternalRoleMappingException { /*************************************************************/ /****************** Authenticate Given User ******************/ /*************************************************************/ // Customer Specific Implementation will override the // ImplementDnameLookupLogic implementation. // Obtain dnName for given username or email address. String dnName = ImplementDnNameLookupLogic(username); if (dnName == null) { System.out.println("Error "); } DirContext dirContext = null; try { // Create a directory context with username or dnName and password dirContext = ImplementDirectoryContextCreationLogic(); /************************************************/ /*** Map internal groups to apigee-edge roles ***/ /************************************************/ return apigeeEdgeRoleMapper(dirContext, dnName, expectedNamespace); } catch (Exception ex) { ex.printStackTrace(); System.out.println("Error in authenticating User: {}" + new Object[] { username }); } finally { // Customer implementation to close // ActiveDirectory/LDAP context. } return null; } /** * * This method would be implemented by the customer and would be invoked * while using security token or access token as authentication credentials. * */ @Override public Collection<NameSpacedRole> getUserRoles(String username, NameSpace expectedNamespace) throws ExternalRoleMappingException { /*************************************************************/ /****************** Authenticate Given User ******************/ /*************************************************************/ // Customer Specific Implementation will override the // ImplementDnameLookupLogic implementation. // Obtain dnName for given username or email address. String dnName = ImplementDnNameLookupLogic(username); if (dnName == null) { System.out.println("Error "); } DirContext dirContext = null; try { // Create a directory context with username or dnName and password dirContext = ImplementDirectoryContextCreationLogic(); /************************************************/ /*** Map internal groups to apigee-edge roles ***/ /************************************************/ return apigeeEdgeRoleMapper(dirContext, dnName, expectedNamespace); } catch (Exception ex) { ex.printStackTrace(); System.out.println("Error in authenticating User: {}" + new Object[] { username }); } finally { // Customer implementation to close // ActiveDirectory/LDAP context. } return null; } /** * This method should be replaced with Customer Specific Implementations * * Provided as a sample Implementation of mapping user groups to apigee-edge roles */ private Collection<NameSpacedRole> apigeeEdgeRoleMapper(DirContext dirContext, String dnName, NameSpace expectedNamespace) throws Exception { Collection<NameSpacedRole> results = new HashSet<NameSpacedRole>(); /****************************************************/ /************ Fetch internal groups *****************/ /****************************************************/ String groupDN = "OU=Groups,DC=corp,DC=wacapps,DC=net"; String userFilter = "(user=userDnName)"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // Looking for all groups the user belongs to in customer's LDAP NamingEnumeration<SearchResult> groups = dirContext.search(groupDN,userFilter.replace("userDnName", dnName), new Object[] { "", "" }, controls); if (groups.hasMoreElements()) { while (groups.hasMoreElements()) { SearchResult searchResult = groups.nextElement(); Attributes attributes = searchResult.getAttributes(); String groupName = attributes.get("name").get().toString(); /************************************************/ /*** Map internal groups to apigee-edge roles ***/ /************************************************/ if (groupName.equals("BusDev")) { results.add(new NameSpacedRole("businessAdmin",SystemNamespace.get())); } else if (groupName.equals("Engineering")) { if (expectedNamespace instanceof OrganizationNamespace) { String orgName = ((OrganizationNamespace) expectedNamespace).getOrganization(); results.add(new NameSpacedRole("orgadmin", new OrganizationNamespace(orgName))); } } else if (groupName.equals("Marketing")) { results.add(new NameSpacedRole("marketAdmin",SystemNamespace.get())); } else { results.add(new NameSpacedRole("readOnly",SystemNamespace.get())); } } } else { // In case of no group found or exception found we throw empty roles. System.out.println(" !!!!! NO GROUPS FOUND !!!!!"); } return results; } /** * The customer need to replace with own implementations for getting dnName for given user */ private String ImplementDnNameLookupLogic(String username) { // Connect to the customer's own LDAP to fetch user dnName return customerLDAP.getDnName(username); } /** * The customer need to replace with own implementations for creating DirContext */ private DirContext ImplementDirectoryContextCreationLogic() { // Connect to the customer's own LDAP to create DirContext for given user return customerLDAP.createLdapContextUsingCredentials(); } }