การแมปบทบาทภายนอกช่วยให้คุณแมปกลุ่มหรือบทบาทของคุณเองกับการควบคุมการเข้าถึงตามบทบาทได้ (RBAC) บทบาทและกลุ่มที่สร้างใน Apigee Edge ฟีเจอร์นี้ใช้ได้กับ Edge เท่านั้นสำหรับ Private Cloud
ข้อกำหนดเบื้องต้น
- คุณต้องเป็นผู้ดูแลระบบ Apigee Private Cloud ที่มีผู้ดูแลระบบส่วนกลาง ข้อมูลเข้าสู่ระบบในการกำหนดค่านี้
- คุณจำเป็นต้องทราบไดเรกทอรีรูทของการติดตั้ง Apigee Edge Private Cloud
ไดเรกทอรีรากเริ่มต้นคือ
/opt
ตัวอย่างการตั้งค่าแบบทีละขั้นตอน
โปรดดู บทความนี้ในฟอรัมชุมชน Apigee สำหรับตัวอย่างทีละขั้นตอนในการตั้งค่า การแมปบทบาท
การกำหนดค่าเริ่มต้น
การแมปบทบาทภายนอกจะปิดใช้อยู่โดยค่าเริ่มต้น
เปิดใช้การแมปบทบาทภายนอก
วิธีเปิดใช้การแมปบทบาทภายนอก
- ก่อนที่คุณจะสามารถกำหนดค่าต่อไปนี้ให้เสร็จสมบูรณ์ คุณต้องสร้างคลาส Java ที่
ใช้งานอินเทอร์เฟซ ExternalRoleMapperServiceV2 และรวมการติดตั้งใช้งานของคุณใน
classpath ของเซิร์ฟเวอร์การจัดการ:
/opt/apigee/edge-management-server/lib/thirdparty/
สำหรับรายละเอียดเกี่ยวกับการติดตั้งนี้ โปรดดูที่ส่วนเกี่ยวกับ ExternalRoleMapperImpl ตัวอย่างการติดตั้งใช้งานภายหลังในเอกสารนี้
- เข้าสู่ระบบเซิร์ฟเวอร์การจัดการ Apigee Edge แล้วหยุดกระบวนการของเซิร์ฟเวอร์การจัดการโดยทำดังนี้
/opt/apigee/apigee-service/bin/apigee-service edge-management-server stop
- เปิด
/opt/apigee/customer/application/management-server.properties
ในเครื่องมือแก้ไขข้อความ หากไม่มี ให้สร้างไฟล์นี้ - แก้ไขไฟล์คุณสมบัติเพื่อตั้งค่าต่อไปนี้
# The user store to be used for authentication.
# Use "externalized.authentication" for LDAP user store.
# Note that for authorization, we continue to use LDAP.
# See Enabling external authentication more on enabling external auth.
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 - บันทึกไฟล์
management-server.properties
- ตรวจสอบว่าผู้ใช้ Apigee เป็นเจ้าของ
management-server.properties
ดังนี้ วันที่chown apigee:apigee /opt/apigee/customer/application/management-server.properties
- เริ่มต้นเซิร์ฟเวอร์การจัดการด้วยคำสั่งต่อไปนี้
/opt/apigee/apigee-service/bin/apigee-service edge-management-server start
ปิดใช้การให้สิทธิ์ภายนอก
ในการปิดใช้งานการให้สิทธิ์ภายนอก:
- เปิด
/opt/apigee/customer/application/management-server.properties
ในเครื่องมือแก้ไขข้อความ หากไม่มีไฟล์ ให้สร้างขึ้นมา - เปลี่ยนที่เก็บผู้ใช้การตรวจสอบสิทธิ์เป็น "LDAP":
conf_security_authentication.user.store=ldap
- ตั้งค่าพร็อพเพอร์ตี้นี้เป็น "เท็จ"
conf_security_externalized.authentication.role.mapper.enabled=false
- รีสตาร์ทเซิร์ฟเวอร์การจัดการ
/opt/apigee/apigee-service/bin/apigee-service edge-management-server start
เกี่ยวกับ ExternalRoleMapperImpl ตัวอย่างการใช้งาน
ในไฟล์การกำหนดค่า Security.properties ซึ่งอธิบายไว้ก่อนหน้านี้ในการเปิดใช้การแมปบทบาทภายนอก โปรดระบุบรรทัดต่อไปนี้
externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl
คลาสนี้ใช้อินเทอร์เฟซ ExternalRoleMapperServiceV2 และจำเป็นต้องใช้ สิ่งที่คุณต้องทำ สร้างการใช้งานคลาสนี้ของคุณเอง ซึ่งสะท้อนให้เห็นถึงกลุ่มของคุณ เมื่อเสร็จแล้ว วางคลาสที่คอมไพล์ใน JAR และใส่ JAR นั้นในคลาสพาธของเซิร์ฟเวอร์การจัดการใน
/opt/apigee/edge-management-server/lib/thirdparty/
คุณสามารถตั้งชื่อคลาสและแพ็กเกจได้ตามต้องการ ExternalRoleMapperServiceV2 สามารถเข้าถึงได้ใน classpath ของคุณ และมีการอ้างอิงอย่างถูกต้องใน Management-server.properties
ต่อไปนี้เป็นตัวอย่างการใช้งานคลาส ExternalRoleMapperImpl
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)));
// In OPDK 4.50 and later, do
// results.add(new NameSpacedRole("orgadmin", OrganizationNamespace.of(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();
}
}