From a19e1fa6e2e0c6f97418254aad1aba60cdfa9f39 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 3 Oct 2013 13:31:24 -0400
Subject: [PATCH] Added access control for TPS token.

The TPS token REST interface has been modified to require client certificate
authentication and limit modifications to administrators only.

Ticket #652
---
 .../netscape/certsrv/tps/token/TokenResource.java   |  9 +++++++++
 .../cms/authorization/AuthMethodInterceptor.java    | 21 +++++++++++----------
 base/tps-tomcat/shared/conf/acl.ldif                |  1 +
 .../shared/webapps/tps/WEB-INF/auth.properties      |  2 ++
 base/tps-tomcat/shared/webapps/tps/WEB-INF/web.xml  | 13 +++++++++++++
 5 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/tps/token/TokenResource.java b/base/common/src/com/netscape/certsrv/tps/token/TokenResource.java
index 5f98845e30cdc4fb3ecd9521f100d609034ebbda..b4716c20b7577035d057ba23aa561bf59aefa5b9 100644
--- a/base/common/src/com/netscape/certsrv/tps/token/TokenResource.java
+++ b/base/common/src/com/netscape/certsrv/tps/token/TokenResource.java
@@ -31,11 +31,16 @@ import javax.ws.rs.core.Response;
 
 import org.jboss.resteasy.annotations.ClientResponseType;
 
+import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMethodMapping;
+
 
 /**
  * @author Endi S. Dewata
  */
 @Path("tokens")
+@AuthMethodMapping("tokens")
+@ACLMapping("tokens.read")
 public interface TokenResource {
 
     @GET
@@ -53,6 +58,7 @@ public interface TokenResource {
     @ClientResponseType(entityType=TokenData.class)
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @ACLMapping("tokens.modify")
     public Response addToken(TokenData tokenData);
 
     @PUT
@@ -60,6 +66,7 @@ public interface TokenResource {
     @ClientResponseType(entityType=TokenData.class)
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @ACLMapping("tokens.modify")
     public Response updateToken(
             @PathParam("tokenID") String tokenID,
             TokenData tokenData);
@@ -69,6 +76,7 @@ public interface TokenResource {
     @ClientResponseType(entityType=TokenData.class)
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @ACLMapping("tokens.modify")
     public Response modifyToken(
             @PathParam("tokenID") String tokenID,
             TokenModifyRequest request);
@@ -76,5 +84,6 @@ public interface TokenResource {
     @DELETE
     @Path("{tokenID}")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @ACLMapping("tokens.modify")
     public void removeToken(@PathParam("tokenID") String tokenID);
 }
diff --git a/base/common/src/com/netscape/cms/authorization/AuthMethodInterceptor.java b/base/common/src/com/netscape/cms/authorization/AuthMethodInterceptor.java
index 257e0ae814e08e4a4114019498f1186de7203174..69139e43d2a5a7fd5964d9a587ca5f8a8478466b 100644
--- a/base/common/src/com/netscape/cms/authorization/AuthMethodInterceptor.java
+++ b/base/common/src/com/netscape/cms/authorization/AuthMethodInterceptor.java
@@ -48,7 +48,7 @@ import com.netscape.cmscore.realm.PKIPrincipal;
 @Provider
 public class AuthMethodInterceptor implements ContainerRequestFilter {
 
-    Properties authProperties;
+    Properties authMethodProperties;
 
     @Context
     ServletContext servletContext;
@@ -58,22 +58,23 @@ public class AuthMethodInterceptor implements ContainerRequestFilter {
 
     public synchronized void loadAuthProperties() throws IOException {
 
-        if (authProperties != null)
+        if (authMethodProperties != null)
             return;
 
-        authProperties = new Properties();
+        authMethodProperties = new Properties();
 
         URL url = servletContext.getResource("/WEB-INF/auth-method.properties");
 
         if (url == null) {
-            authProperties.put("default", "*");
-            authProperties.put("account", "certUserDBAuthMgr,passwdUserDBAuthMgr");
-            authProperties.put("admin", "certUserDBAuthMgr");
-            authProperties.put("agent", "certUserDBAuthMgr");
-            authProperties.put("securityDomain.installToken", "passwdUserDBAuthMgr");
+            authMethodProperties.put("default", "*");
+            authMethodProperties.put("account", "certUserDBAuthMgr,passwdUserDBAuthMgr");
+            authMethodProperties.put("admin", "certUserDBAuthMgr");
+            authMethodProperties.put("agent", "certUserDBAuthMgr");
+            authMethodProperties.put("securityDomain.installToken", "passwdUserDBAuthMgr");
+            authMethodProperties.put("tokens", "certUserDBAuthMgr");
 
         } else {
-            authProperties.load(url.openStream());
+            authMethodProperties.load(url.openStream());
         }
     }
 
@@ -108,7 +109,7 @@ public class AuthMethodInterceptor implements ContainerRequestFilter {
         try {
             loadAuthProperties();
 
-            String value = authProperties.getProperty(name);
+            String value = authMethodProperties.getProperty(name);
             Collection<String> authMethods = new HashSet<String>();
             if (value != null) {
                 for (String v : value.split(",")) {
diff --git a/base/tps-tomcat/shared/conf/acl.ldif b/base/tps-tomcat/shared/conf/acl.ldif
index 17d3bad6459ab49c00e8446f710d90ba3f6aaad9..13072e074f90664df9314b6b969c290c50bfc3da 100644
--- a/base/tps-tomcat/shared/conf/acl.ldif
+++ b/base/tps-tomcat/shared/conf/acl.ldif
@@ -23,3 +23,4 @@ resourceACLS: certServer.clone.configuration:read,modify:allow (modify,read) gro
 resourceACLS: certServer.tps.account:login,logout:allow (login,logout) user="anybody":Anybody can login and logout
 resourceACLS: certServer.tps.groups:execute:allow (execute) group="TUS Administrators":Admins may execute group operations
 resourceACLS: certServer.tps.users:execute:allow (execute) group="TUS Administrators":Admins may execute user operations
+resourceACLS: certServer.tps.tokens:read,modify:allow (read) user=anybody; allow (modify) group="TUS Administrators":Anybody can read tokens, but only admins can modify token operations
diff --git a/base/tps-tomcat/shared/webapps/tps/WEB-INF/auth.properties b/base/tps-tomcat/shared/webapps/tps/WEB-INF/auth.properties
index 8ed17dbe03c770a9d9733a617c6a43483cd1b0a4..d5d19102d0d2b07d2bc15d863190145754642b67 100644
--- a/base/tps-tomcat/shared/webapps/tps/WEB-INF/auth.properties
+++ b/base/tps-tomcat/shared/webapps/tps/WEB-INF/auth.properties
@@ -8,3 +8,5 @@ account.login = certServer.tps.account,login
 account.logout = certServer.tps.account,logout
 admin.users = certServer.tps.users,execute
 admin.groups = certServer.tps.groups,execute
+tokens.read = certServer.tps.tokens,read
+tokens.modify = certServer.tps.tokens,modify
diff --git a/base/tps-tomcat/shared/webapps/tps/WEB-INF/web.xml b/base/tps-tomcat/shared/webapps/tps/WEB-INF/web.xml
index 69316fa542c0ca55ec2bce7c143fed3712940417..056de68e0dd9b98379a97d5d6dea910236912607 100644
--- a/base/tps-tomcat/shared/webapps/tps/WEB-INF/web.xml
+++ b/base/tps-tomcat/shared/webapps/tps/WEB-INF/web.xml
@@ -199,6 +199,19 @@
         </user-data-constraint>
     </security-constraint>
 
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Token Services</web-resource-name>
+            <url-pattern>/rest/tokens/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>*</role-name>
+        </auth-constraint>
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
     <login-config>
         <realm-name>Token Processing Service</realm-name>
     </login-config>
-- 
1.8.1.4

