diff --git a/content/api/enterprise-api-ref/audit-logs-api.markdown b/content/api/enterprise-api-ref/audit-logs-api.markdown index 4106820c4..41678d40b 100644 --- a/content/api/enterprise-api-ref/audit-logs-api.markdown +++ b/content/api/enterprise-api-ref/audit-logs-api.markdown @@ -207,3 +207,20 @@ HTTP 200 OK "Authentication", ] ``` + +## Permissions + +All Audit log API endpoints require the `audit-log.view` RBAC permission. This +permission is granted to the `admin` role by default and can be assigned to +other roles via the [Web RBAC API](/api/enterprise-api-ref/web-rbac/). + +## Retention + +Audit log entries are stored in the `audit_log` table of the `cfsettings` +PostgreSQL database (see the +[schema reference](/api/enterprise-api-ref/sql-schema/cfsettings/)) and are retained +indefinitely. No automatic pruning is performed. + +Operators are expected to apply their own retention policy. See +[Audit log retention](/web-ui/hub_administration/audit-log-retention/) +for inspection queries and pruning recipes. diff --git a/content/api/enterprise-api-ref/sql-schema/cfsettings.markdown b/content/api/enterprise-api-ref/sql-schema/cfsettings.markdown index e35a73511..483b411d9 100644 --- a/content/api/enterprise-api-ref/sql-schema/cfsettings.markdown +++ b/content/api/enterprise-api-ref/sql-schema/cfsettings.markdown @@ -7,7 +7,7 @@ aliases: Settings used by Mission Portal APIs, no reported data. -## Table: audit_logs +## Table: audit_log Stores system logs about actions performed by users. @@ -17,15 +17,19 @@ Stores system logs about actions performed by users. The unique identifier of audit log event, generated from a sequence. - **time** _(timestamp without a time zone)_ Time when an event happened. -- **action** _(text)_ - What was done (e.g., updated, created, deleted, deployed). -- **object_type** _(text)_ - Type of affected object (e.g., user, role, build project). +- **actor** _(text, not null)_ + User who performed the action. +- **action** _(audit_log_action enum, not null)_ + What was done. +- **object_type** _(audit_log_object_type enum, not null)_ + Type of affected object. - **object_id** _(text)_ Identifier of an affected object (e.g. user, role id, build project id), if applicable. -- **details** _(json)_ +- **object_name** _(text)_ + Name of the affected object (e.g. user name, role name, settings name). +- **details** _(jsonb)_ More details in the free-json format. -- **ip_address** _(boolean)_ +- **ip_address** _(inet)_ IP address of the user who performed the action. ## Table: build_modules diff --git a/content/web-ui/_index.markdown b/content/web-ui/_index.markdown index aa9a90e0e..c4ec001df 100644 --- a/content/web-ui/_index.markdown +++ b/content/web-ui/_index.markdown @@ -92,6 +92,35 @@ All Events can be searched and viewed from the Event Log page. Mission Portal - Events View whole system events RBAC page +### Audit log + +The Audit log records administrative actions performed in Mission Portal — for +example user, role, and settings changes, host and group edits, Build project +changes, and federated reporting configuration. Each entry captures the actor, +action, affected object, timestamp, and originating IP address. + +The Audit log is distinct from the Event log: the Event log tracks +_system events_ like host bootstraps and alert state changes, while the Audit +log tracks _human actions_ against the administrative surface. + +- Entries are queryable via the [Audit log API](/api/enterprise-api-ref/audit-logs-api/). +- Viewing the Audit log requires the `audit-log.view` RBAC permission (granted to `admin` by default). +- Entries are stored in the `audit_log` table of the `cfsettings` database and + are retained indefinitely unless pruned. See + [Audit log retention](/web-ui/hub_administration/audit-log-retention/) for + guidance on inspecting and managing table growth. + +![](images/audit-log.png) + +The log can be filtered by date range, actor, object type, and object +name to narrow down to specific activity. +Each row links to a detail view showing the full activity record and any +structured details captured for the action. For example, the configuration +fields changed in a settings update or the values associated with a created +object. + +![](images/audit-log-entry.png) + ### Newly bootstrapped hosts widget The Newly bootstrapped hosts widget helps to visualize the number of hosts bootstrapped to CFEngine over time. diff --git a/content/web-ui/hub_administration/audit-log-retention.markdown b/content/web-ui/hub_administration/audit-log-retention.markdown new file mode 100644 index 000000000..28ef7b068 --- /dev/null +++ b/content/web-ui/hub_administration/audit-log-retention.markdown @@ -0,0 +1,81 @@ +--- +layout: default +title: Audit log retention +aliases: + - "/web-ui-hub_administration-audit-log-retention.html" +--- + +The Mission Portal [Audit log API](/api/enterprise-api-ref/audit-logs-api/) +records administrative actions (user, role, settings, host, group, Build +project, and federated reporting changes) in the `audit_log` table of the +`cfsettings` PostgreSQL database. + +## Default retention + +There is no automatic purging of audit log entries. Records are kept +indefinitely until manually removed. + +This is intentional for compliance use cases where a long, complete history is +desirable, but it means the `audit_log` table will grow without bound on +long-running hubs. Operators are expected to apply their own retention policy. + +## Inspecting current size + +To see how many entries you have and how old they are: + +```console +sudo -u cfpostgres /var/cfengine/bin/psql cfsettings -c \ + "SELECT count(*) AS rows, + min(time) AS oldest, + max(time) AS newest, + pg_size_pretty(pg_total_relation_size('audit_log')) AS size + FROM audit_log;" +``` + +## Manually pruning old entries + +To delete entries older than a chosen number of days, run as the `cfpostgres` +user on the hub: + +```console +sudo -u cfpostgres /var/cfengine/bin/psql cfsettings -c \ + "DELETE FROM audit_log WHERE time < NOW() - INTERVAL '180 days';" +``` + +The `idx_audit_log_timestamp` index ensures this is efficient even on large +tables. Adjust the interval to match your retention policy (regulatory +requirements often dictate 1, 3, or 7 years). + +## Scheduling pruning with CFEngine policy + +Deletion of old records can be accomplished via policy using a `commands` promise. For example: + +```cf3 +bundle agent audit_log_retention +# @brief Prune Mission Portal audit_log entries older than $(days) days +{ + vars: + "days" string => "365"; + + commands: + policy_server:: + "$(sys.bindir)/psql" + args => "cfsettings -c \"DELETE FROM audit_log WHERE time < NOW() - INTERVAL '$(days) day';\"", + contain => in_shell_and_silent, + action => if_elapsed_day, + handle => "audit_log_retention_prune", + comment => "Prune Mission Portal audit_log entries older than $(days) days"; +} +``` + +## RBAC + +Viewing the Audit log in Mission Portal or via the API requires the +`audit-log.view` RBAC permission, granted to the `admin` role by default. + +## See also + +- [Audit log API](/api/enterprise-api-ref/audit-logs-api/) — query the log programmatically +- [Database schema: `audit_log`](/api/enterprise-api-ref/sql-schema/cfsettings/) — column reference +- [Event log](/web-ui/#event-log) — a separate, automatically-pruned log of host + bootstraps, decommissions, and alert state changes diff --git a/content/web-ui/images/audit-log-entry.png b/content/web-ui/images/audit-log-entry.png new file mode 100644 index 000000000..276ee3f8b Binary files /dev/null and b/content/web-ui/images/audit-log-entry.png differ diff --git a/content/web-ui/images/audit-log.png b/content/web-ui/images/audit-log.png new file mode 100644 index 000000000..b6130745b Binary files /dev/null and b/content/web-ui/images/audit-log.png differ