summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEndi Sukma Dewata <edewata@redhat.com>2012-10-10 04:38:05 -0500
committerEndi Sukma Dewata <edewata@redhat.com>2012-11-08 00:29:16 -0500
commit7a533307bd03b6aa5853f32654db3bba7a2d26cb (patch)
treee22c98540243eeb3e30d77f027f0e7948b1a3326
parente5db248fb62510737b7ec17de0d4b27a2dcf8707 (diff)
downloadpki-ticket-400-1.tar.gz
pki-ticket-400-1.tar.xz
pki-ticket-400-1.zip
Added ACLInterceptor.ticket-400-1
Previously ACL checking was done in PKIRealm by matching the URL. This code has been replaced by ACLInterceptor which will intercept RESTEasy method invocations. This allows more precise mapping of REST methods to ACL entries in acl.ldif. Ticket #287
-rw-r--r--base/ca/shared/webapps/ca/WEB-INF/auth.properties18
-rw-r--r--base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java4
-rw-r--r--base/common/src/com/netscape/certsrv/account/AccountResource.java4
-rw-r--r--base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java154
-rw-r--r--base/common/src/com/netscape/certsrv/acls/ACLMapping.java31
-rw-r--r--base/common/src/com/netscape/certsrv/ca/CAClient.java2
-rw-r--r--base/common/src/com/netscape/certsrv/cert/CertRequestResource.java24
-rw-r--r--base/common/src/com/netscape/certsrv/cert/CertResource.java4
-rw-r--r--base/common/src/com/netscape/certsrv/group/GroupMemberResource.java3
-rw-r--r--base/common/src/com/netscape/certsrv/group/GroupResource.java3
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyRequestResource.java2
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyResource.java3
-rw-r--r--base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java9
-rw-r--r--base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java3
-rw-r--r--base/common/src/com/netscape/certsrv/user/UserCertResource.java3
-rw-r--r--base/common/src/com/netscape/certsrv/user/UserResource.java3
-rw-r--r--base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java9
-rw-r--r--base/common/src/com/netscape/cms/servlet/key/KeyService.java2
-rw-r--r--base/common/src/com/netscape/cms/servlet/request/CertRequestService.java15
-rw-r--r--base/common/src/com/netscape/cmscore/realm/PKIRealm.java221
-rw-r--r--base/kra/shared/webapps/kra/WEB-INF/auth.properties16
-rw-r--r--base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java3
-rw-r--r--base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties12
-rw-r--r--base/ocsp/src/com/netscape/ocsp/OCSPApplication.java4
-rw-r--r--base/tks/shared/webapps/tks/WEB-INF/auth.properties12
-rw-r--r--base/tks/src/com/netscape/tks/TKSApplication.java4
26 files changed, 299 insertions, 269 deletions
diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
index 116bc94bf..08f5bea50 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties
+++ b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
@@ -1,13 +1,13 @@
# Restful API auth/authz mapping info
#
# Format:
-# <Rest API URL> = <ACL Resource ID>,<ACL resource operation>
-# ex: /ca/pki/users = certServer.ca.users,read
+# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
+# ex: admin.users = certServer.ca.users,read
-/ca/rest/account/login = certServer.ca.account,login
-/ca/rest/account/logout = certServer.ca.account,logout
-/ca/rest/admin/users = certServer.ca.users,execute
-/ca/rest/admin/groups = certServer.ca.groups,execute
-/ca/rest/agent/certrequests = certServer.ca.certrequests,execute
-/ca/rest/agent/certs = certServer.ca.certs,execute
-/ca/rest/securityDomain/installToken = certServer.securitydomain.domainxml,read
+account.login = certServer.ca.account,login
+account.logout = certServer.ca.account,logout
+admin.users = certServer.ca.users,execute
+admin.groups = certServer.ca.groups,execute
+agent.certrequests = certServer.ca.certrequests,execute
+agent.certs = certServer.ca.certs,execute
+securityDomain.installToken = certServer.securitydomain.domainxml,read
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
index 42fd439de..bc6dd71a6 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
@@ -5,6 +5,7 @@ import java.util.Set;
import javax.ws.rs.core.Application;
+import com.netscape.certsrv.acls.ACLInterceptor;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IConfigStore;
@@ -79,6 +80,9 @@ public class CertificateAuthorityApplication extends Application {
// exception mapper
classes.add(PKIException.Mapper.class);
+
+ // ACL interceptor
+ singletons.add(new ACLInterceptor());
}
public Set<Class<?>> getClasses() {
diff --git a/base/common/src/com/netscape/certsrv/account/AccountResource.java b/base/common/src/com/netscape/certsrv/account/AccountResource.java
index ee40b24a8..a69a3d122 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountResource.java
+++ b/base/common/src/com/netscape/certsrv/account/AccountResource.java
@@ -21,6 +21,8 @@ package com.netscape.certsrv.account;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author Endi S. Dewata
*/
@@ -29,9 +31,11 @@ public interface AccountResource {
@GET
@Path("login")
+ @ACLMapping("account.login")
public void login();
@GET
@Path("logout")
+ @ACLMapping("account.logout")
public void logout();
}
diff --git a/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java
new file mode 100644
index 000000000..bcb0b80a2
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java
@@ -0,0 +1,154 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.acls;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.Principal;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.annotations.interception.Precedence;
+import org.jboss.resteasy.annotations.interception.ServerInterceptor;
+import org.jboss.resteasy.core.ResourceMethod;
+import org.jboss.resteasy.core.ServerResponse;
+import org.jboss.resteasy.spi.Failure;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.realm.PKIPrincipal;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+@Provider
+@ServerInterceptor
+@Precedence("SECURITY")
+public class ACLInterceptor implements PreProcessInterceptor {
+
+ Properties authProperties;
+
+ @Context
+ ServletContext servletContext;
+
+ @Context
+ SecurityContext securityContext;
+
+ public synchronized void loadAuthProperties() throws IOException {
+
+ if (authProperties != null) return;
+
+ URL url = servletContext.getResource("/WEB-INF/auth.properties");
+ authProperties = new Properties();
+ authProperties.load(url.openStream());
+ }
+
+ @Override
+ public ServerResponse preProcess(
+ HttpRequest request,
+ ResourceMethod resourceMethod
+ ) throws Failure, WebApplicationException {
+
+ // Get ACL mapping for the method.
+ Method method = resourceMethod.getMethod();
+ ACLMapping aclMapping = method.getAnnotation(ACLMapping.class);
+
+ // If not available, get ACL mapping for the class.
+ if (aclMapping == null) {
+ Class<?> clazz = method.getDeclaringClass();
+ aclMapping = clazz.getAnnotation(ACLMapping.class);
+ }
+
+ // If still not available, it's unprotected, allow request.
+ if (aclMapping == null) return null;
+
+ Principal principal = securityContext.getUserPrincipal();
+
+ // If unauthenticated, reject request.
+ if (principal == null) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+ }
+
+ // If unrecognized principal, reject request.
+ if (!(principal instanceof PKIPrincipal)) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+ }
+
+ PKIPrincipal pkiPrincipal = (PKIPrincipal)principal;
+ IAuthToken authToken = pkiPrincipal.getAuthToken();
+
+ // If missing auth token, reject request.
+ if (authToken == null) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+ }
+
+ try {
+ loadAuthProperties();
+
+ String name = aclMapping.value();
+ String value = authProperties.getProperty(name);
+
+ // If no property defined, allow request.
+ if (value == null) return null;
+
+ String values[] = value.split(",");
+
+ // If invalid mapping, reject request.
+ if (values.length != 2) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+ }
+
+ // Check authorization.
+ IAuthzSubsystem mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ AuthzToken authzToken = mAuthz.authorize(
+ "DirAclAuthz",
+ authToken,
+ values[0], // resource
+ values[1]); // operation
+
+ // If not authorized, reject request.
+ if (authzToken == null) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+ }
+
+ } catch (EAuthzAccessDenied e) {
+ throw new WebApplicationException(Response.Status.FORBIDDEN);
+
+ } catch (IOException|EBaseException e) {
+ e.printStackTrace();
+ throw new Failure(e);
+ }
+
+ // Allow request.
+ return null;
+ }
+}
diff --git a/base/common/src/com/netscape/certsrv/acls/ACLMapping.java b/base/common/src/com/netscape/certsrv/acls/ACLMapping.java
new file mode 100644
index 000000000..a78ffaee0
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/acls/ACLMapping.java
@@ -0,0 +1,31 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.certsrv.acls;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ACLMapping {
+ public String value();
+}
diff --git a/base/common/src/com/netscape/certsrv/ca/CAClient.java b/base/common/src/com/netscape/certsrv/ca/CAClient.java
index 2c026b799..93d50b670 100644
--- a/base/common/src/com/netscape/certsrv/ca/CAClient.java
+++ b/base/common/src/com/netscape/certsrv/ca/CAClient.java
@@ -64,7 +64,7 @@ public class CAClient extends PKIClient {
CertRequestInfos infos = null;
Collection<CertRequestInfo> list = null;
infos = certRequestClient.listRequests(
- requestState, requestType, new RequestId(0), 100, 100, 10);
+ requestState, requestType, null, null, null, null);
list = infos.getRequests();
return list;
diff --git a/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java b/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
index 1a186f627..0bd285136 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
@@ -18,7 +18,6 @@
package com.netscape.certsrv.cert;
import javax.ws.rs.Consumes;
-import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -28,28 +27,25 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+import com.netscape.certsrv.acls.ACLMapping;
import com.netscape.certsrv.request.RequestId;
@Path("")
public interface CertRequestResource {
- public static final int DEFAULT_START = 0;
- public static final int DEFAULT_PAGESIZE = 20;
- public static final int DEFAULT_MAXRESULTS = 100;
- public static final int DEFAULT_MAXTIME = 10;
-
/**
* Used to generate list of cert requests based on the search parameters
*/
@GET
@Path("agent/certrequests")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public CertRequestInfos listRequests(@QueryParam("requestState") String requestState,
@QueryParam("requestType") String requestType,
- @DefaultValue("" + DEFAULT_START) @QueryParam("start") RequestId start,
- @DefaultValue("" + DEFAULT_PAGESIZE) @QueryParam("pageSize") int pageSize,
- @DefaultValue("" + DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults,
- @DefaultValue("" + DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime);
+ @QueryParam("start") RequestId start,
+ @QueryParam("pageSize") Integer pageSize,
+ @QueryParam("maxResults") Integer maxResults,
+ @QueryParam("maxTime") Integer maxTime);
/**
* Used to retrieve cert request info for a specific request
@@ -62,6 +58,7 @@ public interface CertRequestResource {
@GET
@Path("agent/certrequests/{id}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public CertReviewResponse reviewRequest(@PathParam("id") RequestId id);
// Enrollment - used to test integration with a browser
@@ -80,35 +77,42 @@ public interface CertRequestResource {
@POST
@Path("agent/certrequests/{id}/approve")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void approveRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/reject")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void rejectRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/cancel")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void cancelRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/update")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void updateRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/validate")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void validateRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/unassign")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void unassignRequest(@PathParam("id") RequestId id, CertReviewResponse data);
@POST
@Path("agent/certrequests/{id}/assign")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certrequests")
public void assignRequest(@PathParam("id") RequestId id, CertReviewResponse data);
}
diff --git a/base/common/src/com/netscape/certsrv/cert/CertResource.java b/base/common/src/com/netscape/certsrv/cert/CertResource.java
index 1d5958824..53e06ca6e 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertResource.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertResource.java
@@ -10,6 +10,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
+import com.netscape.certsrv.acls.ACLMapping;
import com.netscape.certsrv.dbs.certdb.CertId;
@Path("")
@@ -44,17 +45,20 @@ public interface CertResource {
@Path("agent/certs/{id}/revoke-ca")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certs")
public CertRequestInfo revokeCACert(@PathParam("id") CertId id, CertRevokeRequest request);
@POST
@Path("agent/certs/{id}/revoke")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certs")
public CertRequestInfo revokeCert(@PathParam("id") CertId id, CertRevokeRequest request);
@POST
@Path("agent/certs/{id}/unrevoke")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("agent.certs")
public CertRequestInfo unrevokeCert(@PathParam("id") CertId id, CertUnrevokeRequest request);
}
diff --git a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
index fb4293ffe..c984daa65 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
@@ -31,10 +31,13 @@ import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.ClientResponseType;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author Endi S. Dewata
*/
@Path("admin/groups/{groupID}/members")
+@ACLMapping("admin.groups")
public interface GroupMemberResource {
@GET
diff --git a/base/common/src/com/netscape/certsrv/group/GroupResource.java b/base/common/src/com/netscape/certsrv/group/GroupResource.java
index e0110e6a8..17728dd13 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupResource.java
@@ -31,10 +31,13 @@ import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.ClientResponseType;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author Endi S. Dewata
*/
@Path("admin/groups")
+@ACLMapping("admin.groups")
public interface GroupResource {
@GET
diff --git a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
index 356fd1569..9f1ffbe02 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
@@ -10,9 +10,11 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+import com.netscape.certsrv.acls.ACLMapping;
import com.netscape.certsrv.request.RequestId;
@Path("agent/keyrequests")
+@ACLMapping("agent.keyrequests")
public interface KeyRequestResource {
public final String SYMMETRIC_KEY_TYPE = "symmetricKey";
diff --git a/base/common/src/com/netscape/certsrv/key/KeyResource.java b/base/common/src/com/netscape/certsrv/key/KeyResource.java
index 50fe82cc3..da7f22031 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyResource.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyResource.java
@@ -9,8 +9,11 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+import com.netscape.certsrv.acls.ACLMapping;
+
@Path("agent/keys")
+@ACLMapping("agent.keys")
public interface KeyResource {
@GET
diff --git a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
index 553e849fa..5ecd56092 100644
--- a/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
@@ -21,6 +21,7 @@ import java.net.URISyntaxException;
import com.netscape.certsrv.client.ClientConfig;
import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.client.PKIConnection;
/**
@@ -30,9 +31,17 @@ public class SecurityDomainClient extends PKIClient {
private SecurityDomainResource client;
+ public SecurityDomainClient(PKIConnection connection) throws URISyntaxException {
+ super(connection);
+ init();
+ }
+
public SecurityDomainClient(ClientConfig config) throws URISyntaxException {
super(config);
+ init();
+ }
+ public void init() throws URISyntaxException {
client = createProxy(SecurityDomainResource.class);
}
diff --git a/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
index 1805d15c4..b34d9fe13 100644
--- a/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
@@ -23,6 +23,8 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author alee
*/
@@ -32,6 +34,7 @@ public interface SecurityDomainResource {
@GET
@Path("installToken")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ACLMapping("securityDomain.installToken")
public InstallToken getInstallToken(
@QueryParam("hostname") String hostname,
@QueryParam("subsystem") String subsystem);
diff --git a/base/common/src/com/netscape/certsrv/user/UserCertResource.java b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
index db463ea59..d85abd6e0 100644
--- a/base/common/src/com/netscape/certsrv/user/UserCertResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
@@ -31,10 +31,13 @@ import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.ClientResponseType;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author Endi S. Dewata
*/
@Path("admin/users/{userID}/certs")
+@ACLMapping("admin.users")
public interface UserCertResource {
@GET
diff --git a/base/common/src/com/netscape/certsrv/user/UserResource.java b/base/common/src/com/netscape/certsrv/user/UserResource.java
index 4a837165f..e72bb0cef 100644
--- a/base/common/src/com/netscape/certsrv/user/UserResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserResource.java
@@ -31,10 +31,13 @@ import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.ClientResponseType;
+import com.netscape.certsrv.acls.ACLMapping;
+
/**
* @author Endi S. Dewata
*/
@Path("admin/users")
+@ACLMapping("admin.users")
public interface UserResource {
@GET
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index 2a2c3b3ab..a7ec566ce 100644
--- a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -129,6 +129,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import com.netscape.certsrv.account.AccountClient;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.EAuthException;
import com.netscape.certsrv.authentication.IAuthSubsystem;
@@ -325,10 +326,14 @@ public class ConfigurationUtils {
config.setUsername(user);
config.setPassword(passwd);
- SecurityDomainClient client = new SecurityDomainClient(config);
+ PKIConnection connection = new PKIConnection(config);
+ AccountClient accountClient = new AccountClient(connection);
+ SecurityDomainClient sdClient = new SecurityDomainClient(connection);
try {
- InstallToken token = client.getInstallToken(sdhost, csType);
+ accountClient.login();
+ InstallToken token = sdClient.getInstallToken(sdhost, csType);
+ accountClient.logout();
return token.getToken();
} catch (ClientResponseFailure e) {
diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyService.java b/base/common/src/com/netscape/cms/servlet/key/KeyService.java
index fe82d5fcd..01c8a0ee9 100644
--- a/base/common/src/com/netscape/cms/servlet/key/KeyService.java
+++ b/base/common/src/com/netscape/cms/servlet/key/KeyService.java
@@ -52,7 +52,7 @@ import com.netscape.cmsutil.ldap.LDAPUtil;
* @author alee
*
*/
-public class KeyService extends PKIService implements KeyResource{
+public class KeyService extends PKIService implements KeyResource {
public static final int DEFAULT_MAXRESULTS = 100;
public static final int DEFAULT_MAXTIME = 10;
diff --git a/base/common/src/com/netscape/cms/servlet/request/CertRequestService.java b/base/common/src/com/netscape/cms/servlet/request/CertRequestService.java
index a8099003f..dba6d9c01 100644
--- a/base/common/src/com/netscape/cms/servlet/request/CertRequestService.java
+++ b/base/common/src/com/netscape/cms/servlet/request/CertRequestService.java
@@ -50,6 +50,11 @@ import com.netscape.cmsutil.ldap.LDAPUtil;
*/
public class CertRequestService extends PKIService implements CertRequestResource {
+ public static final int DEFAULT_START = 0;
+ public static final int DEFAULT_PAGESIZE = 20;
+ public static final int DEFAULT_MAXRESULTS = 100;
+ public static final int DEFAULT_MAXTIME = 10;
+
/**
* Used to retrieve key request info for a specific request
*/
@@ -194,17 +199,17 @@ public class CertRequestService extends PKIService implements CertRequestResourc
* Used to generate list of cert requests based on the search parameters
*/
public CertRequestInfos listRequests(String requestState, String requestType,
- RequestId start, int pageSize, int maxResults, int maxTime) {
+ RequestId start, Integer pageSize, Integer maxResults, Integer maxTime) {
// auth and authz
// get ldap filter
String filter = createSearchFilter(requestState, requestType);
CMS.debug("listRequests: filter is " + filter);
- // get start marker
- if (start == null) {
- start = new RequestId(CertRequestResource.DEFAULT_START);
- }
+ start = start == null ? new RequestId(CertRequestService.DEFAULT_START) : start;
+ pageSize = pageSize == null ? DEFAULT_PAGESIZE : pageSize;
+ maxResults = maxResults == null ? DEFAULT_MAXRESULTS : maxResults;
+ maxTime = maxTime == null ? DEFAULT_MAXTIME : maxTime;
CertRequestDAO reqDAO = new CertRequestDAO();
CertRequestInfos requests;
diff --git a/base/common/src/com/netscape/cmscore/realm/PKIRealm.java b/base/common/src/com/netscape/cmscore/realm/PKIRealm.java
index 9b4b97c2a..5e9ae4116 100644
--- a/base/common/src/com/netscape/cmscore/realm/PKIRealm.java
+++ b/base/common/src/com/netscape/cmscore/realm/PKIRealm.java
@@ -1,31 +1,19 @@
package com.netscape.cmscore.realm;
-import java.io.IOException;
-import java.io.InputStream;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
-import java.util.Properties;
-
-import javax.servlet.http.HttpServletResponse;
import netscape.security.x509.X509CertImpl;
-import org.apache.catalina.Context;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.realm.RealmBase;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.IAuthManager;
import com.netscape.certsrv.authentication.IAuthSubsystem;
import com.netscape.certsrv.authentication.IAuthToken;
-import com.netscape.certsrv.authorization.AuthzToken;
-import com.netscape.certsrv.authorization.IAuthzSubsystem;
import com.netscape.certsrv.usrgrp.EUsrGrpException;
import com.netscape.certsrv.usrgrp.IGroup;
import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -44,27 +32,6 @@ import com.netscape.cmscore.authentication.PasswdUserDBAuthentication;
public class PKIRealm extends RealmBase {
- public final static String PROP_AUTH_FILE_PATH = "/WEB-INF/auth.properties";
- public final static int EXPRESSION_SIZE = 2;
-
- Properties authzProperties;
-
- public PKIRealm() {
- logDebug("Creating PKI realm");
- }
-
- @Override
- protected void initInternal() throws LifecycleException {
- logDebug("Initializing PKI realm");
- super.initInternal();
- }
-
- @Override
- protected void startInternal() throws LifecycleException {
- logDebug("Starting PKI realm");
- super.startInternal();
- }
-
@Override
protected String getName() {
return "PKIRealm";
@@ -180,194 +147,6 @@ public class PKIRealm extends RealmBase {
return null;
}
- /**
- * Perform access control based on the specified authorization constraint.
- * Return <code>true</code> if this constraint is satisfied and processing
- * should continue, or <code>false</code> otherwise.
- * override to check for custom PKI ACL's authz permissions.
- *
- * @param request Request we are processing
- * @param response Response we are creating
- * @param constraints Security constraint we are enforcing
- * @param context The Context to which client of this class is attached.
- *
- * @exception IOException if an input/output error occurs
- */
- @Override
- public boolean hasResourcePermission(Request request,
- Response response,
- SecurityConstraint[] constraints,
- Context context)
- throws IOException {
-
- String requestURI = request.getDecodedRequestURI();
- logDebug("Checking permission: "+requestURI);
-
- boolean allowed = super.hasResourcePermission(request, response, constraints, context);
- logDebug("Resource permission: "+allowed);
-
- if (allowed) {
- allowed = checkACL(request, response, constraints, context);
- logDebug("ACL permission: "+allowed);
- }
-
- if (!allowed) {
- response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("realmBase.forbidden"));
- }
-
- return allowed;
- }
-
- public boolean checkACL(Request request,
- Response response,
- SecurityConstraint[] constraints,
- Context context) {
-
- try {
- loadAuthzProperties(context);
- if (!hasAuthzProperties()) return false;
-
- String requestURI = request.getDecodedRequestURI();
- String match = getACLEntry(requestURI);
- if (match == null) return false;
-
- logDebug("ACL: "+match);
- String[] authzParams = match.split("\\,");
-
- String resource = null;
- String operation = null;
-
- if (authzParams.length >= EXPRESSION_SIZE) {
- resource = authzParams[0];
- operation = authzParams[1];
-
- if (resource != null) {
- resource = resource.trim();
- }
-
- if (operation != null) {
- operation = operation.trim();
- }
- }
-
- Principal principal = request.getUserPrincipal();
- if (principal instanceof PKIPrincipal) {
- PKIPrincipal pkiPrincipal = (PKIPrincipal)principal;
- IAuthToken authToken = pkiPrincipal.getAuthToken();
-
- logDebug("Auth token:");
- Enumeration<String> names = authToken.getElements();
- while (names.hasMoreElements()) {
- String name = names.nextElement();
- Object value = authToken.get(name);
- logDebug(" " + name +": " + value);
- }
-
- logDebug("Resource: " + resource);
- logDebug("Operation: " + operation);
-
- IAuthzSubsystem mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
- AuthzToken authzToken = mAuthz.authorize("DirAclAuthz", authToken, resource, operation);
- if (authzToken != null) return true;
- }
-
- } catch (Throwable e) {
- e.printStackTrace();
- }
-
- return false;
- }
-
- // Search for the proper auth.properties entry corresponding
- // to a particular incoming URL
- // TODO: In the admin interface, often the operation is sent
- // as one of the parameters to the message.
- // There may be a way to extract this information at this level.
- // The parameter name to scan for could be configured with the Realm.
-
- public String getACLEntry(String requestURI) {
-
- if (!hasAuthzProperties()) {
- return null;
- }
-
- logDebug("Checking path: "+requestURI);
- String aclEntryData = authzProperties.getProperty(requestURI);
-
- if (aclEntryData != null) {
- logDebug("Found exact match: "+aclEntryData);
- return aclEntryData;
- }
-
- // Check for a partial match such as
- // ex: /kra/pki/keyrequest/2
- // TODO: Check into more sophisticated
- // methods of doing this mapping.
- // Perhaps Rest gives us this more
- // sophisticated mapping ability.
-
- Properties props = authzProperties;
- Enumeration<?> e = props.propertyNames();
-
- while (e.hasMoreElements()) {
- String key = (String) e.nextElement();
- if (requestURI.startsWith(key)) {
- aclEntryData = props.getProperty(key);
- logDebug("Found partial match ["+key+"]: "+aclEntryData);
- break;
- }
- }
-
- if (aclEntryData == null) {
- logDebug("No match found");
- }
-
- return aclEntryData;
-
- }
-
- // Check to see if we have read in the auth properties file
- public boolean hasAuthzProperties() {
-
- if (authzProperties != null) {
- return true;
- } else {
- return false;
- }
- }
-
- // Load the custom mapping file auth.properties, which maps urls to acl resourceID and operation value
- // example entry: /kra/pki/config/cert/transport = certServer.kra.pki.config.cert.transport,read
- // TODO: Look into a more sophisticated method than this simple properties file if appropriate.
- public synchronized void loadAuthzProperties(Context context) throws IOException {
-
- if (authzProperties == null && context != null) {
-
- InputStream inputStream = context.getServletContext().getResourceAsStream(PROP_AUTH_FILE_PATH);
-
- if (inputStream == null) {
- logDebug("Resource "+PROP_AUTH_FILE_PATH+" not found.");
- throw new IOException("Resource "+PROP_AUTH_FILE_PATH+" not found.");
- }
-
- try {
- logDebug("Loading authorization properties");
-
- Properties properties = new Properties();
- properties.load(inputStream);
-
- authzProperties = properties;
-
- } finally {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
/*
* TODO: Figure out how to do real logging
*/
diff --git a/base/kra/shared/webapps/kra/WEB-INF/auth.properties b/base/kra/shared/webapps/kra/WEB-INF/auth.properties
index 0a529f060..567747f5b 100644
--- a/base/kra/shared/webapps/kra/WEB-INF/auth.properties
+++ b/base/kra/shared/webapps/kra/WEB-INF/auth.properties
@@ -1,12 +1,12 @@
# Restful API auth/authz mapping info
#
# Format:
-# <Rest API URL> = <ACL Resource ID>,<ACL resource operation>
-# ex: /kra/pki/key/retrieve = certServer.kra.pki.key.retrieve,execute
+# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
+# ex: admin.users = certServer.ca.users,read
-/kra/rest/account/login = certServer.kra.account,login
-/kra/rest/account/logout = certServer.kra.account,logout
-/kra/rest/admin/users = certServer.kra.users,execute
-/kra/rest/admin/groups = certServer.kra.groups,execute
-/kra/rest/agent/keys = certServer.kra.keys,execute
-/kra/rest/agent/keyrequests = certServer.kra.keyrequests,execute
+account.login = certServer.kra.account,login
+account.logout = certServer.kra.account,logout
+admin.users = certServer.kra.users,execute
+admin.groups = certServer.kra.groups,execute
+agent.keys = certServer.kra.keys,execute
+agent.keyrequests = certServer.kra.keyrequests,execute
diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
index 280ffe1dc..0ed23f697 100644
--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
+++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
@@ -5,6 +5,7 @@ import java.util.Set;
import javax.ws.rs.core.Application;
+import com.netscape.certsrv.acls.ACLInterceptor;
import com.netscape.certsrv.base.PKIException;
import com.netscape.cms.servlet.account.AccountService;
import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -45,6 +46,8 @@ public class KeyRecoveryAuthorityApplication extends Application {
// exception mapper
classes.add(PKIException.Mapper.class);
+ // ACL interceptor
+ singletons.add(new ACLInterceptor());
}
public Set<Class<?>> getClasses() {
diff --git a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties b/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
index 8eda09bc3..cd2e14058 100644
--- a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
+++ b/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
@@ -1,10 +1,10 @@
# Restful API auth/authz mapping info
#
# Format:
-# <Rest API URL> = <ACL Resource ID>,<ACL resource operation>
-# ex: /kra/pki/key/retrieve = certServer.kra.pki.key.retrieve,execute
+# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
+# ex: admin.users = certServer.ca.users,read
-/ocsp/rest/account/login = certServer.ocsp.account,login
-/ocsp/rest/account/logout = certServer.ocsp.account,logout
-/ocsp/rest/admin/users = certServer.ocsp.users,execute
-/ocsp/rest/admin/groups = certServer.ocsp.groups,execute
+account.login = certServer.ocsp.account,login
+account.logout = certServer.ocsp.account,logout
+admin.users = certServer.ocsp.users,execute
+admin.groups = certServer.ocsp.groups,execute
diff --git a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
index e6816721c..21b37f801 100644
--- a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
+++ b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
@@ -5,6 +5,7 @@ import java.util.Set;
import javax.ws.rs.core.Application;
+import com.netscape.certsrv.acls.ACLInterceptor;
import com.netscape.certsrv.base.PKIException;
import com.netscape.cms.servlet.account.AccountService;
import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -38,6 +39,9 @@ public class OCSPApplication extends Application {
// exception mapper
classes.add(PKIException.Mapper.class);
+
+ // ACL interceptor
+ singletons.add(new ACLInterceptor());
}
public Set<Class<?>> getClasses() {
diff --git a/base/tks/shared/webapps/tks/WEB-INF/auth.properties b/base/tks/shared/webapps/tks/WEB-INF/auth.properties
index 90897683e..6de7f08e5 100644
--- a/base/tks/shared/webapps/tks/WEB-INF/auth.properties
+++ b/base/tks/shared/webapps/tks/WEB-INF/auth.properties
@@ -1,10 +1,10 @@
# Restful API auth/authz mapping info
#
# Format:
-# <Rest API URL> = <ACL Resource ID>,<ACL resource operation>
-# ex: /kra/pki/key/retrieve = certServer.kra.pki.key.retrieve,execute
+# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
+# ex: admin.users = certServer.ca.users,read
-/tks/rest/account/login = certServer.tks.account,login
-/tks/rest/account/logout = certServer.tks.account,logout
-/tks/rest/admin/users = certServer.tks.users,execute
-/tks/rest/admin/groups = certServer.tks.groups,execute
+account.login = certServer.tks.account,login
+account.logout = certServer.tks.account,logout
+admin.users = certServer.tks.users,execute
+admin.groups = certServer.tks.groups,execute
diff --git a/base/tks/src/com/netscape/tks/TKSApplication.java b/base/tks/src/com/netscape/tks/TKSApplication.java
index 5493bb4da..229a64c95 100644
--- a/base/tks/src/com/netscape/tks/TKSApplication.java
+++ b/base/tks/src/com/netscape/tks/TKSApplication.java
@@ -5,6 +5,7 @@ import java.util.Set;
import javax.ws.rs.core.Application;
+import com.netscape.certsrv.acls.ACLInterceptor;
import com.netscape.certsrv.base.PKIException;
import com.netscape.cms.servlet.account.AccountService;
import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -38,6 +39,9 @@ public class TKSApplication extends Application {
// exception mapper
classes.add(PKIException.Mapper.class);
+
+ // ACL interceptor
+ singletons.add(new ACLInterceptor());
}
public Set<Class<?>> getClasses() {