From 06661a298272a3773bc3b276280f983f2146d097 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Tue, 19 Apr 2016 22:32:33 -0400
Subject: [PATCH 295/295] Realm: allow auth instances to support multiple
 realms

In practice, most folks will use something like DirAclAuthz
to manage their realm.  Rather than requiring a new authz plugin
for each realm, we allow the authz plugin to support multiple
realms (as a comma separated list).

For the Acl plugins in particular, we expand the authorize call
to allow the caller to pass in the realm as well as the resource
and operation.  The resource queried would then be constructed on
the fly as realm.resource

Examples will be provided in the wiki page.

Trac Ticket 2041
---
 .../certsrv/authorization/IAuthzSubsystem.java     |  3 +++
 .../server/kra/rest/KeyRequestService.java         |  8 +++----
 .../org/dogtagpki/server/kra/rest/KeyService.java  |  6 ++---
 .../netscape/cms/servlet/key/KeyRequestDAO.java    | 12 +++++-----
 .../cmscore/authorization/AuthzSubsystem.java      | 27 ++++++++++++++++++----
 5 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/authorization/IAuthzSubsystem.java b/base/common/src/com/netscape/certsrv/authorization/IAuthzSubsystem.java
index 156643897a07890eb7edd9555b3061a720322b71..c7d8df56bbfb1bf8af6c51ce491fc1384560b4a8 100644
--- a/base/common/src/com/netscape/certsrv/authorization/IAuthzSubsystem.java
+++ b/base/common/src/com/netscape/certsrv/authorization/IAuthzSubsystem.java
@@ -80,6 +80,9 @@ public interface IAuthzSubsystem extends ISubsystem {
     public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
             String exp) throws EBaseException;
 
+    public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
+            String resource, String operation, String realm) throws EBaseException;
+
     /**
      * Authorize the user against the specified realm.  Looks for authz manager
      * associated with the plugin and authenticates if present.
diff --git a/base/kra/src/org/dogtagpki/server/kra/rest/KeyRequestService.java b/base/kra/src/org/dogtagpki/server/kra/rest/KeyRequestService.java
index 41d78af533b8e94c3e82f6b79d688e32cf3a07e3..103b78923ee9200bed2e0c8608168f35c311df9c 100644
--- a/base/kra/src/org/dogtagpki/server/kra/rest/KeyRequestService.java
+++ b/base/kra/src/org/dogtagpki/server/kra/rest/KeyRequestService.java
@@ -175,7 +175,7 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
 
             String realm = data.getRealm();
             if (realm != null) {
-                authz.checkRealm(realm, getAuthToken(), null, "keyRequest", "archive");
+                authz.checkRealm(realm, getAuthToken(), null, "certServer.kra.requests.archival", "execute");
             }
             response = dao.submitRequest(data, uriInfo, getRequestor());
             auditArchivalRequestMade(response.getRequestInfo().getRequestId(), ILogger.SUCCESS, data.getClientKeyId());
@@ -304,7 +304,7 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
             RequestId start, Integer pageSize, Integer maxResults, Integer maxTime, String realm) {
         if (realm != null) {
             try {
-                authz.checkRealm(realm, getAuthToken(), null, "keyRequests", "list");
+                authz.checkRealm(realm, getAuthToken(), null, "certServer.kra.requests", "list");
             } catch (EAuthzAccessDenied e) {
                 throw new UnauthorizedException("Not authorized to list these requests", e);
             } catch (EAuthzUnknownRealm e) {
@@ -468,7 +468,7 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
             }
             String realm = data.getRealm();
             if (realm != null) {
-                authz.checkRealm(realm, getAuthToken(), null, "keyRequest", "generateSymkey");
+                authz.checkRealm(realm, getAuthToken(), null, "certServer.kra.requests.symkey", "execute");
             }
 
             response = dao.submitRequest(data, uriInfo, getRequestor());
@@ -502,7 +502,7 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
             }
             String realm = data.getRealm();
             if (realm != null) {
-                authz.checkRealm(realm, getAuthToken(), null, "keyRequest", "generateAsymkey");
+                authz.checkRealm(realm, getAuthToken(), null, "certServer.kra.requests.asymkey", "execute");
             }
 
             response = dao.submitRequest(data, uriInfo, getRequestor());
diff --git a/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java b/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
index 255d8d614aba2126c1ed89cd952e6cf9f5de3231..74b58b8a2e3c036925e12114d578a4069b136c74 100644
--- a/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
+++ b/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
@@ -422,7 +422,7 @@ public class KeyService extends PKIService implements KeyResource {
 
         if (realm != null) {
             try {
-                authz.checkRealm(realm, getAuthToken(), null, "keys", "list");
+                authz.checkRealm(realm, getAuthToken(), null, "certServer.kra.keys", "list");
             } catch (EAuthzAccessDenied e) {
                 throw new UnauthorizedException("Not authorized to list these keys", e);
             } catch (EAuthzUnknownRealm e) {
@@ -509,7 +509,7 @@ public class KeyService extends PKIService implements KeyResource {
             if (info != null) {
                 // return the first one, but first confirm that the requester has access to this key
                 try {
-                    authz.checkRealm(info.getRealm(), getAuthToken(), info.getOwnerName(), "key", "read");
+                    authz.checkRealm(info.getRealm(), getAuthToken(), info.getOwnerName(), "certServer.kra.key", "read");
                 } catch (EAuthzAccessDenied e) {
                     throw new UnauthorizedException("Not authorized to read this key", e);
                 } catch (EBaseException e) {
@@ -681,7 +681,7 @@ public class KeyService extends PKIService implements KeyResource {
         IKeyRecord rec = null;
         try {
             rec = repo.readKeyRecord(keyId.toBigInteger());
-            authz.checkRealm(rec.getRealm(), getAuthToken(), rec.getOwnerName(), "key", "read");
+            authz.checkRealm(rec.getRealm(), getAuthToken(), rec.getOwnerName(), "certServer.kra.key", "read");
             KeyInfo info = createKeyDataInfo(rec, true);
             auditRetrieveKey(ILogger.SUCCESS, null, keyId, auditInfo);
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
index 04bb6f2ec35e82fba53e67b661a50c9745285dc7..00e313a80da008ed84f5990cb29680192c3c6cba 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
@@ -169,7 +169,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         }
 
         authz.checkRealm(request.getRealm(), authToken, request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER),
-                "keyRequest", "read");
+                "certServer.kra.request", "read");
 
         KeyRequestInfo info = createKeyRequestInfo(request, uriInfo);
         return info;
@@ -264,7 +264,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         }
 
         try {
-            authz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(), "key", "recover");
+            authz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(), "certServer.kra.key", "recover");
         } catch (EAuthzUnknownRealm e) {
             throw new UnauthorizedException("Invalid realm", e);
         } catch (EBaseException e) {
@@ -322,7 +322,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         }
 
         try {
-            authz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(), "key", "recover");
+            authz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(), "certServer.kra.key", "recover");
         } catch (EAuthzUnknownRealm e) {
             throw new UnauthorizedException("Invalid realm", e);
         } catch (EBaseException e) {
@@ -504,7 +504,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         IRequest request = queue.findRequest(id);
         authz.checkRealm(request.getRealm(), authToken,
                 request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER),
-                "keyRequest", "approve");
+                "certServer.kra.requests", "execute");
 
         service.addAgentAsyncKeyRecovery(id.toString(), requestor);
     }
@@ -514,7 +514,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         String realm = request.getRealm();
         authz.checkRealm(realm, authToken,
                 request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER),
-                "keyRequest", "reject");
+                "certServer.kra.requests", "execute");
         request.setRequestStatus(RequestStatus.REJECTED);
         queue.updateRequest(request);
     }
@@ -524,7 +524,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         String realm = request.getRealm();
         authz.checkRealm(realm, authToken,
                 request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER),
-                "keyRequest", "cancel");
+                "certServer.kra.requests", "execute");
         request.setRequestStatus(RequestStatus.CANCELED);
         queue.updateRequest(request);
     }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
index 3544858979ba349dc1506d46193f00b0eeec6449..378777f99d8ffd647a4d4a183c8e96ab11722a9b 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
@@ -17,8 +17,10 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cmscore.authorization;
 
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.commons.codec.binary.StringUtils;
@@ -227,7 +229,7 @@ public class AuthzSubsystem implements IAuthzSubsystem {
      */
     public AuthzToken authorize(
             String authzMgrInstName, IAuthToken authToken,
-            String resource, String operation)
+            String resource, String operation, String realm)
             throws EAuthzMgrNotFound, EBaseException {
 
         AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName);
@@ -243,9 +245,20 @@ public class AuthzSubsystem implements IAuthzSubsystem {
         if (authzMgrInst == null) {
             throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
         }
+
+        if ((realm != null) && (resource != null)) {
+            resource = realm + "." + resource;
+        }
         return (authzMgrInst.authorize(authToken, resource, operation));
     }
 
+    @Override
+    public AuthzToken authorize(String authzMgrName, IAuthToken authToken, String resource, String operation)
+            throws EBaseException {
+        return authorize(authzMgrName, authToken, resource, operation, null);
+    }
+
+    @Override
     public AuthzToken authorize(
             String authzMgrInstName, IAuthToken authToken, String exp)
             throws EAuthzMgrNotFound, EBaseException {
@@ -485,7 +498,7 @@ public class AuthzSubsystem implements IAuthzSubsystem {
             throw new EAuthzUnknownRealm("Realm not found");
         }
 
-        AuthzToken authzToken = authorize(mgrName, authToken, resource, operation);
+        AuthzToken authzToken = authorize(mgrName, authToken, resource, operation, realm);
         if (authzToken == null) {
             throw new EAuthzAccessDenied("Not authorized by ACL realm");
         }
@@ -496,9 +509,13 @@ public class AuthzSubsystem implements IAuthzSubsystem {
             IAuthzManager mgr = proxy.getAuthzManager();
             if (mgr != null) {
                 IConfigStore cfg = mgr.getConfigStore();
-                String mgrRealm = cfg.getString(PROP_REALM, null);
-                if (StringUtils.equals(mgrRealm, realm)) {
-                    return mgr.getName();
+                String mgrRealmString = cfg.getString(PROP_REALM, null);
+                if (mgrRealmString == null) continue;
+
+                List<String> mgrRealms = Arrays.asList(mgrRealmString.split(","));
+                for (String mgrRealm : mgrRealms) {
+                    if (StringUtils.equals(mgrRealm, realm))
+                        return mgr.getName();
                 }
             }
         }
-- 
2.4.3

