>From 74bec2fc37c350f0e46212502e69d7c57d723d4d Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Thu, 3 Oct 2013 12:58:34 -0400
Subject: [PATCH] Add audit logging for new security data operations in kra

Ticket 97
---
 base/common/src/LogMessages.properties             | 51 +++++++++++++-
 .../com/netscape/cms/servlet/key/KeyService.java   | 41 ++++++++++--
 .../cms/servlet/request/KeyRequestService.java     | 56 ++++++++++++++--
 base/kra/shared/conf/CS.cfg.in                     |  4 +-
 .../netscape/kra/SecurityDataRecoveryService.java  | 72 ++++++++++++++++++--
 .../src/com/netscape/kra/SecurityDataService.java  | 78 ++++++++++++++++++++--
 6 files changed, 276 insertions(+), 26 deletions(-)

diff --git a/base/common/src/LogMessages.properties b/base/common/src/LogMessages.properties
index 67ca3695727eab64df1bba5c3a72ef6d7431e5fd..aacd7fc61daa2fda16a365f1857a53c409820961 100644
--- a/base/common/src/LogMessages.properties
+++ b/base/common/src/LogMessages.properties
@@ -2013,6 +2013,7 @@ LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE_3=<type=SERVER
 #
 LOGGING_SIGNED_AUDIT_KEY_RECOVERY_REQUEST_4=<type=KEY_RECOVERY_REQUEST>:[AuditEvent=KEY_RECOVERY_REQUEST][SubjectID={0}][Outcome={1}][RecoveryID={2}][PubKey={3}] key recovery request made
 #
+#
 # LOGGING_SIGNED_AUDIT_KEY_RECOVERY_REQUEST_ASYNC
 # - used when asynchronous key recovery request is made
 # RequestID  must be the recovery request ID
@@ -2030,6 +2031,7 @@ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_REQUEST_ASYNC_4=<type=KEY_RECOVERY_REQUEST_ASY
 #
 LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN_4=<type=KEY_RECOVERY_AGENT_LOGIN>:[AuditEvent=KEY_RECOVERY_AGENT_LOGIN][SubjectID={0}][Outcome={1}][RecoveryID={2}][RecoveryAgent={3}] key recovery agent login
 #
+#
 # LOGGING_SIGNED_AUDIT_KEY_RECOVERY_REQUEST_PROCESSED
 # - used when key recovery request is processed
 # RecoveryID must be the recovery request ID
@@ -2383,7 +2385,54 @@ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1=<type=SECURITY_DOMAIN_UPDATE>:[Aud
 #    separated by + (if more than one name;;value pair) of config params changed
 #
 LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER_1=<type=CONFIG_SERIAL_NUMBER>:[AuditEvent=CONFIG_SERIAL_NUMBER][SubjectID={0}][Outcome={1}][ParamNameValPairs={2}] serial number range update
-
+#
+# LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED
+# - used when user security data archive request is processed
+#    this is when DRM receives and processed the request
+# Client ID must be the user supplied client ID associated with
+#    the security data to be archived
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED_6=<type=SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED>:[AuditEvent=SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED][SubjectID={0}][Outcome={1}][ArchivalRequestID={2}][ClientID={3}][KeyID={4}][FailureReason={5}] security data archival request processed
+#
+# LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST
+# - used when security data recovery request is made
+# RecoveryID must be the recovery request ID
+# CientID is the ID of the security data to be archived
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_4=<type=SECURITY_DATA_ARCHIVAL_REQUEST>:[AuditEvent=SECURITY_DATA_ARCHIVAL_REQUEST][SubjectID={0}][Outcome={1}][ArchivalRequestID={2}][ClientID={3}] security data archival request made
+#
+#
+# LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_PROCESSED
+# - used when security data recovery request is processed
+# RecoveryID must be the recovery request ID
+# KeyID is the ID of the security data being requested to be recovered
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_PROCESSED_5=<type=SECURITY_DATA_RECOVERY_REQUEST_PROCESSED>:[AuditEvent=SECURITY_DATA_RECOVERY_REQUEST_PROCESSED][SubjectID={0}][Outcome={1}][RecoveryID={2}][KeyID={3}][FailureReason={4}] security data recovery request processed
+#
+#
+# LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST
+# - used when security data recovery request is made
+# RecoveryID must be the recovery request ID
+# DataID is the ID of the security data to be recovered
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_4=<type=SECURITY_DATA_RECOVERY_REQUEST>:[AuditEvent=SECURITY_DATA_RECOVERY_REQUEST][SubjectID={0}][Outcome={1}][RecoveryID={2}][DataID={3}] security data recovery request made
+#
+# LOGGING_SIGNED_AUDIT_KEY_RECOVERY_REQUEST_STATE_CHANGE
+# - used when DRM agents login as recovery agents to change
+#   the state of key recovery requests
+# RecoveryID must be the recovery request ID
+# Operation is the operation performed (approve, reject, cancel etc.)
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE_4=<type=SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE>:[AuditEvent=SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE][SubjectID={0}][Outcome={1}][RecoveryID={2}][Operation={3}] security data recovery request state change
+#
+# LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY
+# - used when user attempts to retrieve key after the recovery request 
+#   has been approved.
+# 
+# RecoveryID must be the recovery request ID
+# Operation is the operation performed (approve, reject, cancel etc.)
+#
+LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY_5=<type=SECURITY_DATA_RETRIEVE_KEY>:[AuditEvent=SECURITY_DATA_RETRIEVE_KEY][SubjectID={0}][Outcome={1}][RecoveryID={2}][KeyID={3}][FailureReason={4}] security data retrieval request
 
 ###########################
 #Unselectable signedAudit Events
diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyService.java b/base/common/src/com/netscape/cms/servlet/key/KeyService.java
index 2aba7ab4045efed376b54c5d9388d0b19e6698d5..09e0abf5d8ed58bde2f1c644673945f00f3f7e40 100644
--- a/base/common/src/com/netscape/cms/servlet/key/KeyService.java
+++ b/base/common/src/com/netscape/cms/servlet/key/KeyService.java
@@ -48,6 +48,7 @@ import com.netscape.certsrv.key.KeyRecoveryRequest;
 import com.netscape.certsrv.key.KeyRequestInfo;
 import com.netscape.certsrv.key.KeyResource;
 import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestQueue;
 import com.netscape.certsrv.request.RequestId;
@@ -73,13 +74,16 @@ public class KeyService extends PKIService implements KeyResource {
     @Context
     private HttpServletRequest servletRequest;
 
-    public static final int DEFAULT_MAXRESULTS = 100;
-    public static final int DEFAULT_MAXTIME = 10;
-
     private IKeyRepository repo;
     private IKeyRecoveryAuthority kra;
     private IRequestQueue queue;
 
+    private final static String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY_5";
+
+    public static final int DEFAULT_MAXRESULTS = 100;
+    public static final int DEFAULT_MAXTIME = 10;
+
     public KeyService() {
         kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
         repo = kra.getKeyRepository();
@@ -94,17 +98,21 @@ public class KeyService extends PKIService implements KeyResource {
     public KeyData retrieveKey(KeyRecoveryRequest data) {
         // auth and authz
         KeyId keyId = validateRequest(data);
+        RequestId requestID = data.getRequestId();
         KeyData keyData;
         try {
             keyData = getKey(keyId, data);
         } catch (EBaseException e) {
             e.printStackTrace();
+            auditRetrieveKey(ILogger.FAILURE, requestID, keyId, e.getMessage());
             throw new PKIException(e.getMessage());
         }
         if (keyData == null) {
             // no key record
+            auditRetrieveKey(ILogger.FAILURE, requestID, keyId, "No key record");
             throw new HTTPGoneException("No key record.");
         }
+        auditRetrieveKey(ILogger.SUCCESS, requestID, keyId, "None");
         return keyData;
     }
 
@@ -138,6 +146,7 @@ public class KeyService extends PKIService implements KeyResource {
                 request.getRequestId());
 
         if(requestParams == null) {
+            auditRetrieveKey(ILogger.FAILURE, rId, keyId, "cannot obtain volatile requestParams");
             throw new EBaseException("Can't obtain Volatile requestParams in getKey!");
         }
 
@@ -160,9 +169,10 @@ public class KeyService extends PKIService implements KeyResource {
             nonceData = data.getNonceData();
 
             if (transWrappedSessionKey == null) {
-                 //There must be at least a transWrappedSessionKey input provided.
-                 //The command AND the request have provided insufficient data, end of the line.
-                 throw new EBaseException("Can't retrieve key, insufficient input data!");
+                //There must be at least a transWrappedSessionKey input provided.
+                //The command AND the request have provided insufficient data, end of the line.
+                auditRetrieveKey(ILogger.FAILURE, rId, keyId, "injsufficient input data");
+                throw new EBaseException("Can't retrieve key, insufficient input data!");
             }
 
             if (sessionWrappedPassphrase != null) {
@@ -217,6 +227,7 @@ public class KeyService extends PKIService implements KeyResource {
         // confirm request exists
         RequestId reqId = data.getRequestId();
         if (reqId == null) {
+            auditRetrieveKey(ILogger.FAILURE, null, null, "Request id not found");
             // log error
             throw new BadRequestException("Request id not found.");
         }
@@ -224,6 +235,7 @@ public class KeyService extends PKIService implements KeyResource {
         // confirm that at least one wrapping method exists
         // There must be at least the wrapped session key method.
         if ((data.getTransWrappedSessionKey() == null)) {
+            auditRetrieveKey(ILogger.FAILURE, reqId, null, "No wrapping method found");
             // log error
             throw new BadRequestException("No wrapping method found.");
         }
@@ -233,11 +245,13 @@ public class KeyService extends PKIService implements KeyResource {
         try {
             reqInfo = reqDAO.getRequest(reqId, uriInfo);
         } catch (EBaseException e1) {
+            auditRetrieveKey(ILogger.FAILURE, reqId, null, "failed to get request");
             // failed to get request
             e1.printStackTrace();
             throw new PKIException(e1.getMessage());
         }
         if (reqInfo == null) {
+            auditRetrieveKey(ILogger.FAILURE, reqId, null, "no request info available");
             // request not found
             throw new HTTPGoneException("No request information available.");
         }
@@ -245,6 +259,7 @@ public class KeyService extends PKIService implements KeyResource {
         //confirm request is of the right type
         String type = reqInfo.getRequestType();
         if (!type.equals(IRequest.SECURITY_DATA_RECOVERY_REQUEST)) {
+            auditRetrieveKey(ILogger.FAILURE, reqId, null, "invalid request type");
             // log error
             throw new BadRequestException("Invalid request type");
         }
@@ -255,8 +270,9 @@ public class KeyService extends PKIService implements KeyResource {
         // confirm request is in approved state
         RequestStatus status = reqInfo.getRequestStatus();
         if (!status.equals(RequestStatus.APPROVED)) {
+            auditRetrieveKey(ILogger.FAILURE, reqId, null, "recovery request not approved");
             // log error
-            throw new UnauthorizedException("Unauthorized request.");
+            throw new UnauthorizedException("Unauthorized request.  Recovery request not approved.");
         }
 
         return reqInfo.getKeyId();
@@ -342,4 +358,15 @@ public class KeyService extends PKIService implements KeyResource {
 
         return filter;
     }
+
+    public void auditRetrieveKey(String status, RequestId requestID, KeyId keyID, String reason) {
+        String msg = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY,
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                requestID != null ? requestID.toString(): "null",
+                keyID != null ? keyID.toString(): "null",
+                reason);
+        auditor.log(msg);
+    }
 }
diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestService.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestService.java
index fce3e879eacc74961ada6d9631fab5f13353f66a..8db16b51f73cd159757afb842403bbf139880acf 100644
--- a/base/common/src/com/netscape/cms/servlet/request/KeyRequestService.java
+++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestService.java
@@ -29,11 +29,13 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.dbs.keydb.KeyId;
 import com.netscape.certsrv.key.KeyArchivalRequest;
 import com.netscape.certsrv.key.KeyRecoveryRequest;
 import com.netscape.certsrv.key.KeyRequestInfo;
 import com.netscape.certsrv.key.KeyRequestInfos;
 import com.netscape.certsrv.key.KeyRequestResource;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.request.RequestNotFoundException;
 import com.netscape.cms.servlet.base.PKIService;
@@ -58,6 +60,15 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
     @Context
     private HttpServletRequest servletRequest;
 
+    private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_4";
+
+    private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_4";
+
+    private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE_4";
+
     public static final int DEFAULT_START = 0;
     public static final int DEFAULT_PAGESIZE = 20;
     public static final int DEFAULT_MAXRESULTS = 100;
@@ -104,9 +115,10 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
         KeyRequestInfo info;
         try {
             info = dao.submitRequest(data, uriInfo);
+            auditArchivalRequestMade(info.getRequestId(), ILogger.SUCCESS, data.getClientId());
         } catch (EBaseException e) {
-            // TODO Auto-generated catch block
             e.printStackTrace();
+            auditArchivalRequestMade(null, ILogger.FAILURE, data.getClientId());
             throw new PKIException(e.toString());
         }
         return info;
@@ -137,9 +149,10 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
         KeyRequestInfo info;
         try {
             info = dao.submitRequest(data, uriInfo);
+            auditRecoveryRequestMade(info.getRequestId(), ILogger.SUCCESS, data.getKeyId());
         } catch (EBaseException e) {
-            // TODO Auto-generated catch block
             e.printStackTrace();
+            auditRecoveryRequestMade(null, ILogger.FAILURE, data.getKeyId());
             throw new PKIException(e.toString());
         }
         return info;
@@ -153,9 +166,10 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
         KeyRequestDAO dao = new KeyRequestDAO();
         try {
             dao.approveRequest(id);
+            auditRecoveryRequestChange(id, ILogger.SUCCESS, "approve");
         } catch (EBaseException e) {
-            // TODO Auto-generated catch block
             e.printStackTrace();
+            auditRecoveryRequestChange(id, ILogger.FAILURE, "approve");
             throw new PKIException(e.toString());
         }
     }
@@ -168,9 +182,10 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
         KeyRequestDAO dao = new KeyRequestDAO();
         try {
             dao.rejectRequest(id);
+            auditRecoveryRequestChange(id, ILogger.SUCCESS, "reject");
         } catch (EBaseException e) {
-            // TODO Auto-generated catch block
             e.printStackTrace();
+            auditRecoveryRequestChange(id, ILogger.FAILURE, "reject");
             throw new PKIException(e.toString());
         }
     }
@@ -183,9 +198,10 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
         KeyRequestDAO dao = new KeyRequestDAO();
         try {
             dao.cancelRequest(id);
+            auditRecoveryRequestChange(id, ILogger.SUCCESS, "cancel");
         } catch (EBaseException e) {
-            // TODO Auto-generated catch block
             e.printStackTrace();
+            auditRecoveryRequestChange(id, ILogger.FAILURE, "cancel");
             throw new PKIException(e.toString());
         }
     }
@@ -248,4 +264,34 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
 
         return filter;
     }
+
+    public void auditRecoveryRequestChange(RequestId requestId, String status, String operation) {
+        String msg = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE,
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                requestId.toString(),
+                operation);
+        auditor.log(msg);
+    }
+
+    public void auditRecoveryRequestMade(RequestId requestId, String status, KeyId dataId) {
+        String msg = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST,
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                requestId != null? requestId.toString(): "null",
+                dataId.toString());
+        auditor.log(msg);
+    }
+
+    public void auditArchivalRequestMade(RequestId requestId, String status, String clientId) {
+        String msg = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST,
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                requestId != null? requestId.toString(): "null",
+                clientId);
+        auditor.log(msg);
+    }
 }
diff --git a/base/kra/shared/conf/CS.cfg.in b/base/kra/shared/conf/CS.cfg.in
index a201b07d154d4136fb011ad79ae5ff322d0afdb1..9045eb904db214a56e428d1d5ed6e656cd6630da 100644
--- a/base/kra/shared/conf/CS.cfg.in
+++ b/base/kra/shared/conf/CS.cfg.in
@@ -272,11 +272,11 @@ log.instance.SignedAudit._001=## Signed Audit Logging
 log.instance.SignedAudit._002=##
 log.instance.SignedAudit._003=##
 log.instance.SignedAudit._004=## Available Audit events:
-log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,CONFIG_SERIAL_NUMBER
+log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,CONFIG_SERIAL_NUMBER,SECURITY_DATA_ARCHIVAL_REQUEST,SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED,SECURITY_DATA_RECOVERY_REQUEST,SECURITY_DATA_RECOVERY_REQUEST_PROCESSED,SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE,SECURITY_DATA_RETRIEVE_KEY
 log.instance.SignedAudit._006=##
 log.instance.SignedAudit.bufferSize=512
 log.instance.SignedAudit.enable=true
-log.instance.SignedAudit.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,CONFIG_SERIAL_NUMBER
+log.instance.SignedAudit.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,CONFIG_SERIAL_NUMBER,SECURITY_DATA_ARCHIVAL_REQUEST,SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED,SECURITY_DATA_RECOVERY_REQUEST,SECURITY_DATA_RECOVERY_REQUEST_PROCESSED,SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE,SECURITY_DATA_RETRIEVE_KEY
 log.instance.SignedAudit.expirationTime=0
 log.instance.SignedAudit.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/signedAudit/kra_cert-kra_audit
 log.instance.SignedAudit.flushInterval=5
diff --git a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
index afe4ed6eadfa844c379005bb6ef8abee81c6b9df..0ec4ed335663112904bf5a573c1b5743c44ef2f3 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
@@ -52,13 +52,16 @@ import org.mozilla.jss.util.Password;
 
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
 import com.netscape.certsrv.dbs.keydb.IKeyRecord;
 import com.netscape.certsrv.dbs.keydb.IKeyRepository;
 import com.netscape.certsrv.key.KeyRequestResource;
 import com.netscape.certsrv.kra.EKRAException;
 import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.security.IStorageKeyUnit;
 import com.netscape.certsrv.security.ITransportKeyUnit;
 import com.netscape.cmscore.dbs.KeyRecord;
@@ -78,7 +81,10 @@ public class SecurityDataRecoveryService implements IService {
     private IKeyRepository mStorage = null;
     private IStorageKeyUnit mStorageUnit = null;
     private ITransportKeyUnit mTransportUnit = null;
+    private ILogger signedAuditLogger = CMS.getSignedAuditLogger();
 
+    private final static String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_PROCESSED =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_PROCESSED_5";
     public static final String ATTR_SERIALNO = "serialNumber";
     public static final String ATTR_KEY_RECORD = "keyRecord";
 
@@ -112,18 +118,22 @@ public class SecurityDataRecoveryService implements IService {
         byte iv_default[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
         byte iv_in[] = null;
 
+        String subjectID = auditSubjectID();
+
         Hashtable<String, Object> params = mKRA.getVolatileRequest(
                 request.getRequestId());
 
+        BigInteger serialno = request.getExtDataInBigInteger(ATTR_SERIALNO);
+        request.setExtData(ATTR_KEY_RECORD, serialno);
+        RequestId requestID = request.getRequestId();
+
         if (params == null) {
             CMS.debug("Can't get volatile params.");
+            auditRecoveryRequestProcessed(subjectID, ILogger.FAILURE, requestID, serialno.toString(),
+                    "cannot get volatile params");
             throw new EBaseException("Can't obtain volatile params!");
         }
 
-        BigInteger serialno = request.getExtDataInBigInteger(ATTR_SERIALNO);
-
-        request.setExtData(ATTR_KEY_RECORD, serialno);
-
         byte[] wrappedPassPhrase = null;
         byte[] wrappedSessKey = null;
 
@@ -202,6 +212,8 @@ public class SecurityDataRecoveryService implements IService {
                 params.put(IRequest.SECURITY_DATA_PASS_WRAPPED_DATA, pbeWrappedData);
 
             } catch (Exception e) {
+                auditRecoveryRequestProcessed(subjectID, ILogger.FAILURE, requestID, serialno.toString(),
+                        "Cannot unwrap passphrase");
                 throw new EBaseException("Can't unwrap pass phase! " + e.toString());
             } finally {
                 if ( pass != null) {
@@ -222,6 +234,8 @@ public class SecurityDataRecoveryService implements IService {
                     wrapper.initWrap(unwrappedSess, new IVParameterSpec(iv));
                     key_data = wrapper.wrap(symKey);
                 } catch (Exception e) {
+                    auditRecoveryRequestProcessed(subjectID, ILogger.FAILURE, requestID, serialno.toString(),
+                            "Cannot wrap symmetric key");
                     throw new EBaseException("Can't wrap symmetric key! " + e.toString());
                 }
 
@@ -233,10 +247,14 @@ public class SecurityDataRecoveryService implements IService {
                         encryptor.initEncrypt(unwrappedSess, new IVParameterSpec(iv));
                         key_data = encryptor.doFinal(unwrappedSecData);
                     } else {
+                        auditRecoveryRequestProcessed(subjectID, ILogger.FAILURE, requestID,
+                                serialno.toString(), "Failed to create cipher");
                         throw new IOException("Failed to create cipher");
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
+                    auditRecoveryRequestProcessed(subjectID, ILogger.FAILURE, requestID,
+                            serialno.toString(), "Cannot wrap pass phrase");
                     throw new EBaseException("Can't wrap pass phrase!");
                 }
             }
@@ -246,7 +264,8 @@ public class SecurityDataRecoveryService implements IService {
             params.put(IRequest.SECURITY_DATA_IV_STRING_OUT, ivStr);
 
         }
-        return false;
+        auditRecoveryRequestProcessed(subjectID, ILogger.SUCCESS, requestID, serialno.toString(), "None");
+        return false; //return true ? TODO
     }
 
     public SymmetricKey recoverSymKey(KeyRecord keyRecord)
@@ -385,4 +404,47 @@ public class SecurityDataRecoveryService implements IService {
         return retData;
     }
 
+    private void audit(String msg) {
+        if (signedAuditLogger == null)
+            return;
+
+        signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+                null,
+                ILogger.S_SIGNED_AUDIT,
+                ILogger.LL_SECURITY,
+                msg);
+    }
+
+    private String auditSubjectID() {
+        if (signedAuditLogger == null) {
+            return null;
+        }
+
+        String subjectID = null;
+
+        // Initialize subjectID
+        SessionContext auditContext = SessionContext.getExistingContext();
+
+        if (auditContext != null) {
+            subjectID = (String) auditContext.get(SessionContext.USER_ID);
+            subjectID = (subjectID != null) ? subjectID.trim() : ILogger.NONROLEUSER;
+        } else {
+            subjectID = ILogger.UNIDENTIFIED;
+        }
+
+        return subjectID;
+    }
+
+    private void auditRecoveryRequestProcessed(String subjectID, String status, RequestId requestID,
+            String keyID, String reason) {
+        String auditMessage = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_PROCESSED,
+                subjectID,
+                status,
+                requestID.toString(),
+                keyID,
+                reason);
+        audit(auditMessage);
+    }
+
 }
diff --git a/base/kra/src/com/netscape/kra/SecurityDataService.java b/base/kra/src/com/netscape/kra/SecurityDataService.java
index 8a5886fa5e910313c7211be1e05fde1fc9f8ab78..9fc737529e87c9bf83bdbdca522b758bae109f81 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataService.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataService.java
@@ -18,20 +18,23 @@
 package com.netscape.kra;
 
 import java.math.BigInteger;
+
 import org.mozilla.jss.crypto.SymmetricKey;
 
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
 import com.netscape.certsrv.key.KeyRequestResource;
 import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.profile.IEnrollProfile;
-import com.netscape.certsrv.request.IService;
 import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.security.IStorageKeyUnit;
 import com.netscape.certsrv.security.ITransportKeyUnit;
-import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.dbs.keydb.IKeyRecord;
-import com.netscape.certsrv.dbs.keydb.IKeyRepository;
-import com.netscape.certsrv.apps.CMS;
 import com.netscape.cmscore.dbs.KeyRecord;
 import com.netscape.cmsutil.util.Utils;
 
@@ -50,6 +53,11 @@ public class SecurityDataService implements IService {
     private IKeyRecoveryAuthority mKRA = null;
     private ITransportKeyUnit mTransportUnit = null;
     private IStorageKeyUnit mStorageUnit = null;
+    private ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+
+    private final static String LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED_6";
+
 
     public SecurityDataService(IKeyRecoveryAuthority kra) {
         mKRA = kra;
@@ -82,9 +90,12 @@ public class SecurityDataService implements IService {
         CMS.debug("SecurityDataService.serviceRequest wrappedSecurityData: " + wrappedSecurityData);
 
         String owner = getOwnerName(request);
+        String subjectID = auditSubjectID();
 
         //Check here even though restful layer checks for this.
         if(wrappedSecurityData == null || clientId == null || dataType == null) {
+            auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(),
+                    clientId, null, "Bad data in request");
             throw new EBaseException("Bad data in SecurityDataService.serviceRequest");
         }
         //We need some info from the PKIArchiveOptions wrapped security data
@@ -95,7 +106,9 @@ public class SecurityDataService implements IService {
 
         //Check here just in case a null ArchiveOptions makes it this far
         if(options == null) {
-            throw new EBaseException("Problem decofing PKIArchiveOptions.");
+            auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(),
+                    clientId, null, "Problem decoding PKIArchiveOptions");
+            throw new EBaseException("Problem decoding PKIArchiveOptions.");
         }
 
         String algStr = options.getSymmAlgOID();
@@ -129,6 +142,8 @@ public class SecurityDataService implements IService {
         } else if (securityData != null) {
             privateSecurityData = mStorageUnit.encryptInternalPrivate(securityData);
         } else { // We have no data.
+            auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(),
+                    clientId, null, "Failed to create security data to archive");
             throw new EBaseException("Failed to create security data to archive!");
         }
         // create key record
@@ -141,6 +156,8 @@ public class SecurityDataService implements IService {
         //Now we need a serial number for our new key.
 
         if (rec.getSerialNumber() != null) {
+            auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(),
+                    clientId, null, CMS.getUserMessage("CMS_KRA_INVALID_STATE"));
             throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"));
         }
 
@@ -150,6 +167,8 @@ public class SecurityDataService implements IService {
         if (serialNo == null) {
             mKRA.log(ILogger.LL_FAILURE,
                     CMS.getLogMessage("CMSCORE_KRA_GET_NEXT_SERIAL"));
+            auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(),
+                    clientId, null, "Failed to get  next Key ID");
             throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"));
         }
 
@@ -162,6 +181,9 @@ public class SecurityDataService implements IService {
 
         storage.addKeyRecord(rec);
 
+        auditArchivalRequestProcessed(subjectID, ILogger.SUCCESS, request.getRequestId(),
+                clientId, serialNo.toString(), "None");
+
         return true;
 
     }
@@ -169,4 +191,48 @@ public class SecurityDataService implements IService {
     private String getOwnerName(IRequest request) {
         return DEFAULT_OWNER;
     }
+
+    private void audit(String msg) {
+        if (signedAuditLogger == null)
+            return;
+
+        signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+                null,
+                ILogger.S_SIGNED_AUDIT,
+                ILogger.LL_SECURITY,
+                msg);
+    }
+
+    private String auditSubjectID() {
+        if (signedAuditLogger == null) {
+            return null;
+        }
+
+        String subjectID = null;
+
+        // Initialize subjectID
+        SessionContext auditContext = SessionContext.getExistingContext();
+
+        if (auditContext != null) {
+            subjectID = (String) auditContext.get(SessionContext.USER_ID);
+            subjectID = (subjectID != null) ? subjectID.trim() : ILogger.NONROLEUSER;
+        } else {
+            subjectID = ILogger.UNIDENTIFIED;
+        }
+
+        return subjectID;
+    }
+
+    private void auditArchivalRequestProcessed(String subjectID, String status, RequestId requestID, String clientID,
+            String keyID, String reason) {
+        String auditMessage = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED,
+                subjectID,
+                status,
+                requestID.toString(),
+                clientID,
+                keyID != null ? keyID : "None",
+                reason);
+        audit(auditMessage);
+    }
 }
\ No newline at end of file
-- 
1.8.3.1

