summaryrefslogtreecommitdiffstats
path: root/base/common/src/com/netscape/certsrv
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 11:20:05 -0500
commitcb209df95c4dee11f2a912e20b417fa3bc41c88f (patch)
treeb50824cdfd3bc4ec3db905b94ef7750d9ff74844 /base/common/src/com/netscape/certsrv
parent906acfd2c82d195a7c55a2af7c4d7abe8ed2655a (diff)
downloadpki-cb209df95c4dee11f2a912e20b417fa3bc41c88f.tar.gz
pki-cb209df95c4dee11f2a912e20b417fa3bc41c88f.tar.xz
pki-cb209df95c4dee11f2a912e20b417fa3bc41c88f.zip
Added ACLInterceptor.
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
Diffstat (limited to 'base/common/src/com/netscape/certsrv')
-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
14 files changed, 237 insertions, 11 deletions
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