From b739dd8935499e833655be5d05a8002df07cc8e9 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Thu, 24 Mar 2016 16:23:05 -0700
Subject: [PATCH] Ticket #1006 Audit logging for TPS REST operations

---
 .../src/com/netscape/certsrv/logging/IAuditor.java |   3 +-
 .../com/netscape/cms/servlet/base/PKIService.java  |  15 ++
 .../org/dogtagpki/server/rest/AuditService.java    | 117 ++++++--
 base/server/cmsbundle/src/LogMessages.properties   |  55 +++-
 .../src/com/netscape/cmscore/logging/Auditor.java  |  19 +-
 base/tps/shared/conf/CS.cfg.in                     |   4 +-
 .../dogtagpki/server/tps/config/ConfigService.java |  30 ++-
 .../server/tps/rest/AuthenticatorService.java      | 187 ++++++++++---
 .../server/tps/rest/ConnectorService.java          | 180 ++++++++++---
 .../server/tps/rest/ProfileMappingService.java     | 157 +++++++++--
 .../dogtagpki/server/tps/rest/ProfileService.java  | 171 ++++++++++--
 .../dogtagpki/server/tps/rest/TokenService.java    | 297 +++++++++++++++++----
 12 files changed, 1028 insertions(+), 207 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/logging/IAuditor.java b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
index a9362259633e29d33f5ae8fc3efc86628c9ebe35..89c03b838ca2e546224bfd2b3785c6684b59aeed 100644
--- a/base/common/src/com/netscape/certsrv/logging/IAuditor.java
+++ b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
@@ -70,9 +70,10 @@ public interface IAuditor {
      * @return a delimited string of one or more delimited name/value pairs
      */
     public String getParamString(String scope, String type, String id, Map<String, String> params);
+    public String getParamString(StringBuilder paramsters, Map<String, String> params);
 
     /**
      * Log audit message.
      */
     public void log(String message);
-}
\ No newline at end of file
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
index d2e55b5a3c42ee89f5784da12de860fd4e8880bf..7ed9c0dc86b08add5066a9c6df29ce791775e54e 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
@@ -259,6 +259,21 @@ public class PKIService {
         auditor.log(auditMessage);
     }
 
+    public void auditConfigTokenGeneral(String status, String service, Map<String, String> params, String info) {
+        CMS.debug("PKIService.auditConfigTokenGeneral begins");
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_GENERAL_5",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+        CMS.debug("PKIService.auditConfigTokenGeneral ends");
+    }
+
     /**
      * Get the values of the fields annotated with @FormParam.
      */
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java b/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
index e32c36c3313e8bbb3ea729245dcd51d5f2fda7a7..273625e81776ab8a8cd024f503f5e45ade94612a 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
@@ -21,6 +21,7 @@ package org.dogtagpki.server.rest;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeSet;
@@ -42,6 +43,7 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.logging.AuditConfig;
 import com.netscape.certsrv.logging.AuditResource;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.cms.servlet.base.PKIService;
 
 /**
@@ -66,29 +68,62 @@ public class AuditService extends PKIService implements AuditResource {
     }
 
     public AuditConfig createAuditConfig() throws UnsupportedEncodingException, EBaseException {
+        return createAuditConfig(null);
+    }
+
+    public AuditConfig createAuditConfig(Map<String, String> auditParams)
+            throws UnsupportedEncodingException, EBaseException {
 
         IConfigStore cs = CMS.getConfigStore();
 
         AuditConfig auditConfig = new AuditConfig();
-        auditConfig.setStatus(cs.getBoolean("log.instance.SignedAudit.enable", false) ? "Enabled" : "Disabled");
-        auditConfig.setSigned(cs.getBoolean("log.instance.SignedAudit.logSigning", false));
-        auditConfig.setInterval(cs.getInteger("log.instance.SignedAudit.flushInterval", 5));
-        auditConfig.setBufferSize(cs.getInteger("log.instance.SignedAudit.bufferSize", 512));
+        String val = null;
+        Boolean boolval = false;
+        Integer integerval;
+
+        val = cs.getBoolean("log.instance.SignedAudit.enable", false) ? "Enabled" : "Disabled";
+        auditConfig.setStatus(val);
+        if (auditParams != null)
+            auditParams.put("enable", val);
+
+        boolval = cs.getBoolean("log.instance.SignedAudit.logSigning", false);
+        if (auditParams != null)
+            auditParams.put("logSigning", boolval ? "true" : "false");
+        auditConfig.setSigned(boolval);
+
+        integerval = cs.getInteger("log.instance.SignedAudit.flushInterval", 5);
+        auditConfig.setInterval(integerval);
+        if (auditParams != null)
+            auditParams.put("flushInterval", integerval.toString());
+
+        integerval = cs.getInteger("log.instance.SignedAudit.bufferSize", 512);
+        auditConfig.setBufferSize(integerval);
+        if (auditParams != null)
+            auditParams.put("bufferSize", integerval.toString());
 
         Map<String, String> eventConfigs = new TreeMap<String, String>();
 
         // unselected optional events
-        for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.unselected.events", ""), ", ")) {
+        val = cs.getString("log.instance.SignedAudit.unselected.events", "");
+        if (auditParams != null)
+            auditParams.put("unselected.events", val);
+        for (String event : StringUtils.split(val, ", ")) {
             eventConfigs.put(event.trim(), "disabled");
         }
 
         // selected optional events
-        for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.events", ""), ", ")) {
+        val = cs.getString("log.instance.SignedAudit.events", "");
+        if (auditParams != null)
+            auditParams.put("events", val);
+        for (String event : StringUtils.split(val, ", ")) {
             eventConfigs.put(event.trim(), "enabled");
         }
 
         // always selected mandatory events
-        for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.mandatory.events", ""), ", ")) {
+        val = cs.getString("log.instance.SignedAudit.mandatory.events", "");
+        if (auditParams != null)
+            auditParams.put("mandatory.events", val);
+        for (String event : StringUtils.split(val, ", ")) {
             eventConfigs.put(event.trim(), "mandatory");
         }
 
@@ -119,8 +154,14 @@ public class AuditService extends PKIService implements AuditResource {
 
     @Override
     public Response updateAuditConfig(AuditConfig auditConfig) {
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (auditConfig == null) throw new BadRequestException("Audit config is null.");
+        if (auditConfig == null) {
+            BadRequestException e = new BadRequestException("Audit config is null.");
+            auditModParams.put("Info", e.toString());
+            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+            throw e;
+        }
 
         CMS.debug("AuditService.updateAuditConfig()");
 
@@ -157,20 +198,29 @@ public class AuditService extends PKIService implements AuditResource {
 
                     // make sure no event is added
                     if (currentValue == null) {
-                        throw new PKIException("Unable to add event: " + name);
+                        PKIException e = new PKIException("Unable to add event: " + name);
+                        auditModParams.put("Info", e.toString());
+                        auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                        throw e;
                     }
 
                     // make sure no optional event becomes mandatory
                     if ("mandatory".equals(value)) {
                         if (!"mandatory".equals(currentValue)) {
-                            throw new PKIException("Unable to add mandatory event: " + name);
+                            PKIException e = new PKIException("Unable to add mandatory event: " + name);
+                            auditModParams.put("Info", e.toString());
+                            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                            throw e;
                         }
                         continue;
                     }
 
                     // make sure no mandatory event becomes optional
                     if ("mandatory".equals(currentValue)) {
-                        throw new PKIException("Unable to remove mandatory event: " + name);
+                        PKIException e = new PKIException("Unable to remove mandatory event: " + name);
+                        auditModParams.put("Info", e.toString());
+                        auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                        throw e;
                     }
 
                     if ("enabled".equals(value)) {
@@ -180,7 +230,10 @@ public class AuditService extends PKIService implements AuditResource {
                         unselected.add(name);
 
                     } else {
-                        throw new PKIException("Invalid event configuration: " + name + "=" + value);
+                        PKIException e = new PKIException("Invalid event configuration: " + name + "=" + value);
+                        auditModParams.put("Info", e.toString());
+                        auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                        throw e;
                     }
                 }
 
@@ -191,20 +244,28 @@ public class AuditService extends PKIService implements AuditResource {
             for (String name : currentEventConfigs.keySet()) {
                 // make sure no event is removed
                 if (!eventConfigs.containsKey(name)) {
-                    throw new PKIException("Unable to remove event: " + name);
+                    PKIException e = new PKIException("Unable to remove event: " + name);
+                    auditModParams.put("Info", e.toString());
+                    auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                    throw e;
                 }
             }
 
             cs.commit(true);
 
-            auditConfig = createAuditConfig();
+            auditConfig = createAuditConfig(auditModParams);
+            auditTPSConfigSignedAudit(ILogger.SUCCESS, auditModParams);
 
             return createOKResponse(auditConfig);
 
         } catch (PKIException e) {
+            auditModParams.put("Info", e.toString());
+            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
             throw e;
 
         } catch (Exception e) {
+            auditModParams.put("Info", e.toString());
+            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
             e.printStackTrace();
             throw new PKIException(e.getMessage());
         }
@@ -212,10 +273,12 @@ public class AuditService extends PKIService implements AuditResource {
 
     @Override
     public Response changeAuditStatus(String action) {
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
         CMS.debug("AuditService.changeAuditStatus()");
 
         try {
+            auditModParams.put("Action", action);
             IConfigStore cs = CMS.getConfigStore();
 
             if ("enable".equals(action)) {
@@ -225,21 +288,45 @@ public class AuditService extends PKIService implements AuditResource {
                 cs.putBoolean("log.instance.SignedAudit.enable", false);
 
             } else {
-                throw new BadRequestException("Invalid action " + action);
+                BadRequestException e = new BadRequestException("Invalid action " + action);
+                auditModParams.put("Info", e.toString());
+                auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+                throw e;
             }
 
             cs.commit(true);
 
             AuditConfig auditConfig = createAuditConfig();
+            auditTPSConfigSignedAudit(ILogger.SUCCESS, auditModParams);
 
             return createOKResponse(auditConfig);
 
         } catch (PKIException e) {
+            auditModParams.put("Info", e.toString());
+            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+            e.printStackTrace();
             throw e;
 
         } catch (Exception e) {
+            auditModParams.put("Info", e.toString());
+            auditTPSConfigSignedAudit(ILogger.FAILURE, auditModParams);
+            e.printStackTrace();
             e.printStackTrace();
             throw new PKIException(e.getMessage());
         }
     }
+
+    /*
+     * in case of failure, "info" should be in the params
+     */
+    public void auditTPSConfigSignedAudit(String status, Map<String, String> params) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT_3",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                auditor.getParamString(null, params));
+        auditor.log(msg);
+
+    }
 }
diff --git a/base/server/cmsbundle/src/LogMessages.properties b/base/server/cmsbundle/src/LogMessages.properties
index 5f9432e28d1ac620d8ef29e13ceb701225a61ff4..433797cbeab280938e76b7b40b7656cd29c24e72 100644
--- a/base/server/cmsbundle/src/LogMessages.properties
+++ b/base/server/cmsbundle/src/LogMessages.properties
@@ -2638,22 +2638,71 @@ LOGGING_SIGNED_AUDIT_TOKEN_AUTH_SUCCESS_9=<type=TOKEN_AUTH_SUCCESS>:[AuditEvent=
 #    (where name and value are separated by the delimiter ;;)
 #    separated by + (if more than one name;;value pair) of config params changed
 #   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
 #
-LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_GENERAL_3=<type=CONFIG_TOKEN_GENERAL>:[AuditEvent=CONFIG_TOKEN_GENERAL][SubjectID={0}][Outcome={1}][ParamNameValPairs={2}] TPS token configuration parameter(s) change
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_GENERAL_5=<type=CONFIG_TOKEN_GENERAL>:[AuditEvent=CONFIG_TOKEN_GENERAL][SubjectID={0}][Outcome={1}][Service={2}][ParamNameValPairs={3}][Info={4}] TPS token configuration parameter(s) change
 #
 # LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_PROFILE
 # - used when configuring token profile
+# Service can be any of the methods offered
 # ParamNameValPairs must be a name;;value pair
 #    (where name and value are separated by the delimiter ;;)
 #    separated by + (if more than one name;;value pair) of config params changed
 #   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
 #
-LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_PROFILE_3=<type=CONFIG_TOKEN_PROFILE>:[AuditEvent=CONFIG_TOKEN_PROFILE][SubjectID={0}][Outcome={1}][ParamNameValPairs={2}] token profile configuration parameter(s) change
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_PROFILE_6=<type=CONFIG_TOKEN_PROFILE>:[AuditEvent=CONFIG_TOKEN_PROFILE][SubjectID={0}][Outcome={1}][Service={2}][ProfileID={3}][ParamNameValPairs={4}][Info={5}] token profile configuration parameter(s) change
+#
+# LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_MAPPING_RESOLVER
+# ParamNameValPairs must be a name;;value pair
+#    (where name and value are separated by the delimiter ;;)
+#    separated by + (if more than one name;;value pair) of config params changed
+#   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
+#
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_MAPPING_RESOLVER_6=<type=CONFIG_TOKEN_MAPPING_RESOLVER>:[AuditEvent=CONFIG_TOKEN_MAPPING_RESOLVER][SubjectID={0}][Outcome={1}][Service={2}][MappingResolverID={3}][ParamNameValPairs={4}][Info={5}] token mapping resolver configuration parameter(s) change
+#
+# LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_AUTHENTICATOR
+# - used when configuring token authenticators
+# Service can be any of the methods offered
+# ParamNameValPairs must be a name;;value pair
+#    (where name and value are separated by the delimiter ;;)
+#    separated by + (if more than one name;;value pair) of config params changed
+#   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
+#
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_AUTHENTICATOR_6=<type=CONFIG_TOKEN_AUTHENTICATOR>:[AuditEvent=CONFIG_TOKEN_AUTHENTICATOR][SubjectID={0}][Outcome={1}][OP={2}][Authenticator={3}][ParamNameValPairs={4}][Info={5}] token authenticator configuration parameter(s) change
+#
+# LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_CONNECTOR
+# - used when configuring token connectors
+# Service can be any of the methods offered
+# ParamNameValPairs must be a name;;value pair
+#    (where name and value are separated by the delimiter ;;)
+#    separated by + (if more than one name;;value pair) of config params changed
+#   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
+#
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_CONNECTOR_6=<type=CONFIG_TOKEN_CONNECTOR>:[AuditEvent=CONFIG_TOKEN_CONNECTOR][SubjectID={0}][Outcome={1}][Service={2}][Connector={3}][ParamNameValPairs={4}][Info={5}] token connector configuration parameter(s) change
+#
+# LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_RECORD
+# - used when token state changed
+# ParamNameValPairs must be a name;;value pair
+#    (where name and value are separated by the delimiter ;;)
+#    separated by + (if more than one name;;value pair) of config params changed
+#   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
+#
+LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_RECORD_6=<type=CONFIG_TOKEN_RECORD>:[AuditEvent=CONFIG_TOKEN_RECORD][SubjectID={0}][Outcome={1}][OP={2}][TokenID={3}][ParamNameValPairs={4}][Info={5}] token record configuration parameter(s) change
 #
 # LOGGING_SIGNED_AUDIT_TOKEN_STATE_CHANGE
 # - used when token state changed
+# ParamNameValPairs must be a name;;value pair
+#    (where name and value are separated by the delimiter ;;)
+#    separated by + (if more than one name;;value pair) of config params changed
+#   --- secret component (password) MUST NOT be logged ---
+# - info in general is used for caturing error info for failed cases
 #
-LOGGING_SIGNED_AUDIT_TOKEN_STATE_CHANGE_5=<type=TOKEN_STATE_CHANGE>:[AuditEvent=TOKEN_STATE_CHANGE][SubjectID={0}][Outcome={1}][CUID={2}][oldState={3}][newState={4}] token state changed
+LOGGING_SIGNED_AUDIT_TOKEN_STATE_CHANGE_8=<type=TOKEN_STATE_CHANGE>:[AuditEvent=TOKEN_STATE_CHANGE][SubjectID={0}][Outcome={1}][oldState={2}][oldReason={3}][newState={4}][newReason={5}][ParamNameValPairs={6}][Info={7}] token state changed
 #
 # LOGGING_SIGNED_AUDIT_AUTHORITY_CONFIG
 # - used when configuring lightweight authorities
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
index f0bcb5bee3b36c654889921f6fcc5b1d5046c44e..8c99e676cc4d8acab36e90b3748fb7d9db7984ec 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
@@ -95,7 +95,8 @@ public class Auditor implements IAuditor {
     public String getParamString(String scope, String type, String id, Map<String, String> params) {
 
         // if no signed audit object exists, bail
-        if (signedAuditLogger == null) return null;
+        if (signedAuditLogger == null)
+            return null;
         StringBuilder parameters = new StringBuilder();
 
         // always identify the scope of the request
@@ -124,16 +125,26 @@ public class Auditor implements IAuditor {
                     + SIGNED_AUDIT_NAME_VALUE_DELIMITER
                     + id);
         }
+        return getParamString(parameters, params);
+    }
 
-        if (params == null) return parameters.toString();
+    @Override
+    public String getParamString(StringBuilder parameters, Map<String, String> params) {
+
+        if (parameters == null) {
+            parameters = new StringBuilder();
+        }
+        if (params == null)
+            return parameters.toString();
 
         // identify any remaining request parameters
 
-        for (Map.Entry<String,String> entry : params.entrySet() ) {
+        for (Map.Entry<String, String> entry : params.entrySet()) {
             String name = entry.getKey();
 
             // skip "RULENAME" parameter
-            if (name.equals(SIGNED_AUDIT_RULENAME)) continue;
+            if (name.equals(SIGNED_AUDIT_RULENAME))
+                continue;
 
             parameters.append(SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER);
 
diff --git a/base/tps/shared/conf/CS.cfg.in b/base/tps/shared/conf/CS.cfg.in
index 2285300ec69bd093f9ac4d110582114af2310bf9..b1cdc572341afeb3322e266b9dc3fb4141b6a669 100644
--- a/base/tps/shared/conf/CS.cfg.in
+++ b/base/tps/shared/conf/CS.cfg.in
@@ -208,11 +208,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,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_CERT_STATUS_CHANGE_REQUEST,TOKEN_PIN_RESET_SUCCESS,TOKEN_PIN_RESET_FAILURE,TOKEN_OP_REQUEST,TOKEN_FORMAT_SUCCESS,TOKEN_FORMAT_FAILURE,TOKEN_APPLET_UPGRADE_SUCCESS,TOKEN_APPLET_UPGRADE_FAILURE,TOKEN_KEY_CHANGEOVER_REQUIREDTOKEN_KEY_CHANGEOVER_FAILURE,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_GENERAL,TOKEN_STATE_CHANGE,TOKEN_CERT_RETRIEVAL,TOKEN_KEY_RECOVERY,TOKEN_AUTH_SUCCESS,TOKEN_AUTH_FAILURE
+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,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_PIN_RESET_SUCCESS,TOKEN_PIN_RESET_FAILURE,TOKEN_OP_REQUEST,TOKEN_FORMAT_SUCCESS,TOKEN_FORMAT_FAILURE,TOKEN_APPLET_UPGRADE_SUCCESS,TOKEN_APPLET_UPGRADE_FAILURE,TOKEN_KEY_CHANGEOVER_REQUIREDTOKEN_KEY_CHANGEOVER_FAILURE,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_MAPPING_RESOLVER,CONFIG_TOKEN_GENERAL,CONFIG_TOKEN_CONNECTOR,CONFIG_TOKEN_RECORD,CONFIG_TOKEN_AUTHENTICATOR,TOKEN_STATE_CHANGE,TOKEN_CERT_RETRIEVAL,TOKEN_KEY_RECOVERY,TOKEN_AUTH_SUCCESS,TOKEN_AUTH_FAILURE
 log.instance.SignedAudit._006=##
 log.instance.SignedAudit.bufferSize=512
 log.instance.SignedAudit.enable=true
-log.instance.SignedAudit.events=SELFTESTS_EXECUTION,AUTHZ_SUCCESS,AUTHZ_FAIL,AUTH_FAIL,AUTH_SUCCESS,AUTH_FAIL,ROLE_ASSUME,AUTHZ_SUCCESS,AUTHZ_FAIL,CIMC_CERT_VERIFICATION,CONFIG_SIGNED_AUDIT,CONFIG_ROLE,CONFIG_AUTH,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_CERT_STATUS_CHANGE_REQUEST,TOKEN_PIN_RESET_SUCCESS,TOKEN_PIN_RESET_FAILURE,TOKEN_OP_REQUEST,TOKEN_FORMAT_SUCCESS,TOKEN_FORMAT_FAILURE,TOKEN_APPLET_UPGRADE_SUCCESS,TOKEN_APPLET_UPGRADE_FAILURE,TOKEN_KEY_CHANGEOVER_REQUIRED,TOKEN_KEY_CHANGEOVER_SUCCESS,TOKEN_KEY_CHANGEOVER_FAILURE,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_GENERAL,TOKEN_STATE_CHANGE,TOKEN_CERT_RETRIEVAL,TOKEN_KEY_RECOVERY,TOKEN_AUTH_SUCCESS,TOKEN_AUTH_FAILURE
+log.instance.SignedAudit.events=SELFTESTS_EXECUTION,AUTHZ_SUCCESS,AUTHZ_FAIL,AUTH_FAIL,AUTH_SUCCESS,AUTH_FAIL,ROLE_ASSUME,AUTHZ_SUCCESS,AUTHZ_FAIL,CIMC_CERT_VERIFICATION,CONFIG_SIGNED_AUDIT,CONFIG_ROLE,CONFIG_AUTH,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_PIN_RESET_SUCCESS,TOKEN_PIN_RESET_FAILURE,TOKEN_OP_REQUEST,TOKEN_FORMAT_SUCCESS,TOKEN_FORMAT_FAILURE,TOKEN_APPLET_UPGRADE_SUCCESS,TOKEN_APPLET_UPGRADE_FAILURE,TOKEN_KEY_CHANGEOVER_REQUIRED,TOKEN_KEY_CHANGEOVER_SUCCESS,TOKEN_KEY_CHANGEOVER_FAILURE,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_MAPPING_RESOLVER,CONFIG_TOKEN_GENERAL,CONFIG_TOKEN_CONNECTOR,CONFIG_TOKEN_RECORD,CONFIG_TOKEN_AUTHENTICATOR,TOKEN_STATE_CHANGE,TOKEN_CERT_RETRIEVAL,TOKEN_KEY_RECOVERY,TOKEN_AUTH_SUCCESS,TOKEN_AUTH_FAILURE
 log.instance.SignedAudit.unselected.events=
 log.instance.SignedAudit.mandatory.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,LOGGING_SIGNED_AUDIT_SIGNING
 log.instance.SignedAudit.expirationTime=0
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java b/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java
index 6cd5e9f7d8be3229f6bb83ace5bb83b5990feab2..b0b4fd229a322e2ecbb959314ad737023a883745 100644
--- a/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java
@@ -20,6 +20,7 @@ package org.dogtagpki.server.tps.config;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
@@ -34,6 +35,7 @@ import org.jboss.resteasy.plugins.providers.atom.Link;
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.config.ConfigData;
 import com.netscape.certsrv.tps.config.ConfigResource;
 import com.netscape.cms.servlet.base.PKIService;
@@ -94,8 +96,15 @@ public class ConfigService extends PKIService implements ConfigResource {
 
     @Override
     public Response updateConfig(ConfigData configData) {
+        String method = "ConfigService.updateConfig";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (configData == null) throw new BadRequestException("Config data is null.");
+        if (configData == null) {
+            BadRequestException e = new BadRequestException("Config data is null.");
+            auditModParams.put("Info", e.toString());
+            auditConfigTokenGeneral(ILogger.FAILURE, method, auditModParams, e.toString());
+            throw e;
+        }
 
         CMS.debug("ConfigService.updateConfig()");
 
@@ -103,32 +112,41 @@ public class ConfigService extends PKIService implements ConfigResource {
             ConfigDatabase configDatabase = new ConfigDatabase();
             ConfigRecord configRecord = configDatabase.getRecord("Generals");
 
-            Map<String, String> properties = configData.getProperties();
-            if (properties != null) {
+            Map<String, String> newProperties = configData.getProperties();
+            if (newProperties != null) {
                 // validate new properties
-                configDatabase.validateProperties(configRecord, null, properties);
+                configDatabase.validateProperties(configRecord, null, newProperties);
 
                 // remove old properties
                 configDatabase.removeProperties(configRecord, null);
 
                 // add new properties
-                configDatabase.addProperties(configRecord, null, properties);
+                configDatabase.addProperties(configRecord, null, newProperties);
             }
 
             configDatabase.commit();
 
-            properties = configDatabase.getProperties(configRecord, null);
+            Map<String, String> properties = configDatabase.getProperties(configRecord, null);
             configData = createConfigData(properties);
 
+            auditConfigTokenGeneral(ILogger.SUCCESS, method,
+                    newProperties, null);
+
             return Response
                     .ok(configData)
                     .build();
 
         } catch (PKIException e) {
+            CMS.debug(method +": " + e);
+            auditConfigTokenGeneral(ILogger.FAILURE, method,
+                    auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
             e.printStackTrace();
+            CMS.debug(method +": " + e);
+            auditConfigTokenGeneral(ILogger.FAILURE, method,
+                    auditModParams, e.toString());
             throw new PKIException(e.getMessage());
         }
     }
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java b/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java
index 2ebc1d6ac416b5da204f8178983577b483e2ee2e..65c1593449e590c60a408bd90515a43dad47b772 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java
@@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLEncoder;
 import java.security.Principal;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -43,6 +44,7 @@ import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.authenticator.AuthenticatorCollection;
 import com.netscape.certsrv.tps.authenticator.AuthenticatorData;
 import com.netscape.certsrv.tps.authenticator.AuthenticatorResource;
@@ -69,7 +71,8 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
         CMS.debug("AuthenticatorService.<init>()");
     }
 
-    public AuthenticatorData createAuthenticatorData(AuthenticatorRecord authenticatorRecord) throws UnsupportedEncodingException {
+    public AuthenticatorData createAuthenticatorData(AuthenticatorRecord authenticatorRecord)
+            throws UnsupportedEncodingException {
 
         String authenticatorID = authenticatorRecord.getID();
 
@@ -79,7 +82,8 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
         authenticatorData.setProperties(authenticatorRecord.getProperties());
 
         authenticatorID = URLEncoder.encode(authenticatorID, "UTF-8");
-        URI uri = uriInfo.getBaseUriBuilder().path(AuthenticatorResource.class).path("{authenticatorID}").build(authenticatorID);
+        URI uri = uriInfo.getBaseUriBuilder().path(AuthenticatorResource.class).path("{authenticatorID}")
+                .build(authenticatorID);
         authenticatorData.setLink(new Link("self", uri));
 
         return authenticatorData;
@@ -108,7 +112,7 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
         size = size == null ? DEFAULT_SIZE : size;
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             Iterator<AuthenticatorRecord> authenticators = database.findRecords(filter).iterator();
@@ -117,24 +121,26 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && authenticators.hasNext(); i++) authenticators.next();
+            for (; i < start && authenticators.hasNext(); i++)
+                authenticators.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && authenticators.hasNext(); i++) {
+            for (; i < start + size && authenticators.hasNext(); i++) {
                 response.addEntry(createAuthenticatorData(authenticators.next()));
             }
 
             // count the total entries
-            for ( ; authenticators.hasNext(); i++) authenticators.next();
+            for (; authenticators.hasNext(); i++)
+                authenticators.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -153,12 +159,13 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
     @Override
     public Response getAuthenticator(String authenticatorID) {
 
-        if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+        if (authenticatorID == null)
+            throw new BadRequestException("Authenticator ID is null.");
 
         CMS.debug("AuthenticatorService.getAuthenticator(\"" + authenticatorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             return createOKResponse(createAuthenticatorData(database.getRecord(authenticatorID)));
@@ -175,68 +182,105 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
 
     @Override
     public Response addAuthenticator(AuthenticatorData authenticatorData) {
+        String method = "AuthenticatorService.addAuthenticator";
 
-        if (authenticatorData == null) throw new BadRequestException("Authenticator data is null.");
+        if (authenticatorData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Authenticator data is null.");
+            throw new BadRequestException("Authenticator data is null.");
+        }
 
         CMS.debug("AuthenticatorService.addAuthenticator(\"" + authenticatorData.getID() + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             String status = authenticatorData.getStatus();
             Principal principal = servletRequest.getUserPrincipal();
 
+            boolean statusChanged = false;
             if (StringUtils.isEmpty(status) || database.requiresApproval() && !database.canApprove(principal)) {
                 // if status is unspecified or user doesn't have rights to approve, the entry is disabled
-                authenticatorData.setStatus(Constants.CFG_DISABLED);
+                status = Constants.CFG_DISABLED;
+                authenticatorData.setStatus(status);
+                statusChanged = true;
             }
 
             database.addRecord(authenticatorData.getID(), createAuthenticatorRecord(authenticatorData));
             authenticatorData = createAuthenticatorData(database.getRecord(authenticatorData.getID()));
+            Map<String, String> properties = authenticatorData.getProperties();
+            if (statusChanged) {
+                properties.put("Status", status);
+            }
+            auditTPSAuthenticatorChange(ILogger.SUCCESS, method, authenticatorData.getID(), properties, null);
 
             return createCreatedResponse(authenticatorData, authenticatorData.getLink().getHref());
 
         } catch (PKIException e) {
             CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorData.getID(), authenticatorData.getProperties(), e.toString());
+
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorData.getID(), authenticatorData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response updateAuthenticator(String authenticatorID, AuthenticatorData authenticatorData) {
+        String method = "uthenticatorService.updateAuthenticator";
 
-        if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
-        if (authenticatorData == null) throw new BadRequestException("Authenticator data is null.");
+        if (authenticatorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Authenticator ID is null.");
+            throw new BadRequestException("Authenticator ID is null.");
+        }
+        if (authenticatorData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Authenticator data is null.");
+            throw new BadRequestException("Authenticator data is null.");
+        }
 
         CMS.debug("AuthenticatorService.updateAuthenticator(\"" + authenticatorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             AuthenticatorRecord record = database.getRecord(authenticatorID);
 
             // only disabled authenticator can be updated
             if (!Constants.CFG_DISABLED.equals(record.getStatus())) {
-                throw new ForbiddenException("Unable to update authenticator " + authenticatorID);
+                Exception e = new ForbiddenException("Unable to update authenticator "
+                        + authenticatorID
+                        + "; authenticator not disabled");
+                auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                        authenticatorID, authenticatorData.getProperties(), e.toString());
+                throw e;
             }
 
             // update status if specified
             String status = authenticatorData.getStatus();
+            boolean statusChanged = false;
             if (status != null && !Constants.CFG_DISABLED.equals(status)) {
                 if (!Constants.CFG_ENABLED.equals(status)) {
-                    throw new ForbiddenException("Invalid authenticator status: " + status);
+                    ForbiddenException e = new ForbiddenException("Invalid authenticator status: " + status);
+                    auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                            authenticatorID, authenticatorData.getProperties(), e.toString());
+                    throw e;
                 }
 
                 // if user doesn't have rights, set to pending
                 Principal principal = servletRequest.getUserPrincipal();
                 if (database.requiresApproval() && !database.canApprove(principal)) {
                     status = Constants.CFG_PENDING_APPROVAL;
+                    statusChanged = true;
                 }
 
                 // enable authenticator
@@ -247,34 +291,54 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
             Map<String, String> properties = authenticatorData.getProperties();
             if (properties != null) {
                 record.setProperties(authenticatorData.getProperties());
+                if (statusChanged) {
+                    properties.put("Status", status);
+                }
             }
 
             database.updateRecord(authenticatorID, record);
 
             authenticatorData = createAuthenticatorData(database.getRecord(authenticatorID));
+            auditTPSAuthenticatorChange(ILogger.SUCCESS, method, authenticatorData.getID(), properties, null);
 
             return createOKResponse(authenticatorData);
 
         } catch (PKIException e) {
             CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, authenticatorData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, authenticatorData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response changeStatus(String authenticatorID, String action) {
+        String method = "AuthenticatorService.changeStatus";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
-        if (action == null) throw new BadRequestException("Action is null.");
+        if (authenticatorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "authenticator id is null.");
+            throw new BadRequestException("Authenticator ID is null.");
+        }
+        auditModParams.put("authenticatorID", authenticatorID);
+        if (action == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, auditModParams,
+                    "action is null.");
+            throw new BadRequestException("Action is null.");
+        }
+        auditModParams.put("Action", action);
 
         CMS.debug("AuthenticatorService.changeStatus(\"" + authenticatorID + "\", \"" + action + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             AuthenticatorRecord record = database.getRecord(authenticatorID);
@@ -294,7 +358,10 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                                authenticatorID, auditModParams, e.toString());
+                        throw e;
                     }
 
                 } else {
@@ -302,7 +369,10 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                                authenticatorID, auditModParams, e.toString());
+                        throw e;
                     }
                 }
 
@@ -312,7 +382,10 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                            authenticatorID, auditModParams, e.toString());
+                    throw e;
                 }
 
             } else if (Constants.CFG_PENDING_APPROVAL.equals(status)) {
@@ -327,59 +400,105 @@ public class AuthenticatorService extends PKIService implements AuthenticatorRes
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                            authenticatorID, auditModParams, e.toString());
                 }
 
             } else {
-                throw new PKIException("Invalid status: " + status);
+                PKIException e = new PKIException("Invalid status: " + status);
+                auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                        authenticatorID, auditModParams, e.toString());
+                throw e;
             }
 
             record.setStatus(status);
             database.updateRecord(authenticatorID, record);
 
             AuthenticatorData authenticatorData = createAuthenticatorData(database.getRecord(authenticatorID));
+            auditModParams.put("Status", status);
+            auditTPSAuthenticatorChange(ILogger.SUCCESS, method, authenticatorID, auditModParams, null);
 
             return createOKResponse(authenticatorData);
 
         } catch (PKIException e) {
             CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response removeAuthenticator(String authenticatorID) {
+        String method = "AuthenticatorService.removeAuthenticator";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+        if (authenticatorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Authenticator ID is null.");
+            throw new BadRequestException("Authenticator ID is null.");
+        }
+        auditModParams.put("authenticatorID", authenticatorID);
 
         CMS.debug("AuthenticatorService.removeAuthenticator(\"" + authenticatorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
 
             AuthenticatorRecord record = database.getRecord(authenticatorID);
             String status = record.getStatus();
 
             if (!Constants.CFG_DISABLED.equals(status)) {
-                throw new ForbiddenException("Unable to delete authenticator " + authenticatorID);
+                Exception e = new ForbiddenException("Unable to remove authenticator "
+                        + authenticatorID
+                        + "; authenticator not disabled");
+                auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                        authenticatorID, auditModParams, e.toString());
+                throw e;
             }
 
             database.removeRecord(authenticatorID);
+            auditTPSAuthenticatorChange(ILogger.SUCCESS, method, authenticatorID, null, null);
 
             return createNoContentResponse();
 
         } catch (PKIException e) {
             CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("AuthenticatorService: " + e);
+            auditTPSAuthenticatorChange(ILogger.FAILURE, method,
+                    authenticatorID, auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
+
+    /*
+     * service can be any of the methods offered
+     */
+    public void auditTPSAuthenticatorChange(String status, String service, String authenticatorID,
+            Map<String, String> params, String info) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_AUTHENTICATOR_6",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                authenticatorID,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java
index 1936b2e2eb090f947f69d972c1a8888b7f4ec326..769f00f5704a1e9189b97990fe9e7aecfe96fe19 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java
@@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLEncoder;
 import java.security.Principal;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -43,6 +44,7 @@ import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.connector.ConnectorCollection;
 import com.netscape.certsrv.tps.connector.ConnectorData;
 import com.netscape.certsrv.tps.connector.ConnectorResource;
@@ -108,7 +110,7 @@ public class ConnectorService extends PKIService implements ConnectorResource {
         size = size == null ? DEFAULT_SIZE : size;
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             Iterator<ConnectorRecord> connections = database.findRecords(filter).iterator();
@@ -117,24 +119,26 @@ public class ConnectorService extends PKIService implements ConnectorResource {
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && connections.hasNext(); i++) connections.next();
+            for (; i < start && connections.hasNext(); i++)
+                connections.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && connections.hasNext(); i++) {
+            for (; i < start + size && connections.hasNext(); i++) {
                 response.addEntry(createConnectorData(connections.next()));
             }
 
             // count the total entries
-            for ( ; connections.hasNext(); i++) connections.next();
+            for (; connections.hasNext(); i++)
+                connections.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -153,12 +157,13 @@ public class ConnectorService extends PKIService implements ConnectorResource {
     @Override
     public Response getConnector(String connectorID) {
 
-        if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+        if (connectorID == null)
+            throw new BadRequestException("Connector ID is null.");
 
         CMS.debug("ConnectorService.getConnector(\"" + connectorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             return createOKResponse(createConnectorData(database.getRecord(connectorID)));
@@ -175,62 +180,95 @@ public class ConnectorService extends PKIService implements ConnectorResource {
 
     @Override
     public Response addConnector(ConnectorData connectorData) {
+        String method = "ConnectorService.addConnector";
 
-        if (connectorData == null) throw new BadRequestException("Connector data is null.");
+        if (connectorData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Connector data is null.");
+            throw new BadRequestException("Connector data is null.");
+        }
 
         CMS.debug("ConnectorService.addConnector(\"" + connectorData.getID() + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             String status = connectorData.getStatus();
             Principal principal = servletRequest.getUserPrincipal();
 
+            boolean statusChanged = false;
             if (StringUtils.isEmpty(status) || database.requiresApproval() && !database.canApprove(principal)) {
                 // if status is unspecified or user doesn't have rights to approve, the entry is disabled
-                connectorData.setStatus(Constants.CFG_DISABLED);
+                status = Constants.CFG_DISABLED;
+                connectorData.setStatus(status);
+                statusChanged = true;
             }
 
             database.addRecord(connectorData.getID(), createConnectorRecord(connectorData));
             connectorData = createConnectorData(database.getRecord(connectorData.getID()));
+            Map<String, String> properties = connectorData.getProperties();
+            if (statusChanged) {
+                properties.put("Status", status);
+            }
+            auditTPSConnectorChange(ILogger.SUCCESS, method, connectorData.getID(), properties, null);
 
             return createCreatedResponse(connectorData, connectorData.getLink().getHref());
 
         } catch (PKIException e) {
             CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorData.getID(), connectorData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorData.getID(), connectorData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response updateConnector(String connectorID, ConnectorData connectorData) {
+        String method = "ConnectorService.updateConnector";
 
-        if (connectorID == null) throw new BadRequestException("Connector ID is null.");
-        if (connectorData == null) throw new BadRequestException("Connector data is null.");
+        if (connectorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Connector id is null.");
+            throw new BadRequestException("Connector ID is null.");
+        }
+        if (connectorData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Connector data is null.");
+            throw new BadRequestException("Connector data is null.");
+        }
 
         CMS.debug("ConnectorService.updateConnector(\"" + connectorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             ConnectorRecord record = database.getRecord(connectorID);
 
             // only disabled connector can be updated
             if (!Constants.CFG_DISABLED.equals(record.getStatus())) {
-                throw new ForbiddenException("Unable to update connector " + connectorID);
+                Exception e = new ForbiddenException("Unable to update connector " + connectorID);
+                auditTPSConnectorChange(ILogger.FAILURE, method,
+                        connectorData.getID(), connectorData.getProperties(), e.toString());
+                throw e;
             }
 
             // update status if specified
             String status = connectorData.getStatus();
+            boolean statusChanged = false;
             if (status != null && !Constants.CFG_DISABLED.equals(status)) {
                 if (!Constants.CFG_ENABLED.equals(status)) {
-                    throw new ForbiddenException("Invalid connector status: " + status);
+                    Exception e = new ForbiddenException("Invalid connector status: " + status);
+                    auditTPSConnectorChange(ILogger.FAILURE, method,
+                            connectorData.getID(), connectorData.getProperties(), e.toString());
+                    throw e;
                 }
 
                 // if user doesn't have rights, set to pending
@@ -241,40 +279,60 @@ public class ConnectorService extends PKIService implements ConnectorResource {
 
                 // enable connector
                 record.setStatus(status);
+                statusChanged = true;
             }
 
             // update properties if specified
             Map<String, String> properties = connectorData.getProperties();
             if (properties != null) {
                 record.setProperties(properties);
+                if (statusChanged) {
+                    properties.put("Status", status);
+                }
             }
 
             database.updateRecord(connectorID, record);
 
             connectorData = createConnectorData(database.getRecord(connectorID));
+            auditTPSConnectorChange(ILogger.SUCCESS, method, connectorData.getID(), properties, null);
 
             return createOKResponse(connectorData);
 
         } catch (PKIException e) {
             CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorData.getID(), connectorData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorData.getID(), connectorData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response changeStatus(String connectorID, String action) {
+        String method = "ConnectorService.changeStatus";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (connectorID == null) throw new BadRequestException("Connector ID is null.");
-        if (action == null) throw new BadRequestException("Action is null.");
+        if (connectorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Connector id is null.");
+            throw new BadRequestException("Connector ID is null.");
+        }
+        if (action == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Action is null.");
+            throw new BadRequestException("Action is null.");
+        }
+        auditModParams.put("Action", action);
 
         CMS.debug("ConnectorService.changeStatus(\"" + connectorID + "\", \"" + action + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             ConnectorRecord record = database.getRecord(connectorID);
@@ -294,7 +352,12 @@ public class ConnectorService extends PKIService implements ConnectorResource {
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditConfigTokenGeneral(ILogger.FAILURE, method,
+                                auditModParams, e.toString());
+                        auditTPSConnectorChange(ILogger.FAILURE, method,
+                                connectorID, auditModParams, e.toString());
+                        throw e;
                     }
 
                 } else {
@@ -302,7 +365,10 @@ public class ConnectorService extends PKIService implements ConnectorResource {
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditTPSConnectorChange(ILogger.FAILURE, method,
+                                connectorID, auditModParams, e.toString());
+                        throw e;
                     }
                 }
 
@@ -312,7 +378,10 @@ public class ConnectorService extends PKIService implements ConnectorResource {
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSConnectorChange(ILogger.FAILURE, method,
+                            connectorID, auditModParams, e.toString());
+                    throw e;
                 }
 
             } else if (Constants.CFG_PENDING_APPROVAL.equals(status)) {
@@ -327,59 +396,106 @@ public class ConnectorService extends PKIService implements ConnectorResource {
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSConnectorChange(ILogger.FAILURE, method,
+                            connectorID, auditModParams, e.toString());
+                    throw e;
                 }
 
             } else {
-                throw new PKIException("Invalid connector status: " + status);
+                Exception e = new BadRequestException("Invalid connector status: " + status);
+                auditTPSConnectorChange(ILogger.FAILURE, method,
+                        connectorID, auditModParams, e.toString());
+                throw e;
             }
 
             record.setStatus(status);
             database.updateRecord(connectorID, record);
 
             ConnectorData connectorData = createConnectorData(database.getRecord(connectorID));
+            auditModParams.put("Status", status);
+            auditTPSConnectorChange(ILogger.SUCCESS, method, connectorData.getID(), auditModParams, null);
 
             return createOKResponse(connectorData);
 
         } catch (PKIException e) {
             CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorID, auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorID, auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response removeConnector(String connectorID) {
+        String method = "ConnectorService.removeConnector";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+        if (connectorID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Connector ID is null.");
+            throw new BadRequestException("Connector ID is null.");
+        }
+        auditModParams.put("connectorID", connectorID);
 
         CMS.debug("ConnectorService.removeConnector(\"" + connectorID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ConnectorDatabase database = subsystem.getConnectorDatabase();
 
             ConnectorRecord record = database.getRecord(connectorID);
             String status = record.getStatus();
 
             if (!Constants.CFG_DISABLED.equals(status)) {
-                throw new ForbiddenException("Unable to delete connector " + connectorID);
+                Exception e = new ForbiddenException("Unable to delete connector "
+                        + connectorID
+                        + "; connector not disabled");
+                auditTPSConnectorChange(ILogger.FAILURE, method,
+                        connectorID, auditModParams, e.toString());
+                throw e;
             }
 
             database.removeRecord(connectorID);
+            auditTPSConnectorChange(ILogger.SUCCESS, method, connectorID, null, null);
 
             return createNoContentResponse();
 
         } catch (PKIException e) {
             CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorID, auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ConnectorService: " + e);
+            auditTPSConnectorChange(ILogger.FAILURE, method,
+                    connectorID, auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
+
+    /*
+     * service can be any of the methods offered
+     */
+    public void auditTPSConnectorChange(String status, String service, String connectorID, Map<String, String> params,
+            String info) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_CONNECTOR_6",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                connectorID,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java
index 970dfde1dd6e2fdf6e4b27471d3ffc40092f1fff..84c171f57e6e0126928730daadc898c26369f561 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java
@@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLEncoder;
 import java.security.Principal;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -43,6 +44,7 @@ import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.profile.ProfileMappingCollection;
 import com.netscape.certsrv.tps.profile.ProfileMappingData;
 import com.netscape.certsrv.tps.profile.ProfileMappingResource;
@@ -69,7 +71,8 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
         CMS.debug("ProfileMappingService.<init>()");
     }
 
-    public ProfileMappingData createProfileMappingData(ProfileMappingRecord profileMappingRecord) throws UnsupportedEncodingException {
+    public ProfileMappingData createProfileMappingData(ProfileMappingRecord profileMappingRecord)
+            throws UnsupportedEncodingException {
 
         String profileMappingID = profileMappingRecord.getID();
 
@@ -79,7 +82,8 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
         profileMappingData.setProperties(profileMappingRecord.getProperties());
 
         profileMappingID = URLEncoder.encode(profileMappingID, "UTF-8");
-        URI uri = uriInfo.getBaseUriBuilder().path(ProfileMappingResource.class).path("{profileMappingID}").build(profileMappingID);
+        URI uri = uriInfo.getBaseUriBuilder().path(ProfileMappingResource.class).path("{profileMappingID}")
+                .build(profileMappingID);
         profileMappingData.setLink(new Link("self", uri));
 
         return profileMappingData;
@@ -108,7 +112,7 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
         size = size == null ? DEFAULT_SIZE : size;
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             Iterator<ProfileMappingRecord> profileMappings = database.findRecords(filter).iterator();
@@ -117,24 +121,26 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && profileMappings.hasNext(); i++) profileMappings.next();
+            for (; i < start && profileMappings.hasNext(); i++)
+                profileMappings.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && profileMappings.hasNext(); i++) {
+            for (; i < start + size && profileMappings.hasNext(); i++) {
                 response.addEntry(createProfileMappingData(profileMappings.next()));
             }
 
             // count the total entries
-            for ( ; profileMappings.hasNext(); i++) profileMappings.next();
+            for (; profileMappings.hasNext(); i++)
+                profileMappings.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -156,7 +162,7 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
         CMS.debug("ProfileMappingService.getProfileMapping(\"" + profileMappingID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             return createOKResponse(createProfileMappingData(database.getRecord(profileMappingID)));
@@ -173,11 +179,12 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
     @Override
     public Response addProfileMapping(ProfileMappingData profileMappingData) {
+        String method = "ProfileMappingService.addProfileMapping";
 
         CMS.debug("ProfileMappingService.addProfileMapping(\"" + profileMappingData.getID() + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             String status = profileMappingData.getStatus();
@@ -190,40 +197,54 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
             database.addRecord(profileMappingData.getID(), createProfileMappingRecord(profileMappingData));
             profileMappingData = createProfileMappingData(database.getRecord(profileMappingData.getID()));
+            auditMappingResolverChange(ILogger.SUCCESS, method, profileMappingData.getID(),
+                    profileMappingData.getProperties(), null);
 
             return createCreatedResponse(profileMappingData, profileMappingData.getLink().getHref());
 
         } catch (PKIException e) {
             CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                    profileMappingData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
             CMS.debug(e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                    profileMappingData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response updateProfileMapping(String profileMappingID, ProfileMappingData profileMappingData) {
+        String method = "ProfileMappingService.updateProfileMapping";
 
         CMS.debug("ProfileMappingService.updateProfileMapping(\"" + profileMappingID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             ProfileMappingRecord record = database.getRecord(profileMappingID);
 
             // only disabled profile mapping can be updated
             if (!Constants.CFG_DISABLED.equals(record.getStatus())) {
-                throw new ForbiddenException("Unable to update profile mapping " + profileMappingID);
+                Exception e = new ForbiddenException("Unable to update profile mapping " + profileMappingID);
+                auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                        profileMappingData.getProperties(), e.toString());
+                throw e;
             }
 
             // update status if specified
             String status = profileMappingData.getStatus();
+            boolean statusChanged = false;
             if (status != null && !Constants.CFG_DISABLED.equals(status)) {
                 if (!Constants.CFG_ENABLED.equals(status)) {
-                    throw new ForbiddenException("Invalid profile mapping status: " + status);
+                    Exception e = new ForbiddenException("Invalid profile mapping status: " + status);
+                    auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                            profileMappingData.getProperties(), e.toString());
+                    throw e;
                 }
 
                 // if user doesn't have rights, set to pending
@@ -234,6 +255,7 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
                 // enable profile mapping
                 record.setStatus(status);
+                statusChanged = true;
             }
 
             // update properties if specified
@@ -245,32 +267,54 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
             database.updateRecord(profileMappingID, record);
 
             profileMappingData = createProfileMappingData(database.getRecord(profileMappingID));
+            if (statusChanged) {
+                properties.put("Status", status);
+            }
+            auditMappingResolverChange(ILogger.SUCCESS, method, profileMappingData.getID(), properties, null);
 
             return createOKResponse(profileMappingData);
 
         } catch (PKIException e) {
             CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                    profileMappingData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingData.getID(),
+                    profileMappingData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response changeStatus(String profileMappingID, String action) {
+        String method = "ProfileMappingService.changeStatus";
 
-        if (profileMappingID == null) throw new BadRequestException("Profile mapping ID is null.");
-        if (action == null) throw new BadRequestException("Action is null.");
+        Map<String, String> auditModParams = new HashMap<String, String>();
+
+        if (profileMappingID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile mapper ID is null.");
+            throw new BadRequestException("Profile mapper ID is null.");
+        }
+
+        if (action == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, auditModParams,
+                    "action is null.");
+            throw new BadRequestException("Action is null.");
+        }
+        auditModParams.put("Action", action);
 
         CMS.debug("ProfileMappingService.changeStatus(\"" + profileMappingID + "\", \"" + action + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             ProfileMappingRecord record = database.getRecord(profileMappingID);
+            boolean statusChanged = false;
             String status = record.getStatus();
 
             Principal principal = servletRequest.getUserPrincipal();
@@ -282,20 +326,29 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
                     if ("submit".equals(action) && !canApprove) {
                         status = Constants.CFG_PENDING_APPROVAL;
+                        statusChanged = true;
 
                     } else if ("enable".equals(action) && canApprove) {
                         status = Constants.CFG_ENABLED;
+                        statusChanged = true;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                                auditModParams, e.toString());
+                        throw e;
                     }
 
                 } else {
                     if ("enable".equals(action)) {
                         status = Constants.CFG_ENABLED;
+                        statusChanged = true;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                                auditModParams, e.toString());
+                        throw e;
                     }
                 }
 
@@ -303,28 +356,41 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
                 if ("disable".equals(action)) {
                     status = Constants.CFG_DISABLED;
+                    statusChanged = true;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                            auditModParams, e.toString());
+                    throw e;
                 }
 
             } else if (Constants.CFG_PENDING_APPROVAL.equals(status)) {
 
                 if ("approve".equals(action) && canApprove) {
                     status = Constants.CFG_ENABLED;
+                    statusChanged = true;
 
                 } else if ("reject".equals(action) && canApprove) {
                     status = Constants.CFG_DISABLED;
+                    statusChanged = true;
 
                 } else if ("cancel".equals(action) && !canApprove) {
                     status = Constants.CFG_DISABLED;
+                    statusChanged = true;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                            auditModParams, e.toString());
+                    throw e;
                 }
 
             } else {
-                throw new PKIException("Invalid profile mapping status: " + status);
+                Exception e = new PKIException("Invalid profile mapping status: " + status);
+                auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                        auditModParams, e.toString());
+                throw e;
             }
 
             record.setStatus(status);
@@ -332,45 +398,82 @@ public class ProfileMappingService extends PKIService implements ProfileMappingR
 
             ProfileMappingData profileMappingData = createProfileMappingData(database.getRecord(profileMappingID));
 
+            if (statusChanged) {
+                auditModParams.put("Status", status);
+            }
+            auditMappingResolverChange(ILogger.SUCCESS, method, profileMappingData.getID(), auditModParams, null);
+
             return createOKResponse(profileMappingData);
 
         } catch (PKIException e) {
             CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                    auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response removeProfileMapping(String profileMappingID) {
+        String method = "ProfileMappingService.removeProfileMapping";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
         CMS.debug("ProfileMappingService.removeProfileMapping(\"" + profileMappingID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
 
             ProfileMappingRecord record = database.getRecord(profileMappingID);
             String status = record.getStatus();
 
             if (!Constants.CFG_DISABLED.equals(status)) {
-                throw new ForbiddenException("Unable to delete profile mapping " + profileMappingID);
+                Exception e = new ForbiddenException("Unable to delete profile mapping " + profileMappingID);
+                auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                        auditModParams, e.toString());
+                throw e;
             }
 
             database.removeRecord(profileMappingID);
+            auditMappingResolverChange(ILogger.SUCCESS, method, profileMappingID, null, null);
 
             return createNoContentResponse();
 
         } catch (PKIException e) {
             CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                    auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
-            CMS.debug(e);
+            CMS.debug("ProfileMappingService: " + e);
+            auditMappingResolverChange(ILogger.FAILURE, method, profileMappingID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
+
+    /*
+     * Service can be any of the methods offered
+     */
+    public void auditMappingResolverChange(String status, String service, String resolverID, Map<String, String> params,
+            String info) {
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_MAPPING_RESOLVER_6",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                resolverID,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
+
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java
index 5fc243073afa4d799f5d3cbb980c6e875bc1cdef..bbcbfae32157d20bc6d0d21d2c1a725172c66aad 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java
@@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLEncoder;
 import java.security.Principal;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -43,6 +44,7 @@ import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.profile.ProfileCollection;
 import com.netscape.certsrv.tps.profile.ProfileData;
 import com.netscape.certsrv.tps.profile.ProfileResource;
@@ -108,7 +110,7 @@ public class ProfileService extends PKIService implements ProfileResource {
         size = size == null ? DEFAULT_SIZE : size;
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             Iterator<ProfileRecord> profiles = database.findRecords(filter).iterator();
@@ -117,24 +119,26 @@ public class ProfileService extends PKIService implements ProfileResource {
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && profiles.hasNext(); i++) profiles.next();
+            for (; i < start && profiles.hasNext(); i++)
+                profiles.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && profiles.hasNext(); i++) {
+            for (; i < start + size && profiles.hasNext(); i++) {
                 response.addEntry(createProfileData(profiles.next()));
             }
 
             // count the total entries
-            for ( ; profiles.hasNext(); i++) profiles.next();
+            for (; profiles.hasNext(); i++)
+                profiles.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -153,12 +157,13 @@ public class ProfileService extends PKIService implements ProfileResource {
     @Override
     public Response getProfile(String profileID) {
 
-        if (profileID == null) throw new BadRequestException("Profile ID is null.");
+        if (profileID == null)
+            throw new BadRequestException("Profile ID is null.");
 
         CMS.debug("ProfileService.getProfile(\"" + profileID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             return createOKResponse(createProfileData(database.getRecord(profileID)));
@@ -175,63 +180,97 @@ public class ProfileService extends PKIService implements ProfileResource {
 
     @Override
     public Response addProfile(ProfileData profileData) {
+        String method = "ProfileService.addProfile";
 
-        if (profileData == null) throw new BadRequestException("Profile data is null.");
+        if (profileData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile data is null.");
+            throw new BadRequestException("Profile data is null.");
+        }
 
         CMS.debug("ProfileService.addProfile(\"" + profileData.getID() + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             String status = profileData.getStatus();
             Principal principal = servletRequest.getUserPrincipal();
 
+            boolean statusChanged = false;
             if (StringUtils.isEmpty(status) || database.requiresApproval() && !database.canApprove(principal)) {
                 // if status is unspecified or user doesn't have rights to approve, the entry is disabled
-                profileData.setStatus(Constants.CFG_DISABLED);
+                status = Constants.CFG_DISABLED;
+                profileData.setStatus(status);
+                statusChanged = true;
             }
 
             database.addRecord(profileData.getID(), createProfileRecord(profileData));
 
             profileData = createProfileData(database.getRecord(profileData.getID()));
 
+            //Map<String, String> properties = database.getRecord(profileData.getID()).getProperties();
+            Map<String, String> properties = profileData.getProperties();
+            if (statusChanged) {
+                properties.put("Status", status);
+            }
+            auditTPSProfileChange(ILogger.SUCCESS, method, profileData.getID(), properties, null);
+
             return createCreatedResponse(profileData, profileData.getLink().getHref());
 
         } catch (PKIException e) {
             CMS.debug("ProfileService: " + e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileData.getID(), null, e.toString());
             throw e;
 
         } catch (Exception e) {
             CMS.debug(e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileData.getID(), null, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response updateProfile(String profileID, ProfileData profileData) {
+        String method = "ProfileService.updateProfile";
 
-        if (profileID == null) throw new BadRequestException("Profile ID is null.");
-        if (profileData == null) throw new BadRequestException("Profile data is null.");
+        if (profileID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile id is null.");
+            throw new BadRequestException("Profile ID is null.");
+        }
+
+        if (profileData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile data is null.");
+            throw new BadRequestException("Profile data is null.");
+        }
 
         CMS.debug("ProfileService.updateProfile(\"" + profileID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             ProfileRecord record = database.getRecord(profileID);
 
             // only disabled profile can be updated
             if (!Constants.CFG_DISABLED.equals(record.getStatus())) {
-                throw new ForbiddenException("Unable to update profile " + profileID);
+                Exception e = new ForbiddenException("Unable to update profile " + profileID);
+                auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                        profileData.getProperties(), e.toString());
+                throw e;
             }
 
             // update status if specified
             String status = profileData.getStatus();
+            boolean statusChanged = false;
             if (status != null && !Constants.CFG_DISABLED.equals(status)) {
                 if (!Constants.CFG_ENABLED.equals(status)) {
-                    throw new ForbiddenException("Invalid profile status: " + status);
+                    Exception e = new ForbiddenException("Invalid profile status: " + status);
+                    auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                            profileData.getProperties(), e.toString());
+                    throw e;
                 }
 
                 // if user doesn't have rights, set to pending
@@ -242,40 +281,61 @@ public class ProfileService extends PKIService implements ProfileResource {
 
                 // enable profile
                 record.setStatus(status);
+                statusChanged = true;
             }
 
             // update properties if specified
             Map<String, String> properties = profileData.getProperties();
             if (properties != null) {
                 record.setProperties(properties);
+                if (statusChanged) {
+                    properties.put("Status", status);
+                }
             }
 
             database.updateRecord(profileID, record);
 
             profileData = createProfileData(database.getRecord(profileID));
 
+            auditTPSProfileChange(ILogger.SUCCESS, method, profileData.getID(), properties, null);
+
             return createOKResponse(profileData);
 
         } catch (PKIException e) {
             CMS.debug("ProfileService: " + e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileID, profileData.getProperties(), e.toString());
             throw e;
 
         } catch (Exception e) {
             CMS.debug(e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileID, profileData.getProperties(), e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response changeStatus(String profileID, String action) {
+        String method = "ProfileService.changeStatus";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (profileID == null) throw new BadRequestException("Profile ID is null.");
-        if (action == null) throw new BadRequestException("Action is null.");
+        if (profileID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile id is null.");
+            throw new BadRequestException("Profile ID is null.");
+        }
+        auditModParams.put("profileID", profileID);
+
+        if (action == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, auditModParams,
+                    "action is null.");
+            throw new BadRequestException("Action is null.");
+        }
+        auditModParams.put("Action", action);
 
         CMS.debug("ProfileService.changeStatus(\"" + profileID + "\", \"" + action + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             ProfileRecord record = database.getRecord(profileID);
@@ -295,7 +355,10 @@ public class ProfileService extends PKIService implements ProfileResource {
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                                auditModParams, e.toString());
+                        throw e;
                     }
 
                 } else {
@@ -303,7 +366,10 @@ public class ProfileService extends PKIService implements ProfileResource {
                         status = Constants.CFG_ENABLED;
 
                     } else {
-                        throw new BadRequestException("Invalid action: " + action);
+                        Exception e = new BadRequestException("Invalid action: " + action);
+                        auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                                auditModParams, e.toString());
+                        throw e;
                     }
                 }
 
@@ -313,7 +379,10 @@ public class ProfileService extends PKIService implements ProfileResource {
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                            auditModParams, e.toString());
+                    throw e;
                 }
 
             } else if (Constants.CFG_PENDING_APPROVAL.equals(status)) {
@@ -328,59 +397,105 @@ public class ProfileService extends PKIService implements ProfileResource {
                     status = Constants.CFG_DISABLED;
 
                 } else {
-                    throw new BadRequestException("Invalid action: " + action);
+                    Exception e = new BadRequestException("Invalid action: " + action);
+                    auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                            auditModParams, e.toString());
+                    throw e;
                 }
 
             } else {
-                throw new PKIException("Invalid profile status: " + status);
+                Exception e = new PKIException("Invalid profile status: " + status);
+                auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                        auditModParams, e.toString());
+                throw e;
             }
 
             record.setStatus(status);
             database.updateRecord(profileID, record);
 
             ProfileData profileData = createProfileData(database.getRecord(profileID));
+            auditModParams.put("Status", status);
+            auditTPSProfileChange(ILogger.SUCCESS, method, profileID, auditModParams, null);
 
             return createOKResponse(profileData);
 
         } catch (PKIException e) {
             CMS.debug("ProfileService: " + e);
+            auditConfigTokenGeneral(ILogger.FAILURE, method,
+                    auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
             CMS.debug(e);
+            auditConfigTokenGeneral(ILogger.FAILURE, method,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response removeProfile(String profileID) {
+        String method = "ProfileService.removeProfile";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (profileID == null) throw new BadRequestException("Profile ID is null.");
+        if (profileID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Profile ID is null.");
+            throw new BadRequestException("Profile ID is null.");
+        }
+        auditModParams.put("profileID", profileID);
 
         CMS.debug("ProfileService.removeProfile(\"" + profileID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             ProfileDatabase database = subsystem.getProfileDatabase();
 
             ProfileRecord record = database.getRecord(profileID);
             String status = record.getStatus();
 
             if (!Constants.CFG_DISABLED.equals(status)) {
-                throw new ForbiddenException("Profile " + profileID + " is not disabled");
+                Exception e = new ForbiddenException("Profile " + profileID + " is not disabled");
+                auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                        auditModParams, e.toString());
+                throw e;
             }
 
             database.removeRecord(profileID);
+            auditTPSProfileChange(ILogger.SUCCESS, method, profileID, null, null);
 
             return createNoContentResponse();
 
         } catch (PKIException e) {
             CMS.debug("ProfileService: " + e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                    auditModParams, e.toString());
             throw e;
 
         } catch (Exception e) {
             CMS.debug(e);
+            auditTPSProfileChange(ILogger.FAILURE, method, profileID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
+
+    /*
+     * Service can be any of the methods offered
+     */
+    public void auditTPSProfileChange(String status, String service, String profileID, Map<String, String> params,
+            String info) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_PROFILE_6",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                profileID,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
+
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
index b3608aef2fff1d12352dc74bce6f89388dffa1ee..cb82a9bf5e9b5019b6ef54df83c05a6b97c9e841 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -50,6 +50,7 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.dbs.EDBException;
 import com.netscape.certsrv.ldap.LDAPExceptionConverter;
+import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.token.TokenCollection;
 import com.netscape.certsrv.tps.token.TokenData;
 import com.netscape.certsrv.tps.token.TokenData.TokenStatusData;
@@ -130,13 +131,22 @@ public class TokenService extends PKIService implements TokenResource {
         return TokenStatus.PERM_LOST;
     }
 
-    public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState, String ipAddress, String remoteUser)
-            throws Exception {
+    public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState, String ipAddress, String remoteUser,
+            Map<String, String> auditModParams)
+                    throws Exception {
         TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
 
+        String oldStatus = tokenRecord.getStatus();
+        String oldReason = tokenRecord.getReason();
+        String newStatus = String.valueOf(tokenState);
+        String newReason = null;
+
+        auditModParams.put("UserID", tokenRecord.getUserID());
+
         switch (tokenState) {
         case UNINITIALIZED:
             tokenRecord.setStatus("uninitialized");
+            newStatus = "uninitialized";
             tokenRecord.setReason(null);
             break;
         case ACTIVE:
@@ -149,19 +159,24 @@ public class TokenService extends PKIService implements TokenResource {
             }
 
             tokenRecord.setStatus("active");
+            newStatus = "active";
             tokenRecord.setReason(null);
             break;
         case PERM_LOST:
         case TEMP_LOST_PERM_LOST:
             tokenRecord.setStatus("lost");
+            newStatus = "lost";
             tokenRecord.setReason("keyCompromise");
+            newReason = "keyCompromise";
 
             //revoke certs
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "keyCompromise", ipAddress, remoteUser);
             break;
         case DAMAGED:
             tokenRecord.setStatus("lost");
+            newStatus = "lost";
             tokenRecord.setReason("destroyed");
+            newReason = "destroyed";
 
             //revoke certs
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "destroyed", ipAddress, remoteUser);
@@ -169,7 +184,9 @@ public class TokenService extends PKIService implements TokenResource {
             break;
         case TEMP_LOST:
             tokenRecord.setStatus("lost");
+            newStatus = "lost";
             tokenRecord.setReason("onHold");
+            newReason = "onHold";
 
             // put certs onHold
             tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "onHold", ipAddress, remoteUser);
@@ -184,15 +201,23 @@ public class TokenService extends PKIService implements TokenResource {
                 reason = "onHold";
             }
             tokenRecord.setStatus("terminated");
+            newStatus = "terminated";
             tokenRecord.setReason(reason);
+            newReason = reason;
 
             //revoke certs
-            tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason, ipAddress, remoteUser) ;
+            tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason, ipAddress, remoteUser);
             break;
         default:
-            throw new PKIException("Unsupported token state: " + tokenState);
+            PKIException e = new PKIException("Unsupported token state: " + tokenState);
+            auditTokenStateChange(ILogger.FAILURE, oldStatus,
+                    newStatus, oldReason, newReason,
+                    auditModParams, e.toString());
+            throw e;
         }
 
+        auditTokenStateChange(ILogger.SUCCESS, oldStatus, newStatus, oldReason, newReason, auditModParams, null);
+
     }
 
     public TokenData createTokenData(TokenRecord tokenRecord) throws Exception {
@@ -256,7 +281,7 @@ public class TokenService extends PKIService implements TokenResource {
         size = size == null ? DEFAULT_SIZE : size;
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
             Iterator<TokenRecord> tokens = database.findRecords(filter).iterator();
@@ -265,24 +290,26 @@ public class TokenService extends PKIService implements TokenResource {
             int i = 0;
 
             // skip to the start of the page
-            for ( ; i<start && tokens.hasNext(); i++) tokens.next();
+            for (; i < start && tokens.hasNext(); i++)
+                tokens.next();
 
             // return entries up to the page size
-            for ( ; i<start+size && tokens.hasNext(); i++) {
+            for (; i < start + size && tokens.hasNext(); i++) {
                 response.addEntry(createTokenData(tokens.next()));
             }
 
             // count the total entries
-            for ( ; tokens.hasNext(); i++) tokens.next();
+            for (; tokens.hasNext(); i++)
+                tokens.next();
             response.setTotal(i);
 
             if (start > 0) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
                 response.addLink(new Link("prev", uri));
             }
 
-            if (start+size < i) {
-                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+            if (start + size < i) {
+                URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
                 response.addLink(new Link("next", uri));
             }
 
@@ -291,7 +318,7 @@ public class TokenService extends PKIService implements TokenResource {
         } catch (EDBException e) {
             Throwable t = e.getCause();
             if (t != null && t instanceof LDAPException) {
-                throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                throw LDAPExceptionConverter.toPKIException((LDAPException) t);
             }
             throw new PKIException(e);
 
@@ -307,12 +334,13 @@ public class TokenService extends PKIService implements TokenResource {
     @Override
     public Response getToken(String tokenID) {
 
-        if (tokenID == null) throw new BadRequestException("Token ID is null.");
+        if (tokenID == null)
+            throw new BadRequestException("Token ID is null.");
 
         CMS.debug("TokenService.getToken(\"" + tokenID + "\")");
 
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+            TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
             return createOKResponse(createTokenData(database.getRecord(tokenID)));
@@ -320,7 +348,7 @@ public class TokenService extends PKIService implements TokenResource {
         } catch (EDBException e) {
             Throwable t = e.getCause();
             if (t != null && t instanceof LDAPException) {
-                throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                throw LDAPExceptionConverter.toPKIException((LDAPException) t);
             }
             throw new PKIException(e);
 
@@ -335,16 +363,25 @@ public class TokenService extends PKIService implements TokenResource {
 
     @Override
     public Response addToken(TokenData tokenData) {
+        String method = "TokenService.addToken";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (tokenData == null) throw new BadRequestException("Token data is null.");
+        if (tokenData == null) {
+            BadRequestException ex = new BadRequestException("Token data is null.");
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    ex.toString());
+            throw ex;
+        }
 
         String tokenID = tokenData.getTokenID();
+        auditModParams.put("tokenID", tokenID);
+
         CMS.debug("TokenService.addToken(\"" + tokenID + "\")");
 
         String remoteUser = servletRequest.getRemoteUser();
         String ipAddress = servletRequest.getRemoteAddr();
 
-        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TokenRecord tokenRecord = null;
         String msg = "add token";
 
@@ -357,20 +394,25 @@ public class TokenService extends PKIService implements TokenResource {
             String userID = tokenData.getUserID();
             if (StringUtils.isNotEmpty(userID)) {
                 tokenRecord.setUserID(userID);
+                auditModParams.put("userID", userID);
             }
 
             String policy = tokenData.getPolicy();
             if (StringUtils.isNotEmpty(policy)) {
                 tokenRecord.setPolicy(policy);
+                auditModParams.put("Policy", policy);
             }
 
             // new tokens are uninitialized when created
             tokenRecord.setStatus("uninitialized");
+            auditModParams.put("Status", "uninitialized");
 
             database.addRecord(tokenID, tokenRecord);
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord,
-                ipAddress, msg, "success", remoteUser);
+                    ipAddress, msg, "success", remoteUser);
             tokenData = createTokenData(database.getRecord(tokenID));
+            auditConfigTokenRecord(ILogger.SUCCESS, method, tokenID,
+                    auditModParams, null);
 
             return createCreatedResponse(tokenData, tokenData.getLink().getHref());
 
@@ -379,35 +421,52 @@ public class TokenService extends PKIService implements TokenResource {
 
             msg = msg + ": " + e.getMessage();
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord,
-                ipAddress, msg, "failure", remoteUser);
+                    ipAddress, msg, "failure", remoteUser);
 
             if (e instanceof EDBException) {
                 Throwable t = e.getCause();
                 if (t != null && t instanceof LDAPException) {
-                    throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                    PKIException ex = LDAPExceptionConverter.toPKIException((LDAPException) t);
+                    auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                            auditModParams, ex.toString());
+                    throw ex;
                 }
             }
 
             if (e instanceof PKIException) {
-                throw (PKIException)e;
+                auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                        auditModParams, e.toString());
+                throw (PKIException) e;
             }
 
+            auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response replaceToken(String tokenID, TokenData tokenData) {
+        String method = "TokenService.replaceToken";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (tokenID == null) throw new BadRequestException("Token ID is null.");
-        if (tokenData == null) throw new BadRequestException("Token data is null.");
+        if (tokenID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Token ID is null.");
+            throw new BadRequestException("Token ID is null.");
+        }
+        if (tokenData == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, auditModParams,
+                    "Token data is null.");
+            throw new BadRequestException("Token data is null.");
+        }
 
         CMS.debug("TokenService.replaceToken(\"" + tokenID + "\")");
 
         String remoteUser = servletRequest.getRemoteUser();
         String ipAddress = servletRequest.getRemoteAddr();
 
-        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TokenRecord tokenRecord = null;
         String msg = "replace token";
         try {
@@ -415,15 +474,22 @@ public class TokenService extends PKIService implements TokenResource {
 
             tokenRecord = database.getRecord(tokenID);
             tokenRecord.setUserID(remoteUser);
+            auditModParams.put("userID", remoteUser);
             tokenRecord.setType(tokenData.getType());
+            auditModParams.put("type", tokenData.getType());
             tokenRecord.setAppletID(tokenData.getAppletID());
+            auditModParams.put("appletID", tokenData.getAppletID());
             tokenRecord.setKeyInfo(tokenData.getKeyInfo());
+            auditModParams.put("keyInfo", tokenData.getKeyInfo());
             tokenRecord.setPolicy(tokenData.getPolicy());
+            auditModParams.put("Policy", tokenData.getPolicy());
             database.updateRecord(tokenID, tokenRecord);
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "success", remoteUser);
+                    ipAddress, msg, "success", remoteUser);
 
             tokenData = createTokenData(database.getRecord(tokenID));
+            auditConfigTokenRecord(ILogger.SUCCESS, method, tokenID,
+                    auditModParams, null);
 
             return createOKResponse(tokenData);
 
@@ -432,36 +498,55 @@ public class TokenService extends PKIService implements TokenResource {
 
             msg = msg + ": " + e.getMessage();
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "failure",
-                remoteUser);
+                    ipAddress, msg, "failure",
+                    remoteUser);
 
             if (e instanceof EDBException) {
                 Throwable t = e.getCause();
                 if (t != null && t instanceof LDAPException) {
-                    throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                    PKIException ex = LDAPExceptionConverter.toPKIException((LDAPException) t);
+                    auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                            auditModParams, ex.toString());
+                    throw ex;
                 }
             }
 
             if (e instanceof PKIException) {
-                throw (PKIException)e;
+                auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                        auditModParams, e.toString());
+                throw (PKIException) e;
             }
 
+            auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response modifyToken(String tokenID, TokenData tokenData) {
+        String method = "TokenService.modifyToken";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (tokenID == null) throw new BadRequestException("Token ID is null.");
-        if (tokenData == null) throw new BadRequestException("Token data is null.");
+        if (tokenID == null) {
+            BadRequestException e = new BadRequestException("Token ID is null.");
+            auditConfigTokenRecord(ILogger.FAILURE, "modify", tokenID,
+                    auditModParams, e.toString());
+            throw e;
+        }
+        if (tokenData == null) {
+            BadRequestException e = new BadRequestException("Token data is null.");
+            auditConfigTokenRecord(ILogger.FAILURE, "modify", tokenID,
+                    auditModParams, e.toString());
+            throw e;
+        }
 
         CMS.debug("TokenService.modifyToken(\"" + tokenID + "\")");
 
         String remoteUser = servletRequest.getRemoteUser();
         String ipAddress = servletRequest.getRemoteAddr();
 
-        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TokenRecord tokenRecord = null;
         String msg = "modify token";
         try {
@@ -477,6 +562,7 @@ public class TokenService extends PKIService implements TokenResource {
                     tokenRecord.setUserID(null);
                 } else { // otherwise replace value
                     tokenRecord.setUserID(userID);
+                    auditModParams.put("userID", userID);
                 }
             }
 
@@ -487,14 +573,17 @@ public class TokenService extends PKIService implements TokenResource {
                     tokenRecord.setPolicy(null);
                 } else { //otherwise replace value
                     tokenRecord.setPolicy(policy);
+                    auditModParams.put("Policy", policy);
                 }
             }
 
             database.updateRecord(tokenID, tokenRecord);
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "success", remoteUser);
+                    ipAddress, msg, "success", remoteUser);
 
             tokenData = createTokenData(database.getRecord(tokenID));
+            auditConfigTokenRecord(ILogger.SUCCESS, method, tokenID,
+                    auditModParams, null);
 
             return createOKResponse(tokenData);
 
@@ -503,36 +592,61 @@ public class TokenService extends PKIService implements TokenResource {
 
             msg = msg + ": " + e.getMessage();
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "failure",
-                remoteUser);
+                    ipAddress, msg, "failure",
+                    remoteUser);
 
             if (e instanceof EDBException) {
                 Throwable t = e.getCause();
                 if (t != null && t instanceof LDAPException) {
-                    throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                    PKIException ex = LDAPExceptionConverter.toPKIException((LDAPException) t);
+                    auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                            auditModParams, ex.toString());
+                    throw ex;
                 }
             }
 
             if (e instanceof PKIException) {
-                throw (PKIException)e;
+                auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                        auditModParams, e.toString());
+                throw (PKIException) e;
             }
 
+            auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response changeTokenStatus(String tokenID, TokenStatus tokenStatus) {
+        String method = "TokenService.changeTokenStatus";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (tokenID == null) throw new BadRequestException("Token ID is null.");
-        if (tokenStatus == null) throw new BadRequestException("Token state is null.");
+        if (tokenID == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Token ID is null.");
+            throw new BadRequestException("Token ID is null.");
+        }
+        auditModParams.put("tokenID", tokenID);
+        if (tokenStatus == null) {
+            auditConfigTokenGeneral(ILogger.FAILURE, method, null,
+                    "Token state is null.");
+            throw new BadRequestException("Token state is null.");
+        }
+        auditModParams.put("tokenStatus", tokenStatus.toString());
 
         CMS.debug("TokenService.changeTokenStatus(\"" + tokenID + "\", \"" + tokenStatus + "\")");
 
         String remoteUser = servletRequest.getRemoteUser();
         String ipAddress = servletRequest.getRemoteAddr();
 
-        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        // for auditing
+        String oldStatus = null;
+        String oldReason = null;
+        String newStatus = null;
+        String newReason = null;
+
         TokenRecord tokenRecord = null;
         String msg = "change token status";
         try {
@@ -542,6 +656,10 @@ public class TokenService extends PKIService implements TokenResource {
             TokenStatus currentTokenStatus = getTokenStatus(tokenRecord);
             CMS.debug("TokenService.changeTokenStatus(): current status: " + currentTokenStatus);
 
+            oldStatus = tokenRecord.getStatus();
+            oldReason = tokenRecord.getReason();
+            newStatus = String.valueOf(tokenStatus);
+
             if (currentTokenStatus == tokenStatus) {
                 CMS.debug("TokenService.changeTokenStatus(): no status change, no activity log generated");
 
@@ -556,15 +674,20 @@ public class TokenService extends PKIService implements TokenResource {
             CMS.debug("TokenService.changeTokenStatus(): allowed next statuses: " + nextStatuses);
             if (nextStatuses == null || !nextStatuses.contains(tokenStatus)) {
                 CMS.debug("TokenService.changeTokenStatus(): next status not allowed: " + tokenStatus);
-                throw new BadRequestException("Invalid token status transition");
+                Exception ex = new BadRequestException("Invalid token status transition");
+                auditTokenStateChange(ILogger.FAILURE, oldStatus,
+                        newStatus, oldReason, newReason,
+                        auditModParams, ex.toString());
+                throw ex;
             }
 
             CMS.debug("TokenService.changeTokenStatus(): next status allowed: " + tokenStatus);
-            setTokenStatus(tokenRecord, tokenStatus, ipAddress, remoteUser);
+            // audit in setTokenStatus()
+            setTokenStatus(tokenRecord, tokenStatus, ipAddress, remoteUser, auditModParams);
             database.updateRecord(tokenID, tokenRecord);
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "success",
-                remoteUser);
+                    ipAddress, msg, "success",
+                    remoteUser);
 
             TokenData tokenData = createTokenData(database.getRecord(tokenID));
 
@@ -575,35 +698,52 @@ public class TokenService extends PKIService implements TokenResource {
 
             msg = msg + ": " + e.getMessage();
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
-                ipAddress, msg, "failure",
-                remoteUser);
+                    ipAddress, msg, "failure",
+                    remoteUser);
 
             if (e instanceof EDBException) {
                 Throwable t = e.getCause();
                 if (t != null && t instanceof LDAPException) {
-                    throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                    PKIException ex = LDAPExceptionConverter.toPKIException((LDAPException) t);
+                    auditTokenStateChange(ILogger.FAILURE, oldStatus,
+                            newStatus, oldReason, newReason,
+                            auditModParams, ex.toString());
+                    throw ex;
                 }
             }
 
             if (e instanceof PKIException) {
-                throw (PKIException)e;
+                auditTokenStateChange(ILogger.FAILURE, oldStatus,
+                        newStatus, oldReason, newReason,
+                        auditModParams, e.toString());
+                throw (PKIException) e;
             }
 
+            auditTokenStateChange(ILogger.FAILURE, oldStatus,
+                    newStatus, oldReason, newReason,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
 
     @Override
     public Response removeToken(String tokenID) {
+        String method = "TokenService.removeToken";
+        Map<String, String> auditModParams = new HashMap<String, String>();
 
-        if (tokenID == null) throw new BadRequestException("Token ID is null.");
+        if (tokenID == null) {
+            BadRequestException ex = new BadRequestException("Token ID is null.");
+            auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                    auditModParams, ex.toString());
+            throw ex;
+        }
 
         CMS.debug("TokenService.removeToken(\"" + tokenID + "\")");
 
         String remoteUser = servletRequest.getRemoteUser();
         String ipAddress = servletRequest.getRemoteAddr();
 
-        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TokenRecord tokenRecord = null;
         String msg = "remove token";
         try {
@@ -615,8 +755,10 @@ public class TokenService extends PKIService implements TokenResource {
             subsystem.tdb.tdbRemoveCertificatesByCUID(tokenRecord.getId());
 
             database.removeRecord(tokenID);
+            auditConfigTokenRecord(ILogger.SUCCESS, method, tokenID,
+                    auditModParams, null);
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DELETE, tokenRecord,
-                ipAddress, msg, "success", remoteUser);
+                    ipAddress, msg, "success", remoteUser);
 
             return createNoContentResponse();
 
@@ -625,21 +767,66 @@ public class TokenService extends PKIService implements TokenResource {
 
             msg = msg + ": " + e.getMessage();
             subsystem.tdb.tdbActivity(ActivityDatabase.OP_DELETE, tokenRecord,
-                ipAddress, msg, "failure",
-                remoteUser);
+                    ipAddress, msg, "failure",
+                    remoteUser);
 
             if (e instanceof EDBException) {
                 Throwable t = e.getCause();
                 if (t != null && t instanceof LDAPException) {
-                    throw LDAPExceptionConverter.toPKIException((LDAPException)t);
+                    PKIException ex = LDAPExceptionConverter.toPKIException((LDAPException) t);
+                    auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                            auditModParams, ex.toString());
+                    throw ex;
                 }
             }
 
             if (e instanceof PKIException) {
-                throw (PKIException)e;
+                auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                        auditModParams, e.toString());
+                throw (PKIException) e;
             }
 
+            auditConfigTokenRecord(ILogger.FAILURE, method, tokenID,
+                    auditModParams, e.toString());
             throw new PKIException(e);
         }
     }
+
+    /*
+     * Service can be any of the methods offered
+     */
+    public void auditConfigTokenRecord(String status, String service, String tokenID, Map<String, String> params,
+            String info) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_CONFIG_TOKEN_RECORD_6",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                service,
+                tokenID,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
+
+    /*
+     *
+     */
+    public void auditTokenStateChange(String status, String oldState, String newState, String oldReason,
+            String newReason, Map<String, String> params, String info) {
+
+        String msg = CMS.getLogMessage(
+                "LOGGING_SIGNED_AUDIT_TOKEN_STATE_CHANGE_8",
+                servletRequest.getUserPrincipal().getName(),
+                status,
+                oldState,
+                oldReason,
+                newState,
+                newReason,
+                auditor.getParamString(null, params),
+                info);
+        auditor.log(msg);
+
+    }
 }
-- 
2.4.3

