Skip to content

Fortified IDDocs

Enable Audit after an upgrade

Step-by-step guide to adding the Audit configuration to a Control installation upgraded from 1.3.0 or earlier.

A new Control installation comes with Audit already configured. An upgrade replaces the Control software but keeps your existing configuration, so the configuration files that enable Audit are not added. This page describes what to add so that Audit works after you upgrade from Control 1.3.0 or earlier.

Control 1.4.0 and later adds three module files to config/modules/. An upgraded installation does not have them:

File Module Purpose
jdbc.json JdbcClient The database where audit events are stored. The default is an embedded HSQLDB database.
audit.json Audit Collects audit events from Flows, Schedules and API calls, and serves the audit UI and REST API at /control/audit.
shell.json Control Hosts the Control web application, with the tabs Launchpad and Audit.

Only users with the auditor role can see and use Audit.

  • Control has been upgraded to 1.4.0 or later.
  • You can edit the configuration directory of the installation, <installation path>/config. The installation path depends on the operating system and how Control was installed. For containers, this is the directory you mount to /opt/fortified/servers/control-server/config. See Container.
  • Your config/config.json includes all files in config/modules/, for example "modules": "@include:modules/*.json". If your installation lists its modules in another way, add the new modules there instead.
  • For LDAP enrichment (step 3): an LdapClient module is already configured for the directory that your pipes write to.
  1. Add a database for the audit trail.

    Create config/modules/jdbc.json. The example below matches a new installation and stores the audit trail in an embedded HSQLDB database in data/auditdb, relative to the installation directory:

    {
    "name": "JdbcClient",
    "config": {
    "jdbc": {
    "url": "jdbc:hsqldb:file:data/auditdb",
    "username": "SA",
    "password": ""
    },
    "migrations": {
    "locations": ["classpath:db/migration/audit"],
    "schemas": ["AUDIT"]
    }
    }
    }

    migrations creates and updates the audit tables in the AUDIT schema when Control starts. Keep locations exactly as shown.

    If the installation already has a JdbcClient module, for example for your own pipes, do not add a second default instance. Add migrations to the existing module instead, or give the new module its own name and refer to it from jdbc.destination in audit.json (step 2).

  2. Add the Audit module.

    Create config/modules/audit.json:

    {
    "name": "Audit",
    "config": {
    "http_listener": "default",
    "http_context": "/control",
    "context_path": "/audit",
    "jdbc": {
    "schema": "AUDIT"
    },
    "requires_any_role": ["auditor"]
    }
    }
    Property Why it is needed
    http_listener Use the same HTTP listener as the Forms module. If your Forms module uses http_port instead, set the same http_port here.
    http_context Must be /control, the same as Forms. The audit UI then shares the Control login session, and users do not have to log in again.
    context_path Serves the audit UI at /control/audit and the REST API at /control/audit/api.
    jdbc.schema Must match the schema in migrations.schemas in jdbc.json.
    requires_any_role Only users with the auditor role get access to the UI and the REST API. Without this property, anyone who can reach the URL can read the audit trail.

    All properties are described in Audit.

  3. Optional: show names instead of LDAP DNs.

    Without enrichment, the audit trail shows LDAP changes with DNs and attribute names. To show names, and to attribute group membership changes to the person who was added or removed rather than to the group, add enrichment to audit.json:

    {
    "name": "Audit",
    "config": {
    "http_listener": "default",
    "http_context": "/control",
    "context_path": "/audit",
    "jdbc": {
    "schema": "AUDIT"
    },
    "enrichment": {
    "ldap": {
    "object_types": {
    "user": {
    "display_name_attributes": ["displayName", "cn"]
    },
    "group": {
    "display_name_attributes": ["displayName", "cn"],
    "reference_attributes": {
    "member": {
    "value_object_type": "user",
    "identity_bearing": true
    }
    }
    }
    }
    }
    },
    "requires_any_role": ["auditor"]
    }
    }

    The names under object_types must be user and group, which are the object types that the LDAP valves report. Change display_name_attributes to match your directory. The first attribute that has a value is used. Enrichment reads from the same LdapClient destination that made the change.

  4. Add the Control application with the Audit tab.

    Create config/modules/shell.json:

    {
    "name": "Control",
    "config": {
    "http_listener": "default",
    "http_context": "/control",
    "tabs": [
    {
    "id": "launchpad",
    "label": "Launchpad",
    "order": 0,
    "default": true,
    "public": true
    },
    {
    "id": "audit",
    "label": "Audit",
    "order": 1,
    "requires_any_role": ["auditor"]
    }
    ]
    }
    }

    Use the same http_listener (or http_port) and http_context as in audit.json. Keep the tab's requires_any_role the same as the Audit module's requires_any_role, so that the tab is shown only to users who can open it.

  5. Give the auditor role to the users who need it.

    Control reads roles from the login and stores them in the session, the same way as for role-based access to Flows. Make sure your identity provider or authenticator sends the role auditor to users who should have access to Audit, for example HR, support or auditors.

    If you want to use a role you already have instead, such as admin, change requires_any_role in both audit.json and shell.json. To give access without any role, see Turn off the role requirement.

  6. Restart Control.

    The audit tables are created at startup. Events are recorded from that point. Changes made before the upgrade are not in the audit trail.

By default, only users with the auditor role can use Audit. If every logged-in user should have access, for example in a test environment, remove the role requirement.

  1. Remove the role requirement from the Audit module.

    In config/modules/audit.json, delete the requires_any_role line (and requires_all_roles, if present):

    {
    "name": "Audit",
    "config": {
    "http_listener": "default",
    "http_context": "/control",
    "context_path": "/audit",
    "jdbc": {
    "schema": "AUDIT"
    }
    }
    }
  2. Remove the role requirement from the Audit tab.

    In config/modules/shell.json, delete requires_any_role from the audit tab:

    {
    "id": "audit",
    "label": "Audit",
    "order": 1
    }

    Every logged-in user now sees the Audit tab. Users who are not logged in do not see it, unless you also add "public": true to the tab. Do not add public unless Audit should be available without login.

  3. Restart Control.

To turn the role requirement back on, add requires_any_role again in both files, with the same roles in each.

  1. Check server.log for errors from the JdbcClient and Audit modules at startup, for example a failed database connection or migration.
  2. Run a Flow, a Schedule or an API call that makes a change, for example an LDAP update.
  3. Log in to Control with a user who has the auditor role. The tabs Launchpad and Audit are shown.
  4. Open the Audit tab, or go to https://<host>/control/audit. The change from step 2 is listed.
  5. Log in with a user who does not have the auditor role. The Audit tab is not shown, and /control/audit returns 403 Forbidden.
  • The Audit tab is not shown. Check that the user has the role in requires_any_role in shell.json, and that shell.json is included by config.json.
  • /control/audit returns 403. The user is logged in but does not have a role in the Audit module's requires_any_role.
  • The Audit module does not start, and server.log says that requires_any_role "did not resolve to any role names". The property is set to an empty list or an invalid value. Remove it, or list at least one role.
  • The Audit tab is not shown to anyone, although the role requirement is turned off. requires_any_role for the tab in shell.json is set to an empty list instead of being removed.
  • The user must log in again to open Audit, or the tab is empty. http_context or the HTTP listener/port in audit.json or shell.json does not match the Forms module.
  • Changes are shown as DNs instead of names. Check enrichment in step 3. The object types must be user and group. If the entry has been deleted or the directory is unreachable, the change is still recorded, but without names.
  • The audit trail is empty after a container restart. The data directory is not on a persistent volume. See the warning in step 1.