>From a0d4754789b14665624236defcfbbd476aacf43f Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Mon, 12 Dec 2011 22:57:33 -0500
Subject: [PATCH] Initial skeleton code for drm resteasy interface

---
 pki/.classpath                                     |    1 +
 .../src/com/netscape/certsrv/request/IRequest.java |    2 +
 .../cms/servlet/rest/KeyRequestResource.java       |  132 +++++++++++++++++
 .../cms/servlet/rest/KeyRequestsResource.java      |   72 ++++++++++
 .../com/netscape/cms/servlet/rest/KeyResource.java |  134 ++++++++++++++++++
 .../netscape/cms/servlet/rest/KeysResource.java    |   68 +++++++++
 .../servlet/rest/model/ArchivalRequestData.java    |  123 ++++++++++++++++
 .../netscape/cms/servlet/rest/model/KeyDAO.java    |   96 +++++++++++++
 .../netscape/cms/servlet/rest/model/KeyData.java   |   57 ++++++++
 .../cms/servlet/rest/model/KeyDataInfo.java        |   96 +++++++++++++
 .../cms/servlet/rest/model/KeyRequestDAO.java      |  149 ++++++++++++++++++++
 .../cms/servlet/rest/model/KeyRequestInfo.java     |  127 +++++++++++++++++
 .../servlet/rest/model/RecoveryRequestData.java    |  122 ++++++++++++++++
 pki/base/kra/shared/webapps/kra/WEB-INF/web.xml    |   27 ++++
 pki/specs/pki-core.spec                            |    6 +-
 15 files changed, 1211 insertions(+), 1 deletions(-)
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestResource.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestsResource.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/KeyResource.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/KeysResource.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/ArchivalRequestData.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDAO.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyData.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDataInfo.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestDAO.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestInfo.java
 create mode 100644 pki/base/common/src/com/netscape/cms/servlet/rest/model/RecoveryRequestData.java

diff --git a/pki/.classpath b/pki/.classpath
index 3370acccf7772b2c62587787b6d2a42b8b66a1a0..d87e36a05ff2c084d49c695ff0c9e9a432add395 100644
--- a/pki/.classpath
+++ b/pki/.classpath
@@ -22,5 +22,6 @@
 	<classpathentry kind="lib" path="/usr/share/java/servlet.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/xerces-j2.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/junit4.jar"/>
+	<classpathentry kind="lib" path="/usr/share/candlepin/lib/jaxrs-api-2.2.1.GA.jar"/>
 	<classpathentry kind="output" path="build/classes"/>
 </classpath>
diff --git a/pki/base/common/src/com/netscape/certsrv/request/IRequest.java b/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
index c509e2966cd1dbcdf8e4e18289ae1a4041f7ce56..4cd7b580086be67fe444c7682e5fa16084bf55a2 100644
--- a/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -71,6 +71,8 @@ public interface IRequest {
     public static final String CLA_UNCERT4CRL_REQUEST = "uncert4crl";
     public static final String NETKEY_KEYGEN_REQUEST = "netkeyKeygen";
     public static final String NETKEY_KEYRECOVERY_REQUEST = "netkeyKeyRecovery";
+    public static final String SECURITY_DATA_ENROLLMENT_REQUEST = "securityDataEnrollment";
+    public static final String SECURITY_DATA_RECOVERY_REQUEST = "securityDataRecovery";
 
     public static final String REQUESTOR_NAME = "csrRequestorName";
     public static final String REQUESTOR_PHONE = "csrRequestorPhone";
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestResource.java b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f9892585d866e908280bcb0fcffa7e57089d7bc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestResource.java
@@ -0,0 +1,132 @@
+// --- 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.rest;
+
+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.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.servlet.rest.model.KeyRequestDAO;
+import com.netscape.cms.servlet.rest.model.KeyRequestInfo;
+import com.netscape.cms.servlet.rest.model.ArchivalRequestData;
+import com.netscape.cms.servlet.rest.model.RecoveryRequestData;
+ 
+/**
+ * @author alee
+ * 
+ */
+@Path("/keyrequest")
+public class KeyRequestResource {
+    
+    @Context
+    UriInfo uriInfo;
+    
+    /**
+     * Used to retrieve key request info for a specific request
+     */
+    @GET
+    @Path("{id}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML  })
+    public KeyRequestInfo getRequestInfo(@PathParam("id") String id) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        KeyRequestInfo info;
+        try {
+            info = dao.getRequest(id, uriInfo);
+        } catch (EBaseException e) {
+            // log error
+            e.printStackTrace();
+            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
+        }
+        return info;
+    }
+    
+    // Archiving - used to test integration with a browser
+    @POST
+    @Path("archive")
+    @Produces({ MediaType.TEXT_XML })
+    public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form) {
+        ArchivalRequestData data = new ArchivalRequestData(form);
+        return archiveKey(data);
+    }
+
+    @POST
+    @Path("archive")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public KeyRequestInfo archiveKey(ArchivalRequestData data) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        KeyRequestInfo info =  dao.submitRequest(data, uriInfo);
+        return info;
+    }
+    
+    //Recovery - used to test integration with a browser
+    @POST
+    @Path("recover")
+    @Produces({ MediaType.TEXT_XML })
+    public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form) {
+        RecoveryRequestData data = new RecoveryRequestData(form);
+        return recoverKey(data);
+    }
+
+    @POST
+    @Path("recover")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public KeyRequestInfo recoverKey(RecoveryRequestData data) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        KeyRequestInfo info =  dao.submitRequest(data, uriInfo);
+        return info;
+    }
+    
+    @POST
+    @Path("approve/{id}")
+    public void approveRequest(@PathParam("id") String id) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        dao.approveRequest(id);
+    }
+    
+    @POST
+    @Path("reject/{id}")
+    public void rejectRequest(@PathParam("id") String id) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        dao.rejectRequest(id);
+    }
+    
+    @POST
+    @Path("cancel/{id}")
+    public void cancelRequest(@PathParam("id") String id) {
+        // auth and authz
+        KeyRequestDAO dao = new KeyRequestDAO();
+        dao.cancelRequest(id);
+    }
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestsResource.java b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestsResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..858597f700e186016aec09fab9cc64984bc85a79
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyRequestsResource.java
@@ -0,0 +1,72 @@
+// --- 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.rest;
+
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.servlet.rest.model.KeyRequestDAO;
+import com.netscape.cms.servlet.rest.model.KeyRequestInfo;
+ 
+/**
+ * @author alee
+ *
+ */
+@Path("/keyrequests")
+public class KeyRequestsResource {
+
+    @Context
+    UriInfo uriInfo;
+
+    /**
+     * Used to generate list of key requests based on the search parameters
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    public List<KeyRequestInfo> listRequests() {
+        // auth and authz
+        // parse search parameters from uriInfo and create search filter
+        // String clientID = uriInfo.getQueryParameters().getFirst(CLIENT_ID);
+        String filter = "requestState=complete";
+        KeyRequestDAO reqDAO = new KeyRequestDAO();
+        List<KeyRequestInfo> requests;
+        try {
+            CMS.debug("alee: getting requests");
+            requests = reqDAO.listRequests(filter, uriInfo);
+            CMS.debug("alee: got request");
+        } catch (EBaseException e) {
+            // log error
+            e.printStackTrace();
+            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
+        }
+        CMS.debug("going into return");
+        return requests;
+    }
+        
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/KeyResource.java b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d58800a4e0b540b9194ec19e6e3c72db497cc89
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/KeyResource.java
@@ -0,0 +1,134 @@
+// --- 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.rest;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import com.netscape.cms.servlet.rest.model.KeyDAO;
+import com.netscape.cms.servlet.rest.model.KeyData;
+import com.netscape.cms.servlet.rest.model.KeyRequestDAO;
+import com.netscape.cms.servlet.rest.model.KeyRequestInfo;
+import com.netscape.cms.servlet.rest.model.RecoveryRequestData;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.base.EBaseException;
+/**
+ * @author alee
+ * 
+ */
+@Path("/key")
+public class KeyResource {
+    
+    @Context
+    UriInfo uriInfo;
+    
+    /**
+     * Used to retrieve a key
+     * @param data
+     * @return
+     */
+    @POST
+    @Path("retrieve")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public KeyData retrieveKey(RecoveryRequestData data) {
+        // auth and authz
+        String keyId = validateRequest(data);
+        KeyDAO dao = new KeyDAO();
+        KeyData keyData;
+        try {
+            keyData = dao.getKey(keyId, data);
+        } catch (EBaseException e) {
+            // log error
+            e.printStackTrace();
+            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
+        }
+        if (keyData == null) {
+            // no key record
+            throw new WebApplicationException(Response.Status.GONE);
+        }
+        return keyData;
+    }
+    
+    // retrieval - used to test integration with a browser
+    @POST
+    @Path("retrieve")
+    @Produces(MediaType.TEXT_XML)
+    public KeyData retrieveKey(MultivaluedMap<String, String> form) {
+        RecoveryRequestData data = new RecoveryRequestData(form);
+        return retrieveKey(data);
+    }
+    
+    private String validateRequest(RecoveryRequestData data) {
+        // confirm that at least one wrapping method exists
+        if ((data.getTransWrappedSessionKey() == null) && (data.getTransWrappedSessionKey() == null)) {
+            // log error
+            throw new WebApplicationException(Response.Status.BAD_REQUEST);
+        }
+        
+        // confirm request exists
+        String reqId = data.getRequestId();
+        if (reqId == null) {
+            // log error
+            throw new WebApplicationException(Response.Status.BAD_REQUEST);
+        }
+        KeyRequestDAO reqDAO = new KeyRequestDAO();
+        KeyRequestInfo reqInfo;
+        try {
+            reqInfo = reqDAO.getRequest(reqId, uriInfo);
+        } catch (EBaseException e1) {
+            // failed to get request
+            e1.printStackTrace();
+            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
+        }
+        if (reqInfo == null) {
+            // request not found
+            throw new WebApplicationException(Response.Status.GONE);
+        }
+        
+        //confirm request is of the right type
+        String type = reqInfo.getRequestType();
+        if (!type.equals(IRequest.SECURITY_DATA_RECOVERY_REQUEST)) {
+            // log error
+            throw new WebApplicationException(Response.Status.BAD_REQUEST);
+        }
+        
+        //confirm that agent is originator of request, else throw 401 
+        //  TO-DO
+        
+        // confirm request is in approved state
+        String status = reqInfo.getRequestStatus();
+        if (!status.equals(RequestStatus.APPROVED.toString())) {
+            // log error
+            throw new WebApplicationException(Response.Status.UNAUTHORIZED);
+        }
+        
+        String keyURL = reqInfo.getKeyURL();
+        return keyURL.substring(keyURL.lastIndexOf("/")); 
+    }
+
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/KeysResource.java b/pki/base/common/src/com/netscape/cms/servlet/rest/KeysResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..34ba758a3170799f3c3733e10c15eb0ce3182afa
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/KeysResource.java
@@ -0,0 +1,68 @@
+// --- 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.rest;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+ 
+import java.util.List;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.servlet.rest.model.KeyDAO;
+import com.netscape.cms.servlet.rest.model.KeyDataInfo;
+
+/**
+ * @author alee
+ * 
+ */
+@Path("/keys")
+public class KeysResource {
+    @Context
+    UriInfo uriInfo;
+
+    /**
+     * Used to generate list of key infos based on the search parameters
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
+    public List<KeyDataInfo> listKeys() {
+        // auth and authz
+        // parse search parameters from uriInfo and create search filter
+        // String clientID = uriInfo.getQueryParameters().getFirst(CLIENT_ID);
+        String filter = "test-filter";
+        KeyDAO dao = new KeyDAO();
+        List<KeyDataInfo> info;
+        try {
+            info = dao.listKeys(filter, uriInfo);
+        } catch (EBaseException e) {
+            e.printStackTrace();
+            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
+        }
+        return info;
+    }
+
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/ArchivalRequestData.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/ArchivalRequestData.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc3fa5a925d9658157dabf54f9ed864323bab72a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/ArchivalRequestData.java
@@ -0,0 +1,123 @@
+// --- 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.rest.model;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * @author alee
+ *
+ */
+@XmlRootElement(name="SecurityDataArchivalRequest")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ArchivalRequestData {
+
+    private static final String CLIENT_ID = "clientID";
+    private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
+    private static final String DATA_TYPE = "dataType";
+    private static final String WRAPPED_PRIVATE_DATA = "wrappedPrivateData";
+
+    @XmlElement
+    protected String clientId;
+    
+    @XmlElement
+    protected String transWrappedSessionKey;
+    
+    @XmlElement
+    protected String dataType;
+    
+    @XmlElement
+    protected String wrappedPrivateData;
+    
+    public ArchivalRequestData() {
+        // required for JAXB (defaults)
+    }
+    
+    public ArchivalRequestData(MultivaluedMap<String, String> form) {        
+        clientId = form.getFirst(CLIENT_ID);
+        transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY);
+        dataType = form.getFirst(DATA_TYPE);
+        wrappedPrivateData = form.getFirst(WRAPPED_PRIVATE_DATA);
+    }
+
+    /**
+     * @return the clientId
+     */
+    public String getClientId() {
+        return clientId;
+    }
+
+    /**
+     * @param clientId the clientId to set
+     */
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    /**
+     * @return the transWrappedSessionKey
+     */
+    public String getTransWrappedSessionKey() {
+        return transWrappedSessionKey;
+    }
+
+    /**
+     * @param transWrappedSessionKey the transWrappedSessionKey to set
+     */
+    public void setTransWrappedSessionKey(String transWrappedSessionKey) {
+        this.transWrappedSessionKey = transWrappedSessionKey;
+    }
+
+    /**
+     * @return the dataType
+     */
+    public String getDataType() {
+        return dataType;
+    }
+
+    /**
+     * @param dataType the dataType to set
+     */
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    /**
+     * @return the wrappedPrivateData
+     */
+    public String getWrappedPrivateData() {
+        return wrappedPrivateData;
+    }
+
+    /**
+     * @param wrappedPrivateData the wrappedPrivateData to set
+     */
+    public void setWrappedPrivateData(String wrappedPrivateData) {
+        this.wrappedPrivateData = wrappedPrivateData;
+    }
+    
+
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDAO.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a96f75442b1015d1413fb564d6ecd55a12b6408
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDAO.java
@@ -0,0 +1,96 @@
+// --- 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.rest.model;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import javax.ws.rs.core.UriInfo;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+
+/**
+ * @author alee
+ *
+ */
+public class KeyDAO {
+
+    private IKeyRepository repo;
+    private int maxSize = 100;
+    private int maxTime = 20;
+    
+    public KeyDAO() {
+        IKeyRecoveryAuthority kra = null;
+        kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
+        repo = kra.getKeyRepository();
+    }
+    /**
+     * This will find the keys in the database matching the specified search parameters
+     * Needs input validation and probably paging, maybe using the vlv functions
+     * @throws EBaseException 
+     */
+    public List<KeyDataInfo> listKeys(String filter, UriInfo uriInfo) throws EBaseException {
+        List <KeyDataInfo> list = new ArrayList<KeyDataInfo>();         
+        Enumeration<IKeyRecord> e = null;
+        try {
+            e = repo.searchKeys(filter, maxSize, maxTime);
+        } catch (EBaseException e1) {
+            // log error and exception
+            e1.printStackTrace();
+            throw e1;
+        }
+        if (e == null) {
+            // log search failed
+            throw new EBaseException("Key Search failed. e is null");
+        }
+        
+        while (e.hasMoreElements()) {
+            IKeyRecord rec = e.nextElement();
+            list.add(new KeyDataInfo(rec, uriInfo));
+        }
+        return list;
+    }
+    
+    public KeyData getKey(String keyId, RecoveryRequestData data) throws EBaseException {
+        KeyData keyData = null;
+        BigInteger serial = new BigInteger(keyId);
+        
+        try {
+            // get wrapped key
+            IKeyRecord rec = repo.readKeyRecord(serial);
+            if (rec == null) {
+                // key does not exist
+                // log the error
+                return null;  
+            }
+            // TODO unwrap the key and wrap with the credential in RecoveryRequestData
+            // need to figure out how to do this with jmagne
+        } catch (EBaseException e){
+            // log error
+            throw e;
+        }
+        
+        return keyData;
+    }
+    
+    
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyData.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyData.java
new file mode 100644
index 0000000000000000000000000000000000000000..90e3aa4a874aa63ffd91a38d1b22610650aa685c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyData.java
@@ -0,0 +1,57 @@
+// --- 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.rest.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * @author alee
+ *
+ */
+@XmlRootElement(name="SecurityData")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KeyData {
+    @XmlElement
+    String wrappedPrivateData;
+    
+    public KeyData() {
+        // required for JAXB (defaults)
+    }
+
+    /**
+     * @return the wrappedPrivateData
+     */
+    public String getWrappedPrivateData() {
+        return wrappedPrivateData;
+    }
+
+    /**
+     * @param wrappedPrivateData the wrappedPrivateData to set
+     */
+    public void setWrappedPrivateData(String wrappedPrivateData) {
+        this.wrappedPrivateData = wrappedPrivateData;
+    }
+    
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDataInfo.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDataInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..c037c8fb014795c09b4146233790a759fe8e2d92
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyDataInfo.java
@@ -0,0 +1,96 @@
+// --- 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.rest.model;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+
+/**
+ * @author alee
+ *
+ */
+@XmlRootElement(name="SecurityDataInfo")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KeyDataInfo {
+    
+    @XmlElement
+    protected String keyURL;
+
+    @XmlElement
+    protected String clientID;
+    
+    public KeyDataInfo() {
+        // required for JAXB (defaults)
+    }
+    
+    public KeyDataInfo(IKeyRecord rec, UriInfo uriInfo) {
+        String serial = null;
+        try {
+            serial = (rec.getSerialNumber()).toString();
+        } catch (EBaseException e) {
+            // log error - unable to get serial number
+            // do something
+            e.printStackTrace();
+        }
+        UriBuilder keyBuilder = uriInfo.getBaseUriBuilder();
+        keyBuilder.path("/key/" + serial);
+        keyURL = keyBuilder.build().toString();
+        
+        // clientID = rec.getClientID();
+        // TODO add other fields as needed
+    }
+
+    /**
+     * @return the keyURL
+     */
+    public String getKeyURL() {
+        return keyURL;
+    }
+
+    /**
+     * @param keyURL the keyURL to set
+     */
+    public void setKeyURL(String keyURL) {
+        this.keyURL = keyURL;
+    }
+
+    /**
+     * @return the clientID
+     */
+    public String getClientID() {
+        return clientID;
+    }
+
+    /**
+     * @param clientID the clientID to set
+     */
+    public void setClientID(String clientID) {
+        this.clientID = clientID;
+    }
+
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestDAO.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..60fa8f493b179d39f25bb6dcad653113b823778b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestDAO.java
@@ -0,0 +1,149 @@
+// --- 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.rest.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * @author alee
+ *
+ */
+public class KeyRequestDAO {
+    private IRequestQueue queue;
+    
+    public KeyRequestDAO() {
+        IKeyRecoveryAuthority kra = null;
+        kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
+        queue = kra.getRequestQueue();
+    }
+
+    /**
+     * This will find the requests in the database matching the specified search parameters
+     * Needs input validation and probably paging, maybe using the vlv functions
+     * @throws EBaseException 
+     */
+    public List<KeyRequestInfo> listRequests(String filter, UriInfo uriInfo) throws EBaseException {
+        List <KeyRequestInfo> list = new ArrayList<KeyRequestInfo>();  
+        IRequestList requests = queue.listRequestsByFilter(filter);
+        while (requests.hasMoreElements()) {
+            RequestId rid = (RequestId) requests.nextElement();
+            IRequest request;
+            try {
+                request = queue.findRequest(rid);
+            } catch (EBaseException e) {
+                // log error
+                throw e;
+            }
+            CMS.debug("ade: got request" + rid.toString());
+            list.add(new KeyRequestInfo(request, uriInfo));
+        }
+        return list;
+    }
+    
+    /**
+     * Gets info for a specific request
+     * @param id
+     * @return info for specific request
+     * @throws EBaseException 
+     */
+    public KeyRequestInfo getRequest(String id, UriInfo uriInfo) throws EBaseException {
+        try {
+            IRequest request = queue.findRequest(new RequestId(id));
+            if (request == null) {
+                return null;
+            }
+            KeyRequestInfo info = new KeyRequestInfo(request, uriInfo);
+            return info;
+        } catch (EBaseException e) {
+            // log the error
+            throw e;
+        }
+    }
+    /**
+     * Submits an archival request and processes it.
+     * @param data
+     * @return info for the request submitted.
+     */
+    public KeyRequestInfo submitRequest(ArchivalRequestData data, UriInfo uriInfo) {
+        try {
+            IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST);
+            //TODO : 
+            //set data using request.setExtData(field, data)
+            queue.processRequest(request);
+            return new KeyRequestInfo(request, uriInfo);
+        } catch(EBaseException e) {
+            // do something
+            return null;
+        }
+    }
+    /**
+     * Submits a key recovery request.
+     * @param data
+     * @return info on the recovery request created
+     */
+    public KeyRequestInfo submitRequest(RecoveryRequestData data, UriInfo uriInfo) { 
+        try {
+            IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
+            // set data using request.setExtData(field, data)
+            queue.processRequest(request);
+            return new KeyRequestInfo(request, uriInfo);
+        } catch(EBaseException e) {
+            // do something
+            return null;
+        }
+    }
+
+    public void approveRequest(String id) {
+        try {
+            IRequest request = queue.findRequest(new RequestId(id));
+            request.setRequestStatus(RequestStatus.APPROVED);
+        } catch (EBaseException e) {
+            // do something
+        }
+    }
+    
+    public void rejectRequest(String id) {
+        try {
+            IRequest request = queue.findRequest(new RequestId(id));
+            request.setRequestStatus(RequestStatus.CANCELED);
+        } catch (EBaseException e) {
+            // do something
+        }
+    }
+    
+    public void cancelRequest(String id) {
+        try {
+            IRequest request = queue.findRequest(new RequestId(id));
+            request.setRequestStatus(RequestStatus.REJECTED);
+        } catch (EBaseException e) {
+            // do something
+        }
+    }
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestInfo.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..439edcb12aa51de19b6d081aaf74ef8ea9fab112
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/KeyRequestInfo.java
@@ -0,0 +1,127 @@
+// --- 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.rest.model;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.request.IRequest;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@XmlRootElement(name="SecurityDataRequestInfo")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KeyRequestInfo {
+
+    @XmlElement
+    protected String requestType;
+    
+    @XmlElement
+    protected String requestStatus;
+    
+    @XmlElement
+    protected String requestURL;
+    
+    @XmlElement
+    protected String keyURL;
+    
+    public KeyRequestInfo(){
+        // required to be here for JAXB (defaults)
+    }
+    
+    public KeyRequestInfo(IRequest request, UriInfo uriInfo) {
+        requestType = request.getRequestType();
+        requestStatus = request.getRequestStatus().toString();
+        
+        String rid = request.getRequestId().toString();
+        UriBuilder reqBuilder = uriInfo.getBaseUriBuilder();
+        reqBuilder.path("/keyRequest/" + rid);
+        requestURL = reqBuilder.build().toString();
+        
+        String kid = request.getExtDataInString("key_id");
+        UriBuilder keyBuilder = uriInfo.getBaseUriBuilder();
+        keyBuilder.path("/key/" + kid);
+        keyURL = reqBuilder.build().toString();
+        
+        CMS.debug("alee: requestType is " + requestType);
+        CMS.debug("alee: requestStatus is " + requestStatus);
+        CMS.debug("alee: requestURL is "+ requestURL);
+        CMS.debug("alee: keyURL is " + keyURL);
+    }
+
+    /**
+     * @return the requestType
+     */
+    public String getRequestType() {
+        return requestType;
+    }
+
+    /**
+     * @param requestType the requestType to set
+     */
+    public void setRequestType(String requestType) {
+        this.requestType = requestType;
+    }
+
+    /**
+     * @return the requestStatus
+     */
+    public String getRequestStatus() {
+        return requestStatus;
+    }
+
+    /**
+     * @param requestStatus the requestStatus to set
+     */
+    public void setRequestStatus(String requestStatus) {
+        this.requestStatus = requestStatus;
+    }
+
+    /**
+     * @return the requestURL
+     */
+    public String getRequestURL() {
+        return requestURL;
+    }
+
+    /**
+     * @param requestURL the requestURL to set
+     */
+    public void setRequestURL(String requestURL) {
+        this.requestURL = requestURL;
+    }
+
+    /**
+     * @return the keyURL
+     */
+    public String getKeyURL() {
+        return keyURL;
+    }
+
+    /**
+     * @param keyURL the keyURL to set
+     */
+    public void setKeyURL(String keyURL) {
+        this.keyURL = keyURL;
+    }
+}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/rest/model/RecoveryRequestData.java b/pki/base/common/src/com/netscape/cms/servlet/rest/model/RecoveryRequestData.java
new file mode 100644
index 0000000000000000000000000000000000000000..b85bed761dc1b86bfa3e69c9297a8934979cd58b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/rest/model/RecoveryRequestData.java
@@ -0,0 +1,122 @@
+// --- 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.rest.model;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * @author alee
+ *
+ */
+@XmlRootElement(name="SecurityDataRecoveryRequest")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RecoveryRequestData {
+    
+    private static final String KEY_ID = "keyId";
+    private static final String REQUEST_ID = "requestId";
+    private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
+    private static final String TRANS_WRAPPED_PASSPHRASE = "transWrappedPassphrase";
+
+    @XmlElement
+    protected String keyId;
+    
+    @XmlElement
+    protected String requestId;
+    
+    @XmlElement
+    protected String transWrappedSessionKey;
+    
+    @XmlElement
+    protected String transWrappedPassphrase;
+    
+    public RecoveryRequestData() {
+        // required for JAXB (defaults)
+    }
+    
+    public RecoveryRequestData(MultivaluedMap<String, String> form) {
+        keyId = form.getFirst(KEY_ID);
+        requestId = form.getFirst(REQUEST_ID);
+        transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY);
+        transWrappedPassphrase = form.getFirst(TRANS_WRAPPED_PASSPHRASE);
+    }
+
+    /**
+     * @return the keyId
+     */
+    public String getKeyId() {
+        return keyId;
+    }
+
+    /**
+     * @param keyId the keyId to set
+     */
+    public void setKeyId(String keyId) {
+        this.keyId = keyId;
+    }
+
+    /**
+     * @return the requestId
+     */
+    public String getRequestId() {
+        return requestId;
+    }
+
+    /**
+     * @param requestId the requestId to set
+     */
+    public void setRequestId(String requestId) {
+        this.requestId = requestId;
+    }
+
+    /**
+     * @return the transWrappedSessionKey
+     */
+    public String getTransWrappedSessionKey() {
+        return transWrappedSessionKey;
+    }
+
+    /**
+     * @param transWrappedSessionKey the transWrappedSessionKey to set
+     */
+    public void setTransWrappedSessionKey(String transWrappedSessionKey) {
+        this.transWrappedSessionKey = transWrappedSessionKey;
+    }
+
+    /**
+     * @return the transWrappedPassphrase
+     */
+    public String getTransWrappedPassphrase() {
+        return transWrappedPassphrase;
+    }
+
+    /**
+     * @param transWrappedPassphrase the transWrappedPassphrase to set
+     */
+    public void setTransWrappedPassphrase(String transWrappedPassphrase) {
+        this.transWrappedPassphrase = transWrappedPassphrase;
+    }
+
+}
diff --git a/pki/base/kra/shared/webapps/kra/WEB-INF/web.xml b/pki/base/kra/shared/webapps/kra/WEB-INF/web.xml
index fdc2779b1a583579472388f7d87c52ee0b6bbda0..4e9027acc6dc310cb275c2f4faceb367d8f899e4 100644
--- a/pki/base/kra/shared/webapps/kra/WEB-INF/web.xml
+++ b/pki/base/kra/shared/webapps/kra/WEB-INF/web.xml
@@ -756,6 +756,28 @@
                          <param-value> ee          </param-value> </init-param>
    </servlet>
 
+   <context-param>
+      <param-name>resteasy.scan</param-name>
+      <param-value>true</param-value>
+   </context-param>
+
+   <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
+      </param-value>
+   </context-param>
+
+   <servlet>
+      <servlet-name>Resteasy</servlet-name>
+      <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
+   </servlet>
+
 [PKI_OPEN_SEPARATE_PORTS_WEB_COMMENT]
    <filter-mapping>
       <filter-name>  AgentRequestFilter  </filter-name>
@@ -783,6 +805,11 @@
 [PKI_CLOSE_SEPARATE_PORTS_WEB_COMMENT]
 
    <servlet-mapping>
+      <servlet-name>Resteasy</servlet-name>
+      <url-pattern>/pki/*</url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>
       <servlet-name>  kraserver  </servlet-name>
       <url-pattern>   /server  </url-pattern>
    </servlet-mapping>
diff --git a/pki/specs/pki-core.spec b/pki/specs/pki-core.spec
index 075a10aac2a709b1887899ad3774b28fa9643a6d..c9bb229a0d5af6621ce19b21ac4fe2148f7cb1db 100644
--- a/pki/specs/pki-core.spec
+++ b/pki/specs/pki-core.spec
@@ -1,6 +1,6 @@
 Name:             pki-core
 Version:          9.0.16
-Release:          1%{?dist}
+Release:          2%{?dist}
 Summary:          Certificate System - PKI Core Components
 URL:              http://pki.fedoraproject.org/
 License:          GPLv2
@@ -26,6 +26,7 @@ BuildRequires:    selinux-policy-devel
 BuildRequires:    velocity
 BuildRequires:    xalan-j2
 BuildRequires:    xerces-j2
+BuildRequires:    candlepin-deps
 %if 0%{?fedora} >= 16
 BuildRequires:    jpackage-utils >= 0:1.7.5-10
 BuildRequires:    jss >= 4.2.6-19.1
@@ -274,6 +275,9 @@ Group:            System Environment/Base
 BuildArch:        noarch
 
 Requires:         java >= 1:1.6.0
+Requires:         candlepin-deps
+Requires:         javassist
+Requires:         jettison
 Requires:         pki-common-theme >= 9.0.0
 Requires:         pki-java-tools = %{version}-%{release}
 Requires:         pki-setup = %{version}-%{release}
-- 
1.7.6.4

