Auditing Your Deployment

For information about the IG audit framework, see Audit Framework. The following sections describe how to set up auditing for your deployment:

For more information about each event handler, see Audit Framework.

Recording Access Audit Events in CSV

This section describes how to record access audit events in a CSV file. For information about the CSV audit event handler, see CsvAuditEventHandler.

The CSV handler does not sanitize messages when writing to CSV log files.

Do not open CSV logs in spreadsheets or other applications that treat data as code.

Before you start, prepare IG and the sample application as described in the Getting Started.

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/30-csv.json
    appdata\OpenIG\config\routes\30-csv.json
    {
      "name": "30-csv",
      "baseURI": "http://app.example.com:8081",
      "condition": "${matches(request.uri.path, '^/home/csv-audit')}",
      "heap": [
        {
          "name": "AuditService",
          "type": "AuditService",
          "config": {
            "eventHandlers": [
              {
                "class": "org.forgerock.audit.handlers.csv.CsvAuditEventHandler",
                "config": {
                  "name": "csv",
                  "logDirectory": "/tmp/logs",
                  "buffering": {
                    "enabled": "true",
                    "autoFlush": "true"
                  },
                  "topics": [
                    "access"
                  ]
                }
              }
            ],
            "config": { }
          }
        }
      ],
      "auditService": "AuditService",
      "handler": "ForgeRockClientHandler"
    }

    The route calls an audit service configuration for publishing log messages to the CSV file, /tmp/logs/access.csv.

  2. When a request matches audit, audit events are logged to the CSV file.

    The route uses the ForgeRockClientHandler as its handler, to send the X-ForgeRock-TransactionId header with its requests to external services.

  3. Go to http://openig.example.com:8080/home/csv-audit.

    The home page of the sample application is displayed, and the file /tmp/logs/access.csv is updated.

Recording Access Audit Events With a JMS Audit Event Handler

This procedure is an example of how to record access audit events with a JMS audit event handler configured to use the ActiveMQ message broker. This example is not tested on all configurations, and can be more or less relevant to your configuration.

For information about configuring the JMS event handler, see JmsAuditEventHandler.

Before you start, prepare IG as described in the Getting Started.

  1. Download the following files:

  2. Add the files to the configuration:

    • For IG in standalone mode, create the directory $HOME/.openig/extra, where $HOME/.openig is the instance directory, and add .jar files to the directory.

    • For IG in web container mode, add .jar files to the web container classpath. For example, in Jetty use /path/to/jetty/webapps/ROOT/WEB-INF/lib.

  3. Create a consumer that subscribes to the audit topic.

    From the ActiveMQ installation directory, run the following command:

    $ ./bin/activemq consumer --destination topic://audit
  4. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/30-jms.json
    appdata\OpenIG\config\routes\30-jms.json
    {
      "name": "30-jms",
      "MyCapture" : "all",
      "baseURI": "http://app.example.com:8081",
      "condition" : "${request.uri.path == '/activemq_event_handler'}",
      "heap": [
        {
          "name": "AuditService",
          "type": "AuditService",
          "config": {
            "eventHandlers" : [
              {
                "class" : "org.forgerock.audit.handlers.jms.JmsAuditEventHandler",
                "config" : {
                  "name" : "jms",
                  "topics": [ "access" ],
                  "deliveryMode" : "NON_PERSISTENT",
                  "sessionMode" : "AUTO",
                  "jndi" : {
                    "contextProperties" : {
                      "java.naming.factory.initial" : "org.apache.activemq.jndi.ActiveMQInitialContextFactory",
                      "java.naming.provider.url" : "tcp://openam.example.com:61616",
                      "topic.audit" : "audit"
                    },
                    "topicName" : "audit",
                    "connectionFactoryName" : "ConnectionFactory"
                  }
                }
              }
            ],
            "config" : { }
          }
        }
      ],
      "auditService": "AuditService",
      "handler" : {
        "type" : "StaticResponseHandler",
        "config" : {
          "status" : 200,
          "headers" : {
            "Content-Type" : [ "text/plain" ]
          },
          "reason" : "found",
          "entity" : "Message from audited route"
        }
      }
    }

    When a request matches the /activemq_event_handler route, this configuration publishes JMS messages containing audit event data to an ActiveMQ managed JMS topic, and the StaticResponseHandler displays a message.

  5. Access the route on http://openig.example.com:8080/activemq_event_handler.

    Depending on how ActiveMQ is configured, audit events are displayed on the ActiveMQ console or written to file.

Recording Access Audit Events With a JSON Audit Event Handler

This section describes how to record access audit events with a JSON audit event handler. For information about configuring the JSON event handler, see JsonAuditEventHandler.

Record Audit Events With a JSON Audit Event Handler
  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/30-json.json
    appdata\OpenIG\config\routes\30-json.json
    {
      "name": "30-json",
      "baseURI": "http://app.example.com:8081",
      "condition": "${matches(request.uri.path, '^/home/json-audit')}",
      "heap": [
        {
          "name": "AuditService",
          "type": "AuditService",
          "config": {
            "eventHandlers": [
              {
                "class": "org.forgerock.audit.handlers.json.JsonAuditEventHandler",
                "config": {
                  "name": "json",
                  "logDirectory": "/tmp/logs",
                  "topics": [
                    "access"
                  ],
                  "buffering": {
                    "maxSize": 100000,
                    "writeInterval": "100 ms"
                  },
                  "rotationRetentionCheckInterval": "1 m"
                }
              }
            ]
          }
        }
      ],
      "auditService": "AuditService",
      "handler": "ReverseProxyHandler"
    }

    Notice the following features of the route:

    • The route calls an audit service configuration for publishing log messages to the JSON file, /tmp/audit/access.audit.json. When a request matches /home/json-audit, a single line per audit event is logged to the JSON file.

    • The route uses the ForgeRockClientHandler as its handler, to send the X-ForgeRock-TransactionId header with its requests to external services.

  2. Go to http://openig.example.com:8080/home/json-audit.

    The home page of the sample application is displayed and the file /tmp/logs/access.audit.json is created or updated with a message. The following example message is formatted for easy reading, but it is produced as a single line for each event:

    {
      "_id": "830...-41",
      "timestamp": "2019-...540Z",
      "eventName": "OPENIG-HTTP-ACCESS",
      "transactionId": "830...-40",
      "client": {
        "ip": "0:0:0:0:0:0:0:1",
        "port": 51666
      },
      "server": {
        "ip": "0:0:0:0:0:0:0:1",
        "port": 8080
      },
      "http": {
        "request": {
          "secure": false,
          "method": "GET",
          "path": "http://openig.example.com:8080/home/json-audit",
          "headers": {
            "accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],
            "host": ["{gatewayUrl}:8080"],
            "user-agent": ["Mozilla/5.0 ... Firefox/66.0"]
          }
        }
      },
      "response": {
        "status": "SUCCESSFUL",
        "statusCode": "200",
        "elapsedTime": 212,
        "elapsedTimeUnits": "MILLISECONDS"
      }
    }

Recording Access Audit Events to Standard Output

This section describes how to record access audit events to standard output. For more information about the event handler, see JsonStdoutAuditEventHandler.

Before you start, prepare IG and the sample application as described in the Getting Started.

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/30-jsonstdout.json
    appdata\OpenIG\config\routes\30-jsonstdout.json
    {
      "name": "30-jsonstdout",
      "baseURI": "http://app.example.com:8081",
      "condition": "${matches(request.uri.path, '^/home/jsonstdout-audit')}",
      "heap": [
        {
          "name": "AuditService",
          "type": "AuditService",
          "config": {
            "eventHandlers": [
              {
                "class": "org.forgerock.audit.handlers.json.stdout.JsonStdoutAuditEventHandler",
                "config": {
                  "name": "jsonstdout",
                  "elasticsearchCompatible": false,
                  "topics": [
                    "access"
                  ]
                }
              }
            ],
            "config": {}
          }
        }
      ],
      "auditService": "AuditService",
      "handler": "ReverseProxyHandler"
    }

    Notice the following features of the route:

    • The route matches requests to /home/jsonstdout-audit.

    • The route calls the audit service configuration for publishing access log messages to standard output. When a request matches /home/jsonstdout-audit, a single line per audit event is logged.

Test the Setup
  1. Go to http://openig.example.com:8080/home/jsonstdout-audit.

    The home page of the sample application is displayed, and a message like this is published to standard output:

    {
      "_id": "830...-61",
      "timestamp": "2019-...89Z",
      "eventName": "OPENIG-HTTP-ACCESS",
      "transactionId": "830...-60",
      "client": {
        "ip": "0:0:0:0:0:0:0:1",
        "port": 51876
      },
      "server": {
        "ip": "0:0:0:0:0:0:0:1",
        "port": 8080
      },
      "http": {
        "request": {
          "secure": false,
          "method": "GET",
          "path": "http://openig.example.com:8080/home/jsonstdout-audit",
          "headers": {
            "accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],
            "host": ["{gatewayUrl}:8080"],
            "user-agent": ["Mozilla/5.0 ... Firefox/66.0"]
          }
        }
      },
      "response": {
        "status": "SUCCESSFUL",
        "statusCode": "200",
        "elapsedTime": 10,
        "elapsedTimeUnits": "MILLISECONDS"
      },
      "source": "audit",
      "topic": "access",
      "level": "INFO"
    }

Trusting Transaction IDs From Other Products

Each audit event is identified by a unique transaction ID that can be communicated across products and recorded for each local event. By using the transaction ID, requests can be tracked as they traverse the platform, making it easier to monitor activity and to enrich reports.

The X-ForgeRock-TransactionId header is automatically set in all outgoing HTTP calls from one ForgeRock product to another. Customers can also set this header themselves from their own applications or scripts that call into the ForgeRock Identity Platform.

To reduce the risk of malicious attacks, by default IG does not trust transaction ID headers from client applications.

If you trust the transaction IDs sent by your client applications, consider setting Java system property org.forgerock.http.TrustTransactionHeader to true. All incoming X-ForgeRock-TransactionId headers are trusted, and monitoring or reporting systems that consume the logs can allow requests to be correlated as they traverse multiple servers:

  • When IG is running in standalone mode, add the following system property in env.sh:

    # Specify a JVM option
    TX_HEADER_OPT="-Dorg.forgerock.http.TrustTransactionHeader=true"
    
    # Include it into the JAVA_OPTS environment variable
    export JAVA_OPTS="${TX_HEADER_OPT}"
  • When IG is running in web container mode, set a Java system property. For information, see the container documentation.

Safelisting Audit Event Fields for the Logs

To prevent logging of sensitive data for an audit event, the Common Audit Framework uses a safelist to specify which audit event fields appear in the logs.

By default, only safelisted audit event fields are included in the logs. For information about how to include non-safelisted audit event fields, or exclude safelisted audit event fields, see Including or Excluding Audit Event Fields In Logs.

Audit event fields use JSON pointer notation, and are taken from the JSON schema for the audit event content. The following event fields are safelisted:

  • /_id

  • /timestamp

  • /eventName

  • /transactionId

  • /trackingIds

  • /userId

  • /client

  • /server

  • /http/request/secure

  • /http/request/method

  • /http/request/path

  • /http/request/headers/accept

  • /http/request/headers/accept-api-version

  • /http/request/headers/content-type

  • /http/request/headers/host

  • /http/request/headers/user-agent

  • /http/request/headers/x-forwarded-for

  • /http/request/headers/x-forwarded-host

  • /http/request/headers/x-forwarded-port

  • /http/request/headers/x-forwarded-proto

  • /http/request/headers/x-original-uri

  • /http/request/headers/x-real-ip

  • /http/request/headers/x-request-id

  • /http/request/headers/x-requested-with

  • /http/request/headers/x-scheme

  • /request

  • /response

Including or Excluding Audit Event Fields In Logs

The safelist is designed to prevent logging of sensitive data for audit events by specifying which audit event fields appear in the logs. You can add or remove messages from the logs as follows:

  • To include audit event fields in logs that are not safelisted, configure the includeIf property of AuditService.

    Before you include non-safelisted audit event fields in the logs, consider the impact on security. Including some headers, query parameters, or cookies in the logs could cause credentials or tokens to be logged, and allow anyone with access to the logs to impersonate the holder of these credentials or tokens.
  • To exclude safelisted audit event fields from the logs, configure the excludeIf property of AuditService. For an example, see Exclude Safelisted Audit Event Fields From Logs.

Exclude Safelisted Audit Event Fields From Logs
  1. Set up recording for audit events, as described in Recording Access Audit Events in JSON, and note the audit event fields in the log file access.audit.json.

  2. Replace the route 30-json.json with the following route:

    {
      "name": "30-json-excludeif",
      "baseURI": "http://app.example.com:8081",
      "condition": "${matches(request.uri.path, '^/home/json-audit-excludeif$')}",
      "heap": [
        {
          "name": "AuditService",
          "type": "AuditService",
          "config": {
            "config": {
              "filterPolicies": {
                "field": {
                  "excludeIf": [
                    "/access/http/request/headers/host",
                    "/access/http/request/path",
                    "/access/server",
                    "/access/response"
                  ]
                }
              }
            },
            "eventHandlers": [
              {
                "class": "org.forgerock.audit.handlers.json.JsonAuditEventHandler",
                "config": {
                  "name": "json",
                  "logDirectory": "/tmp/logs",
                  "topics": [
                    "access"
                  ],
                  "buffering": {
                    "maxSize": 100000,
                    "writeInterval": "100 ms"
                  },
                  "rotationRetentionCheckInterval": "1 m"
                }
              }
            ]
          }
        }
      ],
      "auditService": "AuditService",
      "handler": "ReverseProxyHandler"
    }

    Notice that the AuditService is configured with an excludeIf property to exclude audit event fields from the logs.

  3. Go to http://openig.example.com:8080/home/json-audit-excludeif.

    The home page of the sample application is displayed and the file /tmp/logs/access.audit.json is updated:

    {
      "_id": "830...-41",
      "timestamp": "2019-...540Z",
      "eventName": "OPENIG-HTTP-ACCESS",
      "transactionId": "830...-40",
      "client": {
        "ip": "0:0:0:0:0:0:0:1",
        "port": 51666
      },
      "http": {
        "request": {
          "secure": false,
          "method": "GET",
          "headers": {
            "accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],
            "user-agent": ["Mozilla/5.0 ... Firefox/66.0"]
          }
        }
      }
    }
  4. Compare the audit event fields in access.audit.json with those produced in Recording Access Audit Events in JSON, and note that the audit event fields specified by the excludeIf property no longer appear in the logs.