diff options
Diffstat (limited to 'base/common/src/com/netscape/certsrv')
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 |