From 71a314ff7b53ef786c67bd190795342a833ffc3a Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Thu, 26 Jul 2012 20:40:08 -0500
Subject: [PATCH] Moved REST services into separate URLs.

To support different access control configurations the REST
services have been moved out of /pki into several URLs:

 * /admin/groups
 * /admin/users
 * /agent/certrequests
 * /agent/certs
 * /agent/keyrequests
 * /agent/keys
 * /agent/profiles
 * /config/cert
 * /ee/certrequests
 * /ee/certs
 * /installer

The certificate and certificate request EE services are now
located under /ee. The configuration services are located under
/config and /installer. Some of these services may require
service-level authentication and authorization. The agent and
admin services are located under /agent and /admin. They require
realm authentication using client cert or basic authentication and
also require administrator or agent access rights. Existing
servlets should not be affected by this change.

Ticket #107
---
 .../netscape/cms/servlet/test/CARestClient.java    |  17 +-
 base/ca/shared/webapps/ca/WEB-INF/web.xml          |  59 ++++++-
 .../ca/CertificateAuthorityApplication.java        |   4 +
 .../certsrv/group/GroupMemberResource.java         |   2 +-
 .../com/netscape/certsrv/group/GroupResource.java  |   2 +-
 .../netscape/certsrv/user/UserCertResource.java    |   2 +-
 .../com/netscape/certsrv/user/UserResource.java    |   2 +-
 .../netscape/cms/client/cert/CertRestClient.java   |  16 +-
 .../netscape/cms/servlet/cert/CertResource.java    |  31 +---
 .../cms/servlet/cert/CertResourceService.java      | 148 ----------------
 .../{CertResource.java => EECertResource.java}     |  26 +--
 ...urceService.java => EECertResourceService.java} | 193 +--------------------
 .../cms/servlet/csadmin/CMSRestClient.java         |   3 +-
 .../com/netscape/cms/servlet/key/KeyResource.java  |   2 +-
 .../cms/servlet/profile/ProfileResource.java       |   2 +-
 .../cms/servlet/request/CertRequestResource.java   |  17 +-
 .../request/CertRequestResourceService.java        |  36 ----
 .../cms/servlet/request/EECertRequestResource.java |  44 +++++
 .../request/EECertRequestResourceService.java      |  71 ++++++++
 .../cms/servlet/request/KeyRequestResource.java    |   2 +-
 base/kra/functional/drmclient.py                   |  18 +-
 21 files changed, 217 insertions(+), 480 deletions(-)
 copy base/common/src/com/netscape/cms/servlet/cert/{CertResource.java => EECertResource.java} (61%)
 copy base/common/src/com/netscape/cms/servlet/cert/{CertResourceService.java => EECertResourceService.java} (57%)
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/EECertRequestResource.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/EECertRequestResourceService.java

diff --git a/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java b/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java
index 24ce212775b235b8079d7c7339d305e52051c82a..0b593dfed2bcb9504db2b33f0524cda961a77707 100644
--- a/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java
+++ b/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java
@@ -23,7 +23,7 @@ import java.util.Collection;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.cms.client.cli.ClientConfig;
-import com.netscape.cms.servlet.cert.CertResource;
+import com.netscape.cms.servlet.cert.EECertResource;
 import com.netscape.cms.servlet.cert.model.CertDataInfos;
 import com.netscape.cms.servlet.cert.model.CertSearchData;
 import com.netscape.cms.servlet.cert.model.CertificateData;
@@ -32,6 +32,7 @@ import com.netscape.cms.servlet.profile.ProfileResource;
 import com.netscape.cms.servlet.profile.model.ProfileData;
 import com.netscape.cms.servlet.profile.model.ProfileDataInfos;
 import com.netscape.cms.servlet.request.CertRequestResource;
+import com.netscape.cms.servlet.request.EECertRequestResource;
 import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRequestInfos;
@@ -39,15 +40,17 @@ import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
 
 public class CARestClient extends CMSRestClient {
 
-    private CertResource certClient;
+    private EECertResource eeCertClient;
     private CertRequestResource certRequestClient;
+    private EECertRequestResource eeCertRequestClient;
     private ProfileResource profileClient;
 
     public CARestClient(ClientConfig config) throws URISyntaxException {
         super(config);
 
         certRequestClient = createProxy(CertRequestResource.class);
-        certClient = createProxy(CertResource.class);
+        eeCertRequestClient = createProxy(EECertRequestResource.class);
+        eeCertClient = createProxy(EECertResource.class);
         profileClient = createProxy(ProfileResource.class);
     }
 
@@ -62,11 +65,11 @@ public class CARestClient extends CMSRestClient {
     }
 
     public CertDataInfos listCerts(String status) {
-        return certClient.listCerts(status, 100, 10);
+        return eeCertClient.listCerts(status, 100, 10);
     }
 
     public CertDataInfos searchCerts(CertSearchData data) {
-        return certClient.searchCerts(data, 100, 10);
+        return eeCertClient.searchCerts(data, 100, 10);
     }
 
     public ProfileDataInfos listProfiles() {
@@ -88,7 +91,7 @@ public class CARestClient extends CMSRestClient {
             return null;
         }
 
-        return certClient.getCert(id);
+        return eeCertClient.getCert(id);
 
     }
 
@@ -97,7 +100,7 @@ public class CARestClient extends CMSRestClient {
             return null;
         }
 
-        return certRequestClient.enrollCert(data);
+        return eeCertRequestClient.enrollCert(data);
     }
 
     public CertRequestInfo getRequest(RequestId id) {
diff --git a/base/ca/shared/webapps/ca/WEB-INF/web.xml b/base/ca/shared/webapps/ca/WEB-INF/web.xml
index 8471d6cd4f3ac30a4296b120ebf2c897e0d5f7fa..7cb7b2b020726c17316cdfabc8c5a55f3fba4628 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/web.xml
+++ b/base/ca/shared/webapps/ca/WEB-INF/web.xml
@@ -1816,16 +1816,13 @@
                          <param-value> /agent/ca/doRevoke       </param-value> </init-param>
    </servlet>
 
+   <!-- ==================== RESTEasy Configuration =============== -->
+
    <listener>
       <listener-class> org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap </listener-class>
    </listener>
 
    <context-param>
-      <param-name>resteasy.servlet.mapping.prefix</param-name>
-      <param-value>/pki</param-value>
-   </context-param>
-
-   <context-param>
       <param-name>resteasy.resource.method-interceptors</param-name>
       <param-value>
          org.jboss.resteasy.core.ResourceMethodSecurityInterceptor
@@ -1843,7 +1840,57 @@
    
    <servlet-mapping>
       <servlet-name>Resteasy</servlet-name>
-      <url-pattern>/pki/*</url-pattern>
+      <url-pattern>/admin/groups/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/admin/users/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/agent/certrequests/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/agent/certs/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/agent/keyrequests/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/agent/keys/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/agent/profiles/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/config/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/ee/certrequests/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/ee/certs/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/installer/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
index d539bdb44ad6d13bc83e1676e0c4e9833b01e492..d8505b5a060112305c892ec4314daf36e51a7e2f 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
@@ -12,9 +12,11 @@ import com.netscape.cms.servlet.admin.UserCertResourceService;
 import com.netscape.cms.servlet.admin.UserResourceService;
 import com.netscape.cms.servlet.base.CMSException;
 import com.netscape.cms.servlet.cert.CertResourceService;
+import com.netscape.cms.servlet.cert.EECertResourceService;
 import com.netscape.cms.servlet.csadmin.SystemConfigurationResourceService;
 import com.netscape.cms.servlet.profile.ProfileResourceService;
 import com.netscape.cms.servlet.request.CertRequestResourceService;
+import com.netscape.cms.servlet.request.EECertRequestResourceService;
 
 public class CertificateAuthorityApplication extends Application {
     private Set<Object> singletons = new HashSet<Object>();
@@ -26,7 +28,9 @@ public class CertificateAuthorityApplication extends Application {
 
         // certs and requests
         classes.add(CertResourceService.class);
+        classes.add(EECertResourceService.class);
         classes.add(CertRequestResourceService.class);
+        classes.add(EECertRequestResourceService.class);
 
         // profile management
         classes.add(ProfileResourceService.class);
diff --git a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
index 51370f5731f4597ee0e42a318a116e37c1016a86..8a41e26f4bf56c8ff8f1895cb7e99c6045d3f2e9 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
@@ -34,7 +34,7 @@ import org.jboss.resteasy.annotations.ClientResponseType;
 /**
  * @author Endi S. Dewata
  */
-@Path("/groups/{groupID}/members")
+@Path("/admin/groups/{groupID}/members")
 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 5889048ea6546c57b3b57c7afeaa865b1ee9f83b..d57cc6816b8977244e4b74627e0d001b6066d97f 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupResource.java
@@ -34,7 +34,7 @@ import org.jboss.resteasy.annotations.ClientResponseType;
 /**
  * @author Endi S. Dewata
  */
-@Path("/groups")
+@Path("/admin/groups")
 public interface GroupResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/user/UserCertResource.java b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
index b9339bc33ec739af6cff1fa826cab9133c7d4149..61a510325a6d4e090b3e4082f96facae4f42a6c3 100644
--- a/base/common/src/com/netscape/certsrv/user/UserCertResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
@@ -34,7 +34,7 @@ import org.jboss.resteasy.annotations.ClientResponseType;
 /**
  * @author Endi S. Dewata
  */
-@Path("/users/{userID}/certs")
+@Path("/admin/users/{userID}/certs")
 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 fae700bc32a72a633cf715fddd4b2927cc397d04..7294162c10798bea2b14ad37c9c69f25b77cc87f 100644
--- a/base/common/src/com/netscape/certsrv/user/UserResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserResource.java
@@ -34,7 +34,7 @@ import org.jboss.resteasy.annotations.ClientResponseType;
 /**
  * @author Endi S. Dewata
  */
-@Path("/users")
+@Path("/admin/users")
 public interface UserResource {
 
     @GET
diff --git a/base/common/src/com/netscape/cms/client/cert/CertRestClient.java b/base/common/src/com/netscape/cms/client/cert/CertRestClient.java
index 44249523ff601289a48988b8a72fe6984e76e286..08b35f4b86a0ca26aa9c5a180aafdde39f25957c 100644
--- a/base/common/src/com/netscape/cms/client/cert/CertRestClient.java
+++ b/base/common/src/com/netscape/cms/client/cert/CertRestClient.java
@@ -23,12 +23,14 @@ import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.cms.client.cli.ClientConfig;
 import com.netscape.cms.servlet.cert.CertResource;
+import com.netscape.cms.servlet.cert.EECertResource;
 import com.netscape.cms.servlet.cert.model.CertDataInfos;
 import com.netscape.cms.servlet.cert.model.CertRevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertUnrevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertificateData;
 import com.netscape.cms.servlet.csadmin.CMSRestClient;
 import com.netscape.cms.servlet.request.CertRequestResource;
+import com.netscape.cms.servlet.request.EECertRequestResource;
 import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRequestInfos;
@@ -40,24 +42,28 @@ import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
 public class CertRestClient extends CMSRestClient {
 
     public CertResource certClient;
+    public EECertResource eeCertClient;
     public CertRequestResource certRequestResource;
+    public EECertRequestResource eeCertRequestResource;
 
     public CertRestClient(ClientConfig config) throws URISyntaxException {
         super(config);
 
         certClient = createProxy(CertResource.class);
+        eeCertClient = createProxy(EECertResource.class);
         certRequestResource = createProxy(CertRequestResource.class);
+        eeCertRequestResource = createProxy(EECertRequestResource.class);
     }
 
     public CertificateData getCert(CertId id) {
-        return certClient.getCert(id);
+        return eeCertClient.getCert(id);
     }
 
     public CertDataInfos findCerts(String status) {
-        return certClient.listCerts(
+        return eeCertClient.listCerts(
                 status,
-                CertResource.DEFAULT_MAXRESULTS,
-                CertResource.DEFAULT_MAXTIME);
+                EECertResource.DEFAULT_MAXRESULTS,
+                EECertResource.DEFAULT_MAXTIME);
     }
 
     public CertRequestInfo revokeCert(CertId id, CertRevokeRequest request) {
@@ -73,7 +79,7 @@ public class CertRestClient extends CMSRestClient {
     }
 
     public CertRequestInfos enrollRequest(EnrollmentRequestData data){
-        return certRequestResource.enrollCert(data);
+        return eeCertRequestResource.enrollCert(data);
     }
 
     public AgentEnrollmentRequestData reviewRequest(RequestId id){
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertResource.java b/base/common/src/com/netscape/cms/servlet/cert/CertResource.java
index 74e02c3ea9859a109e4c073922da2c6a9b64160b..477a13a68f3bad6705134de92f312b307ae1f3b8 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertResource.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertResource.java
@@ -1,48 +1,19 @@
 package com.netscape.cms.servlet.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;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
 import com.netscape.certsrv.dbs.certdb.CertId;
-import com.netscape.cms.servlet.cert.model.CertDataInfos;
 import com.netscape.cms.servlet.cert.model.CertRevokeRequest;
-import com.netscape.cms.servlet.cert.model.CertSearchData;
 import com.netscape.cms.servlet.cert.model.CertUnrevokeRequest;
-import com.netscape.cms.servlet.cert.model.CertificateData;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 
-@Path("/certs")
+@Path("/agent/certs")
 public interface CertResource {
-    public static final int DEFAULT_MAXTIME = 10;
-    public static final int DEFAULT_MAXRESULTS = 100;
-
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
-    public CertDataInfos listCerts(
-                                 @QueryParam("status") String status,
-                                 @DefaultValue(""+DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults,
-                                 @DefaultValue(""+DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime);
-
-    @POST
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertDataInfos searchCerts(
-                                CertSearchData data,
-                                @DefaultValue(""+DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults,
-                                @DefaultValue(""+DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime);
-
-    @GET
-    @Path("{id}")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
-    public CertificateData getCert(@PathParam("id") CertId id);
 
     @POST
     @Path("{id}/revoke-ca")
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java b/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java
index 395907b5366d5baad567993d5e4d9ec078720ed4..b50f9f869b07155c54d4f56200b20d7ed6b0e1c8 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java
@@ -25,13 +25,7 @@ import java.net.URI;
 import java.security.Principal;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.Enumeration;
-import java.util.List;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
 
 import netscape.security.pkcs.ContentInfo;
 import netscape.security.pkcs.PKCS7;
@@ -46,28 +40,22 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.ICertPrettyPrint;
 import com.netscape.certsrv.ca.ICertificateAuthority;
-import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.request.IRequest;
-import com.netscape.cms.servlet.base.BadRequestException;
 import com.netscape.cms.servlet.base.CMSException;
 import com.netscape.cms.servlet.base.CMSResourceService;
 import com.netscape.cms.servlet.base.UnauthorizedException;
-import com.netscape.cms.servlet.cert.model.CertDataInfo;
-import com.netscape.cms.servlet.cert.model.CertDataInfos;
 import com.netscape.cms.servlet.cert.model.CertRevokeRequest;
-import com.netscape.cms.servlet.cert.model.CertSearchData;
 import com.netscape.cms.servlet.cert.model.CertUnrevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertificateData;
 import com.netscape.cms.servlet.processors.Processor;
 import com.netscape.cms.servlet.request.model.CertRequestDAO;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRetrievalRequestData;
-import com.netscape.cmsutil.ldap.LDAPUtil;
 import com.netscape.cmsutil.util.Utils;
 
 /**
@@ -85,34 +73,6 @@ public class CertResourceService extends CMSResourceService implements CertResou
         repo = authority.getCertificateRepository();
     }
 
-    private void validateRequest(CertId id) {
-        if (id == null) {
-            throw new BadRequestException("Invalid id in CertResourceService.validateRequest.");
-        }
-    }
-
-    @Override
-    public CertificateData getCert(CertId id) {
-        validateRequest(id);
-
-        CertRetrievalRequestData data = new CertRetrievalRequestData();
-        data.setCertId(id);
-
-        CertificateData certData = null;
-
-        try {
-            certData = getCert(data);
-        } catch (EDBRecordNotFoundException e) {
-            throw new CertNotFoundException(id);
-        } catch (EBaseException e) {
-            throw new CMSException("Problem returning certificate: " + id);
-        } catch (CertificateEncodingException e) {
-            throw new CMSException("Problem encoding certificate searched for: " + id);
-        }
-
-        return certData;
-    }
-
     @Override
     public CertRequestInfo revokeCACert(CertId id, CertRevokeRequest request) {
         return revokeCert(id, request, true);
@@ -290,97 +250,6 @@ public class CertResourceService extends CMSResourceService implements CertResou
         }
     }
 
-    private String createSearchFilter(String status) {
-        String filter = "";
-
-        if ((status == null)) {
-            filter = "(serialno=*)";
-            return filter;
-        }
-
-        if (status != null) {
-            filter += "(certStatus=" + LDAPUtil.escapeFilter(status) + ")";
-        }
-
-        return filter;
-    }
-
-    private String createSearchFilter(CertSearchData data) {
-        if (data == null) {
-            return null;
-        }
-
-        return data.buildFilter();
-    }
-
-    @Override
-    public CertDataInfos listCerts(String status, int maxResults, int maxTime) {
-        // get ldap filter
-        String filter = createSearchFilter(status);
-        CMS.debug("listKeys: filter is " + filter);
-
-        CertDataInfos infos;
-        try {
-            infos = getCertList(filter, maxResults, maxTime);
-        } catch (EBaseException e) {
-            e.printStackTrace();
-            throw new CMSException("Error listing certs in CertsResourceService.listCerts!");
-        }
-        return infos;
-    }
-
-    @Override
-    public CertDataInfos searchCerts(CertSearchData data, int maxResults, int maxTime) {
-        if (data == null) {
-            throw new WebApplicationException(Response.Status.BAD_REQUEST);
-        }
-        String filter = createSearchFilter(data);
-        CertDataInfos infos;
-
-        try {
-            infos = getCertList(filter, maxResults, maxTime);
-        } catch (EBaseException e) {
-            e.printStackTrace();
-            throw new CMSException("Error listing certs in CertsResourceService.listCerts!");
-        }
-
-        return infos;
-    }
-
-    /**
-     * Returns list of certs meeting specified search filter.
-     * Currently, vlv searches are not used for certs.
-     *
-     * @param filter
-     * @param maxResults
-     * @param maxTime
-     * @param uriInfo
-     * @return
-     * @throws EBaseException
-     */
-    private CertDataInfos getCertList(String filter, int maxResults, int maxTime)
-            throws EBaseException {
-        List<CertDataInfo> list = new ArrayList<CertDataInfo>();
-        Enumeration<ICertRecord> e = null;
-
-        e = repo.searchCertificates(filter, maxResults, maxTime);
-        if (e == null) {
-            throw new EBaseException("search results are null");
-        }
-
-        while (e.hasMoreElements()) {
-            ICertRecord rec = e.nextElement();
-            if (rec != null) {
-                list.add(createCertDataInfo(rec));
-            }
-        }
-
-        CertDataInfos ret = new CertDataInfos();
-        ret.setCertInfos(list);
-
-        return ret;
-    }
-
     public CertificateData getCert(CertRetrievalRequestData data) throws EBaseException, CertificateEncodingException {
         CertId certId = data.getCertId();
 
@@ -421,23 +290,6 @@ public class CertResourceService extends CMSResourceService implements CertResou
         return certData;
     }
 
-    private CertDataInfo createCertDataInfo(ICertRecord record) throws EBaseException {
-        CertDataInfo info = new CertDataInfo();
-
-        CertId id = new CertId(record.getSerialNumber());
-        info.setID(id);
-
-        X509Certificate cert = record.getCertificate();
-        info.setSubjectDN(cert.getSubjectDN().toString());
-
-        info.setStatus(record.getStatus());
-
-        URI uri = uriInfo.getBaseUriBuilder().path(CertResource.class).path("{id}").build(id.toHexString());
-        info.setLink(new Link("self", uri));
-
-        return info;
-    }
-
     private String getCertChainData(X509CertImpl x509cert) {
         X509Certificate mCACerts[];
 
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertResource.java b/base/common/src/com/netscape/cms/servlet/cert/EECertResource.java
similarity index 61%
copy from base/common/src/com/netscape/cms/servlet/cert/CertResource.java
copy to base/common/src/com/netscape/cms/servlet/cert/EECertResource.java
index 74e02c3ea9859a109e4c073922da2c6a9b64160b..e9035a810ca5ded6c9a9d329bf6fe9670a650a1d 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertResource.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/EECertResource.java
@@ -12,14 +12,12 @@ import javax.ws.rs.core.MediaType;
 
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.cms.servlet.cert.model.CertDataInfos;
-import com.netscape.cms.servlet.cert.model.CertRevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertSearchData;
-import com.netscape.cms.servlet.cert.model.CertUnrevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertificateData;
-import com.netscape.cms.servlet.request.model.CertRequestInfo;
 
-@Path("/certs")
-public interface CertResource {
+@Path("/ee/certs")
+public interface EECertResource {
+
     public static final int DEFAULT_MAXTIME = 10;
     public static final int DEFAULT_MAXRESULTS = 100;
 
@@ -43,22 +41,4 @@ public interface CertResource {
     @Path("{id}")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
     public CertificateData getCert(@PathParam("id") CertId id);
-
-    @POST
-    @Path("{id}/revoke-ca")
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfo revokeCACert(@PathParam("id") CertId id, CertRevokeRequest request);
-
-    @POST
-    @Path("{id}/revoke")
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfo revokeCert(@PathParam("id") CertId id, CertRevokeRequest request);
-
-    @POST
-    @Path("{id}/unrevoke")
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfo unrevokeCert(@PathParam("id") CertId id, CertUnrevokeRequest request);
 }
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java b/base/common/src/com/netscape/cms/servlet/cert/EECertResourceService.java
similarity index 57%
copy from base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java
copy to base/common/src/com/netscape/cms/servlet/cert/EECertResourceService.java
index 395907b5366d5baad567993d5e4d9ec078720ed4..7bd0b9b7a9442d80036ec3d6191752a879a5820b 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertResourceService.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/EECertResourceService.java
@@ -19,8 +19,6 @@
 package com.netscape.cms.servlet.cert;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
 import java.net.URI;
 import java.security.Principal;
 import java.security.cert.CertificateEncodingException;
@@ -37,7 +35,6 @@ import netscape.security.pkcs.ContentInfo;
 import netscape.security.pkcs.PKCS7;
 import netscape.security.pkcs.SignerInfo;
 import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.RevocationReason;
 import netscape.security.x509.X509CertImpl;
 
 import org.jboss.resteasy.plugins.providers.atom.Link;
@@ -50,22 +47,13 @@ import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
-import com.netscape.certsrv.logging.AuditFormat;
-import com.netscape.certsrv.logging.ILogger;
-import com.netscape.certsrv.request.IRequest;
 import com.netscape.cms.servlet.base.BadRequestException;
 import com.netscape.cms.servlet.base.CMSException;
 import com.netscape.cms.servlet.base.CMSResourceService;
-import com.netscape.cms.servlet.base.UnauthorizedException;
 import com.netscape.cms.servlet.cert.model.CertDataInfo;
 import com.netscape.cms.servlet.cert.model.CertDataInfos;
-import com.netscape.cms.servlet.cert.model.CertRevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertSearchData;
-import com.netscape.cms.servlet.cert.model.CertUnrevokeRequest;
 import com.netscape.cms.servlet.cert.model.CertificateData;
-import com.netscape.cms.servlet.processors.Processor;
-import com.netscape.cms.servlet.request.model.CertRequestDAO;
-import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRetrievalRequestData;
 import com.netscape.cmsutil.ldap.LDAPUtil;
 import com.netscape.cmsutil.util.Utils;
@@ -74,13 +62,13 @@ import com.netscape.cmsutil.util.Utils;
  * @author alee
  *
  */
-public class CertResourceService extends CMSResourceService implements CertResource {
+public class EECertResourceService extends CMSResourceService implements EECertResource {
 
     ICertificateAuthority authority;
     ICertificateRepository repo;
 
 
-    public CertResourceService() {
+    public EECertResourceService() {
         authority = (ICertificateAuthority) CMS.getSubsystem("ca");
         repo = authority.getCertificateRepository();
     }
@@ -113,183 +101,6 @@ public class CertResourceService extends CMSResourceService implements CertResou
         return certData;
     }
 
-    @Override
-    public CertRequestInfo revokeCACert(CertId id, CertRevokeRequest request) {
-        return revokeCert(id, request, true);
-    }
-
-    @Override
-    public CertRequestInfo revokeCert(CertId id, CertRevokeRequest request) {
-        return revokeCert(id, request, false);
-    }
-
-    public CertRequestInfo revokeCert(CertId id, CertRevokeRequest request, boolean caCert) {
-        RevocationReason revReason = request.getReason();
-        if (revReason == RevocationReason.REMOVE_FROM_CRL) {
-            CertUnrevokeRequest unrevRequest = new CertUnrevokeRequest();
-            unrevRequest.setRequestID(request.getRequestID());
-            return unrevokeCert(id, unrevRequest);
-        }
-
-        RevocationProcessor processor;
-        try {
-            processor = new RevocationProcessor("caDoRevoke-agent", getLocale());
-            processor.setStartTime(CMS.getCurrentDate().getTime());
-
-            // TODO: set initiative based on auth info
-            processor.setInitiative(AuditFormat.FROMAGENT);
-
-            processor.setSerialNumber(id);
-            processor.setRequestID(request.getRequestID());
-
-            processor.setRevocationReason(revReason);
-            processor.setRequestType(revReason == RevocationReason.CERTIFICATE_HOLD
-                    ? RevocationProcessor.ON_HOLD : RevocationProcessor.REVOKE);
-            processor.setInvalidityDate(request.getInvalidityDate());
-            processor.setComments(request.getComments());
-
-            processor.setAuthority(authority);
-
-        } catch (EBaseException e) {
-            throw new CMSException(e.getMessage());
-        }
-
-        try {
-            X509Certificate clientCert = null;
-            try {
-                clientCert = Processor.getSSLClientCertificate(servletRequest);
-            } catch (EBaseException e) {
-                // No client certificate, ignore.
-            }
-
-            ICertRecord clientRecord = null;
-            BigInteger clientSerialNumber = null;
-            String clientSubjectDN = null;
-
-            if (clientCert != null) {
-                clientSerialNumber = clientCert.getSerialNumber();
-                clientSubjectDN = clientCert.getSubjectDN().toString();
-                clientRecord = processor.getCertificateRecord(clientSerialNumber);
-
-                // Verify client cert is not revoked.
-                // TODO: This should be checked during authentication.
-                if (clientRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
-                    throw new UnauthorizedException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
-                }
-            }
-
-            // Find target cert record if different from client cert.
-            ICertRecord targetRecord = id.equals(clientSerialNumber) ? clientRecord : processor.getCertificateRecord(id);
-            X509CertImpl targetCert = targetRecord.getCertificate();
-
-            processor.createCRLExtension();
-            processor.validateCertificateToRevoke(clientSubjectDN, targetRecord, caCert);
-            processor.addCertificateToRevoke(targetCert);
-            processor.createRevocationRequest();
-
-            processor.auditChangeRequest(ILogger.SUCCESS);
-
-        } catch (CMSException e) {
-            processor.log(ILogger.LL_FAILURE, e.getMessage());
-            processor.auditChangeRequest(ILogger.FAILURE);
-            throw e;
-
-        } catch (EBaseException e) {
-            processor.log(ILogger.LL_FAILURE, "Error " + e);
-            processor.auditChangeRequest(ILogger.FAILURE);
-
-            throw new CMSException(e.getMessage());
-
-        } catch (IOException e) {
-            processor.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString()));
-            processor.auditChangeRequest(ILogger.FAILURE);
-
-            throw new CMSException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
-        }
-
-        // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
-        // to distinguish which type of signed audit log message to save
-        // as a failure outcome in case an exception occurs
-
-        try {
-            processor.processRevocationRequest();
-
-            processor.auditChangeRequestProcessed(ILogger.SUCCESS);
-
-        } catch (EBaseException e) {
-            processor.log(ILogger.LL_FAILURE, "Error " + e);
-            processor.auditChangeRequestProcessed(ILogger.FAILURE);
-
-            throw new CMSException(e.getMessage());
-        }
-
-        try {
-            IRequest certRequest = processor.getRequest();
-            CertRequestDAO dao = new CertRequestDAO();
-            return dao.getRequest(certRequest.getRequestId(), uriInfo);
-
-        } catch (EBaseException e) {
-            throw new CMSException(e.getMessage());
-        }
-    }
-
-    @Override
-    public CertRequestInfo unrevokeCert(CertId id, CertUnrevokeRequest request) {
-        RevocationProcessor processor;
-        try {
-            processor = new RevocationProcessor("caDoUnrevoke", getLocale());
-
-            // TODO: set initiative based on auth info
-            processor.setInitiative(AuditFormat.FROMAGENT);
-
-            processor.setSerialNumber(id);
-            processor.setRequestID(request.getRequestID());
-            processor.setRevocationReason(RevocationReason.CERTIFICATE_HOLD);
-            processor.setAuthority(authority);
-
-        } catch (EBaseException e) {
-            throw new CMSException(e.getMessage());
-        }
-
-        try {
-            processor.addSerialNumberToUnrevoke(id.toBigInteger());
-            processor.createUnrevocationRequest();
-
-            processor.auditChangeRequest(ILogger.SUCCESS);
-
-        } catch (EBaseException e) {
-            processor.log(ILogger.LL_FAILURE, "Error " + e);
-            processor.auditChangeRequest(ILogger.FAILURE);
-
-            throw new CMSException(e.getMessage());
-        }
-
-        // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
-        // to distinguish which type of signed audit log message to save
-        // as a failure outcome in case an exception occurs
-
-        try {
-            processor.processUnrevocationRequest();
-
-            processor.auditChangeRequestProcessed(ILogger.SUCCESS);
-
-        } catch (EBaseException e) {
-            processor.log(ILogger.LL_FAILURE, "Error " + e);
-            processor.auditChangeRequestProcessed(ILogger.FAILURE);
-
-            throw new CMSException(e.getMessage());
-        }
-
-        try {
-            IRequest certRequest = processor.getRequest();
-            CertRequestDAO dao = new CertRequestDAO();
-            return dao.getRequest(certRequest.getRequestId(), uriInfo);
-
-        } catch (EBaseException e) {
-            throw new CMSException(e.getMessage());
-        }
-    }
-
     private String createSearchFilter(String status) {
         String filter = "";
 
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CMSRestClient.java b/base/common/src/com/netscape/cms/servlet/csadmin/CMSRestClient.java
index 2317eac47021c53ab89ddeac4e98aae7ddf3ed70..8eb80d25a44f9e27c02e81026e3d00a05ad17237 100644
--- a/base/common/src/com/netscape/cms/servlet/csadmin/CMSRestClient.java
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/CMSRestClient.java
@@ -275,8 +275,7 @@ public abstract class CMSRestClient {
     }
 
     public <T> T createProxy(Class<T> clazz) throws URISyntaxException {
-        URI uri = new URI(config.getServerURI()+"/pki");
-        return ProxyFactory.create(clazz, uri, executor, providerFactory);
+        return ProxyFactory.create(clazz, config.getServerURI(), executor, providerFactory);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyResource.java b/base/common/src/com/netscape/cms/servlet/key/KeyResource.java
index 9a9b5db1a9aafb412fe5f4b1444defdf09c2d6fe..cba7cd1b6b0a34d21232351a1e3b640eff5095d3 100644
--- a/base/common/src/com/netscape/cms/servlet/key/KeyResource.java
+++ b/base/common/src/com/netscape/cms/servlet/key/KeyResource.java
@@ -14,7 +14,7 @@ import com.netscape.cms.servlet.key.model.KeyData;
 import com.netscape.cms.servlet.key.model.KeyDataInfos;
 import com.netscape.cms.servlet.request.model.RecoveryRequestData;
 
-@Path("/keys")
+@Path("/agent/keys")
 public interface KeyResource {
 
     public static final int DEFAULT_MAXTIME = 10;
diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileResource.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileResource.java
index e402aeadd39315ec1d78923df976796d131cc510..a2768980cb70c4d283c284d6b072cd469f7db31f 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileResource.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileResource.java
@@ -9,7 +9,7 @@ import javax.ws.rs.core.MediaType;
 import com.netscape.cms.servlet.profile.model.ProfileData;
 import com.netscape.cms.servlet.profile.model.ProfileDataInfos;
 
-@Path("/profiles")
+@Path("/agent/profiles")
 public interface ProfileResource {
 
     @GET
diff --git a/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java
index f350747388f6b83a7b54560ce9b57a9490b09c62..45525f198bf10c63e464e5b44f3f7ba540c43e59 100644
--- a/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java
+++ b/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java
@@ -26,15 +26,13 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
 
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRequestInfos;
-import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
 
-@Path("/certrequests")
+@Path("/agent/certrequests")
 public interface CertRequestResource {
 
     public static final int DEFAULT_START = 0;
@@ -67,19 +65,6 @@ public interface CertRequestResource {
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
     public AgentEnrollmentRequestData reviewRequest(@PathParam("id") RequestId id);
 
-    // Enrollment - used to test integration with a browser
-    @POST
-    @Path("enroll")
-    @Produces({ MediaType.TEXT_XML })
-    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
-    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form);
-
-    @POST
-    @Path("enroll")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfos enrollCert(EnrollmentRequestData data);
-
     @POST
     @Path("{id}/approve")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
diff --git a/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java b/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java
index d107e21914b2b9715ed9adcf02491eacf82ea99d..4b845e122a25ee6bd403eb14ca0d2b36def6ba0b 100644
--- a/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java
+++ b/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java
@@ -19,12 +19,9 @@
 package com.netscape.cms.servlet.request;
 
 import javax.ws.rs.PathParam;
-import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 
 import com.netscape.certsrv.apps.CMS;
-import com.netscape.certsrv.authentication.EAuthException;
-import com.netscape.certsrv.authorization.EAuthzException;
 import com.netscape.certsrv.base.BadRequestDataException;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.profile.EDeferException;
@@ -39,12 +36,10 @@ import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData;
 import com.netscape.cms.servlet.request.model.CertRequestDAO;
 import com.netscape.cms.servlet.request.model.CertRequestInfo;
 import com.netscape.cms.servlet.request.model.CertRequestInfos;
-import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
 import com.netscape.cmsutil.ldap.LDAPUtil;
 
 /**
  * @author alee
- *
  */
 public class CertRequestResourceService extends CMSResourceService implements CertRequestResource {
 
@@ -72,37 +67,6 @@ public class CertRequestResourceService extends CMSResourceService implements Ce
         return info;
     }
 
-    // Enrollment - used to test integration with a browser
-    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form) {
-        EnrollmentRequestData data = new EnrollmentRequestData(form);
-        return enrollCert(data);
-    }
-
-    public CertRequestInfos enrollCert(EnrollmentRequestData data) {
-        CertRequestInfos infos;
-        if (data == null) {
-            throw new BadRequestException("Bad data input into CertRequestResourceService.enrollCert!");
-        }
-        CertRequestDAO dao = new CertRequestDAO();
-
-        try {
-            infos = dao.submitRequest(data, servletRequest, uriInfo, getLocale());
-        } catch (EAuthException e) {
-            CMS.debug("enrollCert: authentication failed: " + e);
-            throw new CMSException(Response.Status.UNAUTHORIZED, e.toString());
-        } catch (EAuthzException e) {
-            CMS.debug("enrollCert: authorization failed: " + e);
-            throw new CMSException(Response.Status.UNAUTHORIZED, e.toString());
-        } catch (BadRequestDataException e) {
-            CMS.debug("enrollCert: bad request data: " + e);
-            throw new CMSException(Response.Status.BAD_REQUEST, e.toString());
-        } catch (EBaseException e) {
-            throw new CMSException(e.toString());
-        }
-
-        return infos;
-    }
-
     public void approveRequest(RequestId id, AgentEnrollmentRequestData data) {
         changeRequestState(id, data, "approve");
     }
diff --git a/base/common/src/com/netscape/cms/servlet/request/EECertRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/EECertRequestResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..abb142827417c31089571df9de6344fc9f1c64fe
--- /dev/null
+++ b/base/common/src/com/netscape/cms/servlet/request/EECertRequestResource.java
@@ -0,0 +1,44 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import com.netscape.cms.servlet.request.model.CertRequestInfos;
+import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
+
+@Path("/ee/certrequests")
+public interface EECertRequestResource {
+
+    @POST
+    @Path("enroll")
+    @Produces({ MediaType.TEXT_XML })
+    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
+    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form);
+
+    @POST
+    @Path("enroll")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public CertRequestInfos enrollCert(EnrollmentRequestData data);
+}
diff --git a/base/common/src/com/netscape/cms/servlet/request/EECertRequestResourceService.java b/base/common/src/com/netscape/cms/servlet/request/EECertRequestResourceService.java
new file mode 100644
index 0000000000000000000000000000000000000000..aff60769ab2d27373ac849bb230c650903a50b4e
--- /dev/null
+++ b/base/common/src/com/netscape/cms/servlet/request/EECertRequestResourceService.java
@@ -0,0 +1,71 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.request;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.servlet.base.BadRequestException;
+import com.netscape.cms.servlet.base.CMSException;
+import com.netscape.cms.servlet.base.CMSResourceService;
+import com.netscape.cms.servlet.request.model.CertRequestDAO;
+import com.netscape.cms.servlet.request.model.CertRequestInfos;
+import com.netscape.cms.servlet.request.model.EnrollmentRequestData;
+
+/**
+ * @author alee
+ */
+public class EECertRequestResourceService extends CMSResourceService implements EECertRequestResource {
+
+    // Enrollment - used to test integration with a browser
+    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form) {
+        EnrollmentRequestData data = new EnrollmentRequestData(form);
+        return enrollCert(data);
+    }
+
+    public CertRequestInfos enrollCert(EnrollmentRequestData data) {
+        CertRequestInfos infos;
+        if (data == null) {
+            throw new BadRequestException("Bad data input into CertRequestResourceService.enrollCert!");
+        }
+        CertRequestDAO dao = new CertRequestDAO();
+
+        try {
+            infos = dao.submitRequest(data, servletRequest, uriInfo, getLocale());
+        } catch (EAuthException e) {
+            CMS.debug("enrollCert: authentication failed: " + e);
+            throw new CMSException(Response.Status.UNAUTHORIZED, e.toString());
+        } catch (EAuthzException e) {
+            CMS.debug("enrollCert: authorization failed: " + e);
+            throw new CMSException(Response.Status.UNAUTHORIZED, e.toString());
+        } catch (BadRequestDataException e) {
+            CMS.debug("enrollCert: bad request data: " + e);
+            throw new CMSException(Response.Status.BAD_REQUEST, e.toString());
+        } catch (EBaseException e) {
+            throw new CMSException(e.toString());
+        }
+
+        return infos;
+    }
+}
diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
index cf326540daf6212baa071b2906282be44182c5ae..91cdbbc9f14ff49d8e3d5f1ca2d9abe9fe766b9e 100644
--- a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
+++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
@@ -17,7 +17,7 @@ import com.netscape.cms.servlet.request.model.KeyRequestInfo;
 import com.netscape.cms.servlet.request.model.KeyRequestInfos;
 import com.netscape.cms.servlet.request.model.RecoveryRequestData;
 
-@Path("/keyrequests")
+@Path("/agent/keyrequests")
 public interface KeyRequestResource {
     public final String SYMMETRIC_KEY_TYPE = "symmetricKey";
     public final String PASS_PHRASE_TYPE = "passPhrase";
diff --git a/base/kra/functional/drmclient.py b/base/kra/functional/drmclient.py
index 62940fdf247bb81413dd2b44302acfdd147d5571..f6146efbdc9b3194782b52ec2509af701ea444c7 100644
--- a/base/kra/functional/drmclient.py
+++ b/base/kra/functional/drmclient.py
@@ -612,7 +612,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests/archive',
+            self._request('/kra/agent/keyrequests/archive',
                          self.kra_agent_port,
                          self.POST,
                          etree.tostring(request.getroot(), encoding='UTF-8'))            
@@ -637,7 +637,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/config/cert/transport',
+            self._request('/kra/config/cert/transport',
                          self.kra_agent_port,
                          self.GET,
                          None)            
@@ -675,7 +675,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keys',
+            self._request('/kra/agent/keys',
                           self.kra_agent_port,
                           self.GET,
                           get_args)
@@ -717,7 +717,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests',
+            self._request('/kra/agent/keyrequests',
                           self.kra_agent_port,
                           self.GET,
                           get_args)
@@ -750,7 +750,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests/recover',
+            self._request('/kra/agent/keyrequests/recover',
                          self.kra_agent_port,
                          self.POST,
                          etree.tostring(request.getroot(), encoding='UTF-8'))            
@@ -798,7 +798,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests/approve/'+ request_id,
+            self._request('/kra/agent/keyrequests/approve/'+ request_id,
                          self.kra_agent_port,
                          self.POST,
                          None)            
@@ -820,7 +820,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests/reject/'+ request_id,
+            self._request('/kra/agent/keyrequests/reject/'+ request_id,
                          self.kra_agent_port,
                          self.POST,
                          None)            
@@ -842,7 +842,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keyrequests/cancel/'+ request_id,
+            self._request('/kra/agent/keyrequests/cancel/'+ request_id,
                          self.kra_agent_port,
                          self.POST,
                          None)            
@@ -898,7 +898,7 @@ class kra:
         
         #Call CMS
         http_status, http_reason_phrase, http_headers, http_body = \
-            self._request('/kra/pki/keys/retrieve',
+            self._request('/kra/agent/keys/retrieve',
                          self.kra_agent_port,
                          self.POST,
                          etree.tostring(request.getroot(), encoding='UTF-8'))            
-- 
1.7.11.2

