Edge สำหรับ Private Cloud เวอร์ชัน 4.18.01
การแมปบทบาทภายนอกช่วยให้คุณแมปกลุ่มหรือบทบาทของคุณเองกับบทบาทและการควบคุมการเข้าถึงตามบทบาท (RBAC) และกลุ่มที่สร้างใน Apigee Edge ได้ ฟีเจอร์นี้ใช้ได้กับ Edge Private Cloud เท่านั้น
มีอะไรใหม่
เลิกใช้งานบริการการแมปบทบาทภายนอกสำหรับ Edge สำหรับ Private Cloud รุ่นก่อน 4.18.01 แล้ว รุ่น 4.18.01 ของการแมปบทบาทภายนอกคือเวอร์ชันอัปเดตที่มีการแก้ไขข้อบกพร่อง และเพิ่มฟีเจอร์ใหม่เข้ามา
- แก้ไขปัญหาที่คุณได้รับคำตอบต้องห้ามในการตรวจสอบสิทธิ์ 403 เมื่อตรวจสอบสิทธิ์กับผู้ใช้ที่ควรมีสิทธิ์เข้าถึง
- รองรับส่วนหัว X-Apigee-Current-User ในการแมปบทบาทภายนอกแล้ว ผู้ใช้ที่มีสิทธิ์การเข้าถึงที่เหมาะสม (ผู้ดูแลระบบ) จะสามารถดูบทบาทที่กำหนดให้กับผู้ใช้รายอื่นได้
ข้อกำหนดเบื้องต้น
- คุณต้องเป็นผู้ดูแลระบบ Apigee Private Cloud ที่มีข้อมูลเข้าสู่ระบบของผู้ดูแลระบบส่วนกลางจึงจะกำหนดค่านี้ได้
-
คุณจำเป็นต้องทราบไดเรกทอรีรูทของการติดตั้ง Apigee Edge Private Cloud ของคุณ ไดเรกทอรีรากเริ่มต้นคือ /opt
ตัวอย่างการตั้งค่าแบบทีละขั้นตอน
ดูตัวอย่างแบบทีละขั้นตอนของการตั้งค่าการแมปบทบาทภายนอกได้ที่ บทความนี้ในฟอรัมชุมชน Apigee
การกำหนดค่าเริ่มต้น
การแมปบทบาทภายนอกจะปิดใช้อยู่โดยค่าเริ่มต้น
การเปิดใช้การจับคู่บทบาทภายนอก
- ก่อนที่คุณจะกำหนดค่าต่อไปนี้ให้เสร็จสมบูรณ์ได้ คุณต้องสร้างคลาส Java ที่ใช้งานอินเทอร์เฟซ ExternalRoleMapperServiceV2 และรวมการใช้งานของคุณในคลาสพาธเซิร์ฟเวอร์การจัดการ:
/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 ในเครื่องมือแก้ไขข้อความ หากไม่มีไฟล์นี้ ให้สร้างขึ้นมา
- แก้ไขไฟล์พร็อพเพอร์ตี้เพื่อสร้างการตั้งค่าต่อไปนี้
# ร้านค้าของผู้ใช้ที่จะใช้สำหรับการตรวจสอบสิทธิ์
# ใช้ "externalized.authentication" สำหรับร้านค้าผู้ใช้ LDAP
# โปรดทราบว่าเราจะใช้ LDAP ต่อไปสำหรับการให้สิทธิ์
# ดูข้อมูลเพิ่มเติมเรื่องการเปิดใช้การตรวจสอบสิทธิ์ภายนอกเกี่ยวกับการเปิดใช้การตรวจสอบสิทธิ์ภายนอก
conf_security_authentication.user.store=externalized.authentication
#เปิดใช้ตัวแมปบทบาทการให้สิทธิ์ภายนอก
conf_security_externalized.authentication.role.mapper.enabled=true conf_security_externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl
สำคัญ: คลาสการติดตั้งใช้งานและชื่อแพ็กเกจต้องอ้างอิงในการกำหนดค่าด้านบน (ExternalRoleMapperImpl)
สำคัญ: คลาสการติดตั้งใช้งานและชื่อแพ็กเกจต้องอ้างอิงในการกำหนดค่าข้างต้น (ExternalRoleMapperImpl) ที่คุณต้องการเท่านั้น โปรดดูรายละเอียดเกี่ยวกับการติดตั้งใช้งานคลาสนี้ที่หัวข้อเกี่ยวกับคลาสตัวอย่างการติดตั้งใช้งาน ExternalRoleMapperImpl ด้านล่าง นี่คือคลาสที่คุณต้องใช้เพื่อแสดงถึงกลุ่มของคุณเอง - บันทึกไฟล์ management-server.properties
- ตรวจสอบว่า management-server.properties เป็นของผู้ใช้ Apigee หรือไม่
> 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))); } } 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(); } }