Pemetaan Peran Eksternal

Edge untuk Private Cloud v4.18.01

Dengan Pemetaan Peran Eksternal, Anda dapat memetakan grup atau peran Anda sendiri ke peran kontrol akses berbasis peran (RBAC) dan grup yang dibuat di Apigee Edge. Fitur ini hanya tersedia di Edge Private Cloud.

Yang Baru

Layanan Pemetaan Peran Eksternal bagi Edge untuk rilis Private Cloud sebelum 4.18.01 tidak digunakan lagi. Rilis 4.18.01 dari Pemetaan Peran Eksternal adalah versi terbaru dengan perbaikan bug dan penambahan fitur baru:

  • Memperbaiki masalah saat Anda menerima respons terlarang 403 autentikasi saat melakukan autentikasi dengan pengguna yang seharusnya memiliki akses.
  • Header X-Apigee-Current-User kini didukung di Pemetaan Peran Eksternal. Pengguna dengan akses yang tepat (sysadmin) kini dapat melihat peran yang ditetapkan kepada pengguna lain.

Prasyarat

  • Anda harus menjadi administrator sistem Apigee Private Cloud dengan kredensial admin sistem global untuk menjalankan konfigurasi ini.
  • Anda perlu mengetahui direktori utama penginstalan Apigee Edge Private Cloud Anda. Direktori utama default adalah /opt.

Contoh penyiapan langkah demi langkah

Baca artikel ini di Forum Komunitas Apigee untuk mengetahui contoh langkah demi langkah penyiapan pemetaan peran eksternal.

Konfigurasi default

Pemetaan peran eksternal dinonaktifkan secara default.

Mengaktifkan Pemetaan Peran Eksternal

  1. Sebelum dapat menyelesaikan konfigurasi berikut, Anda harus membuat class Java yang menerapkan antarmuka ExternalRoleMapperServiceV2 dan menyertakan implementasi Anda dalam classpath Management Server:

    /opt/apigee/edge-management-server/lib/thirdparty/

    Untuk mengetahui detail tentang penerapan ini, lihat bagian Tentang penerapan contoh ExternalRoleMapperImpl di bagian selanjutnya dalam dokumen ini.
  2. Login ke server pengelolaan Apigee Edge Anda, lalu hentikan proses server pengelolaan:
    > /opt/apigee/apigee-service/bin/apigee-service edge-management-server stop
  3. Buka /opt/apigee/customer/application/management-server.properties di editor teks. Jika file ini tidak ada, buatlah file tersebut.
  4. Edit file properti untuk membuat setelan berikut:
    # Penyimpanan pengguna yang akan digunakan untuk autentikasi.
    # Gunakan "externalized.authentication" untuk penyimpanan pengguna LDAP.
    # Perlu diketahui bahwa untuk otorisasi, kami terus menggunakan LDAP.
    # Lihat Mengaktifkan autentikasi eksternal selengkapnya tentang cara mengaktifkan autentikasi eksternal.
    conf_security_authentication.user.store=externalized.authentication

    #Mengaktifkan mapper peran otorisasi eksternal.
    conf_security_externalized.authentication.role.mapper.enabled=true conf_security_externalized.authentication.role.mapper.implementation.class=
    com.customer.authorization.impl.ExternalRoleMapperImpl

    Penting:
    Class penerapan dan nama paket yang direferensikan dalam konfigurasi di atas (ExternalRoleMapperImpl) hanyalah contoh yang Anda inginkan dan nama class yang dapat Anda terapkan Untuk mengetahui detail tentang penerapan class ini, lihat Tentang penerapan contoh ExternalRoleMapperImpl di bawah. Ini adalah class yang harus diimplementasikan untuk mencerminkan grup Anda sendiri.
  5. Simpan file management-server.properties.
  6. Pastikan management-server.properties dimiliki oleh pengguna apigee:?
    > chown apigee:apigee /opt/apigee/customer/application/management-server.properties
  7. Mulai server pengelolaan:
    > /opt/apigee/apigee-service/bin/apigee-service edge-management-server start

Menonaktifkan Otorisasi Eksternal

Untuk menonaktifkan otorisasi eksternal:

  1. Buka /opt/apigee/customer/application/management-server.properties di editor teks. Jika file tidak ada, buat file tersebut.
  2. Ubah penyimpanan pengguna autentikasi ke ldap:
    conf_security_authentication.user.store=ldap
  3. Tetapkan properti ini ke false:
    conf_security_externalized.authentication.role.mapper.enabled=false
  4. Mulai ulang server pengelolaan:
    > /opt/apigee/apigee-service/bin/apigee-service edge-management-server start

Tentang contoh penerapan ExternalRoleMapperImpl

Di file konfigurasi security.properties yang dijelaskan sebelumnya di Mengaktifkan pemetaan peran eksternal, perhatikan baris berikut:

externalized.authentication.role.mapper.implementation.class=com.customer.authorization.impl.ExternalRoleMapperImpl

Class ini menerapkan antarmuka ExternalRoleMapperServiceV2, dan bersifat wajib. Anda perlu membuat implementasi class ini sendiri yang mencerminkan grup Anda masing-masing. Setelah selesai, tempatkan class yang dikompilasi ke dalam JAR dan masukkan JAR tersebut ke classpath Management Server di:

/opt/apigee/edge-management-server/lib/thirdparty/

Anda dapat memberi nama class dan mengemas apa pun yang diinginkan selama class tersebut mengimplementasikan ExternalRoleMapperServiceV2, dapat diakses di classpath Anda, dan direferensikan dengan benar di file konfigurasi management-server.properties.

Di bawah ini kami menawarkan contoh penerapan kelas ExternalRoleMapperImpl yang telah dikomentari dengan baik.

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();
   }

}