diff --git a/_install-and-configure/configuring-opensearch/security-settings.md b/_install-and-configure/configuring-opensearch/security-settings.md index d36e20ac4f..f30c5209fd 100644 --- a/_install-and-configure/configuring-opensearch/security-settings.md +++ b/_install-and-configure/configuring-opensearch/security-settings.md @@ -205,6 +205,14 @@ The Security plugin supports the following audit log settings: - `plugins.security.audit.config.cert_alias` (Static): An alias to the certificate used for audit log access. +- `plugins.security.audit.config.body_logging_exclusions` (Dynamic): A list of action group names or raw action/path patterns for which request body logging is suppressed. Default is `[]` (empty, log all bodies). See [Body logging exclusions]({{site.url}}{{site.baseurl}}/security/audit-logs/index/#body-logging-exclusions) for details. + +- `plugins.security.audit.config.action_groups.` (Static): Defines named groups of action/path patterns for use with `body_logging_exclusions`. Each group is a comma-separated string of transport action patterns and/or REST paths. Supports wildcards. + +- `plugins.security.audit.config.log4j.enable_mdc_routing` (Static): Enables MDC (Mapped Diagnostic Context) routing for the Log4j audit sink. When enabled, audit events set MDC keys (`audit_category`, `audit_action`, `audit_user`, `audit_request_type`) that can be used by Log4j routing appenders. Default is `false`. + +- `plugins.security.audit.enable_standalone` (Static): Enables standalone audit logging mode for clusters running without fine-grained access control (SSL-only or security-disabled modes). Must be set to `true` alongside `plugins.security.audit.type` to activate standalone audit. Default is `false`. + - `plugins.security.audit.config.pemkey_filepath` (Static): The `/config` relative file path to the Privacy Enhanced Mail (PEM) key used for audit logging. - `plugins.security.audit.config.pemkey_content` (Static): The Base64-encoded content of the PEM key used for audit logging. This is an alternative to `...config.pemkey_filepath`. @@ -237,6 +245,8 @@ The Security plugin supports the following audit log settings: - `opendistro_security.audit.config.disabled_transport_categories` (Dynamic): A list of transport layer categories to be ignored by the logger. Valid values are `AUTHENTICATED` and `GRANTED_PRIVILEGES`. +The dynamic audit filter settings and all `plugins.security.audit.compliance.*` settings are marked with `Setting.Property.Sensitive`. This means only security admin users can view or modify their values via the cluster settings API; values are masked for non-admin users. The `plugins.security.audit.config.body_logging_exclusions` and `plugins.security.audit.config.action_groups.` settings are exceptions and are not marked sensitive. + ## Hostname verification and DNS lookup settings The Security plugin supports the following hostname verification and DNS lookup settings: diff --git a/_security/audit-logs/index.md b/_security/audit-logs/index.md index 4a11130d21..4476a22bdb 100644 --- a/_security/audit-logs/index.md +++ b/_security/audit-logs/index.md @@ -26,6 +26,13 @@ redirect_from: Audit logs let you track access to your OpenSearch cluster and are useful for compliance purposes or in the aftermath of a security breach. You can configure the categories to be logged, the detail level of the logged messages, and where to store the logs. +OpenSearch supports two audit logging modes: + +- **Standard mode** (default): Requires the Security plugin with fine-grained access control (FGAC) enabled. Configuration is managed through the `audit.yml` file in the security index and the REST API. +- **Standalone mode**: Works without FGAC---in SSL-only mode (`plugins.security.ssl_only: true`) or with security disabled (`plugins.security.disabled: true`). Configuration is managed entirely through `opensearch.yml` and dynamic cluster settings. See [Standalone audit logging]({{site.url}}{{site.baseurl}}/security/audit-logs/standalone/) for details. + +### Enabling audit logging (standard mode) + Audit logging is disabled by default. To enable audit logging: 1. Add the following line to `opensearch.yml` on each node: @@ -39,9 +46,7 @@ Audit logging is disabled by default. To enable audit logging: 2. Restart each node. -After this initial setup, you can use OpenSearch Dashboards to manage your audit log categories and other settings. In OpenSearch Dashboards, select **Security** and then **Audit logs**. - -An alternative is to specify initial settings for audit logging in the `audit.yml` and `opensearch.yml` files (which file depends on the setting---see [Audit log settings](#audit-log-settings)). Thereafter, you can use Dashboards or the [Audit logs]({{site.url}}{{site.baseurl}}/security/access-control/api/#audit-logs) API to manage and update settings. +After this initial setup, you can specify settings for audit logging in the `audit.yml` and `opensearch.yml` files (which file depends on the setting---see [Audit log settings](#audit-log-settings)). You can also use the [Audit logs]({{site.url}}{{site.baseurl}}/security/access-control/api/#audit-logs) API to manage and update settings. ## Tracked events @@ -59,6 +64,11 @@ Event | Logged on REST | Logged on transport | Description `BAD_HEADERS` | Yes | Yes | An attempt was made to spoof a request to OpenSearch with the Security plugin internal headers. `CLUSTER_SETTINGS_CHANGED` | No | Yes | A persistent or transient cluster setting was changed. Disabled by default. `INDEX_SETTINGS_CHANGED` | No | Yes | An index setting was changed. Disabled by default. +`REQUEST_AUDIT` | Yes | No | A REST-layer request was received and processed. Generated in [standalone audit logging]({{site.url}}{{site.baseurl}}/security/audit-logs/standalone/) mode only. +`TRANSPORT_AUDIT` | No | Yes | A transport-layer request was received on a node. Generated in [standalone audit logging]({{site.url}}{{site.baseurl}}/security/audit-logs/standalone/) mode only. +`RESOURCE_ACCESS_GRANTED` | No | Yes | Access to a shared resource was granted. Disabled by default. +`RESOURCE_ACCESS_DENIED` | No | Yes | Access to a shared resource was denied. Disabled by default. +`RESOURCE_SHARING_CHANGED` | No | Yes | A resource sharing configuration was changed. Disabled by default. ## Audit log settings @@ -260,11 +270,30 @@ config: ### Settings in opensearch.yml -The following settings are stored in the `opensearch.yml` file. +The following settings are stored in the `opensearch.yml` file. The audit filter and compliance settings---for example, `log_request_body`, `resolve_indices`, `disabled_categories`, and the `plugins.security.audit.compliance.*` settings---are dynamic: they can be changed at runtime using the [Cluster settings API]({{site.url}}{{site.baseurl}}/api-reference/cluster-api/cluster-settings/) without a node restart. Most of these dynamic settings are also marked as sensitive, meaning only security admin users can view or modify them via the cluster settings API (`body_logging_exclusions` and `action_groups.` are exceptions and are not sensitive). Other audit settings---such as `action_groups.`, `log4j.enable_mdc_routing`, `config.index`, the thread pool settings, and the sink connection settings---are static and require a node restart. + +#### Enable or disable audit logging + +```yml +plugins.security.audit.enabled: true +``` +{% include copy.html %} + +Enables or disables audit logging globally. Default is `true`. This setting is dynamic and can be toggled at runtime: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.enabled": false + } +} +``` +{% include copy.html %} #### Exclude categories -You can configure disabled categories in `opensearch.yml` using the `plugins.security.audit.config` prefix. This is useful for non-fine-grained access control (FGAC) modes (SSL-only or security-disabled) for which the `audit.yml` security index is not available: +You can configure disabled categories in `opensearch.yml` using the `plugins.security.audit.config` prefix. This is useful for non-FGAC modes (SSL-only or security-disabled) where the `audit.yml` security index is not available: ```yml plugins.security.audit.config.disabled_categories: @@ -273,7 +302,7 @@ plugins.security.audit.config.disabled_categories: ``` {% include copy.html %} -The layer-specific settings (`disabled_rest_categories` and `disabled_transport_categories`) may be deprecated in a future version. Use the unified `disabled_categories` setting instead. +The following layer-specific settings (`disabled_rest_categories` and `disabled_transport_categories`) are on a deprecation path and could be removed in a future release. Use the unified `disabled_categories` setting instead. {: .warning} The layer-specific settings are also available: @@ -288,12 +317,155 @@ plugins.security.audit.config.disabled_transport_categories: ``` {% include copy.html %} -When both `disabled_categories` and the layer-specific settings are configured, a category is disabled on a given layer if it appears in either setting. +When both `disabled_categories` and the layer-specific settings are configured, they work in tandem---a category is disabled on a given layer if it appears in either setting. A deprecation warning is logged when both are configured, encouraging migration to `disabled_categories` only. + +The `disabled_categories` settings suppress only REST and transport categories. They do not affect `COMPLIANCE_*` categories, which are governed solely by the compliance settings (`compliance.enabled`, the watched indices/fields, and the compliance ignore-users settings). +{: .note} + +#### Body logging exclusions + +Request body logging is valuable for compliance but can be expensive at scale. For example, a cluster performing 100,000+ bulk writes per second generates enormous audit volume---most of it redundant data payloads. The `log_request_body: false` toggle is all-or-nothing: it either logs all bodies or none. + +Body logging exclusions give operators granular control: suppress request bodies for high-volume operations (like bulk ingestion) while still capturing bodies for searches, index creation, and admin operations that matter for investigation. + +##### How it works + +Each audit event's action name and REST path are matched against a set of exclusion patterns. When a match is found, the request body field is omitted from the audit event---all other fields (user, IP address, indices, timestamp, etc.) are preserved. + +Matching uses two identifiers per request: + +- **Transport action** --- The internal action name (for example, `indices:data/write/bulk[s][p]`). This is matched for transport-layer audit events. +- **REST path** --- The HTTP request path (for example, `/_bulk`). This is matched for REST-layer audit events. REST paths always start with `/`. + +Both identifiers support wildcard patterns using `*` (for example, `indices:data/write/bulk*` matches `indices:data/write/bulk[s][p]`). + +##### Configuring action groups + +Action groups are named collections of action patterns and/or REST paths, defined statically in `opensearch.yml`. The group name is user-chosen---pick any name that is meaningful for your operations: + +```yml +plugins.security.audit.config.action_groups.BULK: "indices:data/write/bulk*,/_bulk" +plugins.security.audit.config.action_groups.SEARCH: "indices:data/read/search*,/_search" +plugins.security.audit.config.action_groups.INDEX_ADMIN: "indices:admin/*" +``` +{% include copy.html %} + +Each action group maps a name to a comma-separated list of patterns. Patterns can be: + +- Transport action patterns (contain `:`) --- for example, `indices:data/write/bulk*` +- REST path patterns (start with `/`) --- for example, `/_bulk` +- Wildcard patterns (contain `*`) --- for example, `indices:data/write/*` + +Action groups are static settings and require a node restart to change. The group names themselves are case-sensitive. + +##### Configuring body logging exclusions + +The `body_logging_exclusions` setting references action group names or raw patterns. It is dynamic and can be changed at runtime: + +```yml +plugins.security.audit.config.body_logging_exclusions: + - BULK +``` +{% include copy.html %} + +Or update at runtime without a restart: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.config.body_logging_exclusions": ["BULK", "SEARCH"] + } +} +``` +{% include copy.html %} + +Each entry in the list is processed as follows: + +1. If the entry matches a defined action group name, that group's patterns are expanded. +2. If it does not match any group name, the entry is treated as a raw pattern (literal or wildcard). + +A warning is logged for entries that don't look like an action pattern (no `:`), REST path (no `/`), or wildcard (no `*`), since they are unlikely to match any action. + +##### Bulk request behavior + +When `resolve_bulk_requests: true` is configured (logging individual bulk sub-items), the exclusion check uses the parent bulk action string. This means that excluding the `BULK` group suppresses bodies for **all** sub-items (index, update, delete) within that bulk request. You cannot selectively keep index-item bodies while dropping delete-item bodies within the same bulk request. + +##### Interaction with `log_request_body` + +Body logging exclusions only apply when `log_request_body` is `true`. If `log_request_body` is `false`, no bodies are logged regardless of the exclusion configuration. + +##### Example: Complete configuration + +```yml +# opensearch.yml + +# Define action groups (static, requires restart) +plugins.security.audit.config.action_groups.BULK: "indices:data/write/bulk*,/_bulk" +plugins.security.audit.config.action_groups.SEARCH: "indices:data/read/search*,/_search" +plugins.security.audit.config.action_groups.MONITORING: "cluster:monitor/*,indices:monitor/*" + +# Initial exclusions (can be updated at runtime via _cluster/settings) +plugins.security.audit.config.body_logging_exclusions: + - BULK +``` +{% include copy.html %} + +With this configuration: +- Bulk write requests: body is **not** logged (excluded) +- Search requests: body **is** logged (not excluded) +- Index creation: body **is** logged (not excluded) +- Monitoring requests: body **is** logged (not excluded, unless you add `MONITORING` to exclusions) + +To add search exclusions at runtime: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.config.body_logging_exclusions": ["BULK", "SEARCH"] + } +} +``` +{% include copy.html %} + +To clear all exclusions (resume logging all bodies): + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.config.body_logging_exclusions": [] + } +} +``` +{% include copy.html %} + +#### Log4j MDC routing + +When using the `log4j` audit sink, you can enable MDC (Mapped Diagnostic Context) routing to allow Log4j to route audit events to different appenders based on event properties: + +```yml +plugins.security.audit.config.log4j.enable_mdc_routing: true +``` +{% include copy.html %} + +When enabled, the following MDC keys are set on each audit event: + +- `audit_category` --- The audit event category (for example, `REQUEST_AUDIT`, `GRANTED_PRIVILEGES`) +- `audit_action` --- The action name +- `audit_user` --- The effective user +- `audit_request_type` --- The request type + +This allows you to configure Log4j routing appenders in your `log4j2.properties` to split audit logs by category, user, or any other MDC key. + +This is a static setting and requires a node restart. +{: .note} #### Configure the audit log index name -By default, the Security plugin stores audit events in a daily rolling index named `auditlog-YYYY.MM.dd`: +By default, the Security plugin stores audit events in a daily rolling index named `security-auditlog-YYYY.MM.dd`: ```yml plugins.security.audit.config.index: myauditlogindex @@ -328,7 +500,7 @@ plugins.security.audit.config.threadpool.max_queue_len: 100000 ## Disabling audit logs -To disable audit logs after they've been enabled, remove the `plugins.security.audit.type: internal_opensearch` setting from `opensearch.yml`, or switch off the **Enable audit logging** check box in OpenSearch Dashboards. +To disable audit logs after they've been enabled, remove the `plugins.security.audit.type: internal_opensearch` setting from `opensearch.yml`, or set `plugins.security.audit.enabled` to `false` via the cluster settings API. ## Audit user account manipulation diff --git a/_security/audit-logs/standalone.md b/_security/audit-logs/standalone.md new file mode 100644 index 0000000000..c49de8b001 --- /dev/null +++ b/_security/audit-logs/standalone.md @@ -0,0 +1,308 @@ +--- +layout: default +title: Standalone audit logging +parent: Audit logs +nav_order: 130 +--- + +# Standalone audit logging + +--- + +
+ + Table of contents + + {: .text-delta } +- TOC +{:toc} +
+ +--- + +Standalone audit logging enables audit logging for OpenSearch clusters that do not use fine-grained access control (FGAC). This includes clusters running in SSL-only mode (`plugins.security.ssl_only: true`) or with security disabled (`plugins.security.disabled: true`). + +In this context, *standalone* means audit logging is independent of fine-grained access control---not a separate plugin or process. It runs inside the Security plugin and reuses the same audit pipeline as standard mode; it just does not depend on authentication or authorization to produce events. + +Many organizations need audit trails for compliance (SOC2, HIPAA, PCI-DSS, GDPR) even when they don't require authentication or authorization. Standalone audit logging answers the question "who did what, when?" without requiring the full security infrastructure. + +{: .note } +Standalone audit logging uses the same audit infrastructure (sinks, routing, async thread pool) as standard FGAC audit logging. The difference is that it does not depend on authentication or authorization to produce events. + +## Requirements + +To enable standalone audit logging, add both of the following settings to `opensearch.yml` on each node: + +```yml +plugins.security.audit.enable_standalone: true +plugins.security.audit.type: log4j +``` +{% include copy.html %} + +Both settings are required: +- `plugins.security.audit.enable_standalone: true` activates the standalone audit subsystem. +- `plugins.security.audit.type: ` specifies the audit sink (where events are stored). + +After adding these settings, restart each node to activate standalone audit logging. + +{: .warning } +Authentication-only audit categories (`FAILED_LOGIN`, `AUTHENTICATED`, `GRANTED_PRIVILEGES`, `MISSING_PRIVILEGES`) will never produce events in standalone mode because no authentication or authorization decisions occur. A warning is logged at startup listing these inactive categories. + +## Supported audit sinks + +Standalone audit logging supports the same sinks as standard mode: + +Sink type | Description +:--- | :--- +`internal_opensearch` | Writes audit events to an index on the current OpenSearch cluster. +`log4j` | Writes events to a Log4j logger. You can use any Log4j appender (file, SNMP, JDBC, Kafka, etc.). +`webhook` | Sends events as JSON to an arbitrary HTTP endpoint. +`external_opensearch` | Writes to an audit index on a remote OpenSearch cluster. + +For sink-specific configuration options, see [Audit log storage types]({{site.url}}{{site.baseurl}}/security/audit-logs/storage-types/). + +## Tracked events + +Standalone audit logging introduces two request-tracking categories designed for environments without authentication: + +Category | Layer | Description +:--- | :--- | :--- +`REQUEST_AUDIT` | REST | Captures all REST-layer requests including source IP, target indices, request body, HTTP headers, and request method. This is the primary event for standalone mode. +`TRANSPORT_AUDIT` | Transport | Captures transport-layer requests between nodes, including shard-level operations (`bulk[s][p]`, `search[phase/query]`), replica writes, and forwarded requests. + +These categories do not imply any authentication or authorization semantics---they simply record that a request was received and processed. + +In addition to these request-tracking categories, standalone audit logging emits the standard document-level compliance categories when [compliance tracking](#compliance-tracking) is enabled: + +Category | Description +:--- | :--- +`COMPLIANCE_DOC_WRITE` | A document was written to a watched index. See [Document write tracking](#document-write-tracking). +`COMPLIANCE_DOC_READ` | A watched field was read from a watched index. See [Document read tracking](#document-read-tracking). + +Compliance events are governed only by the compliance settings (watched indices/fields and `compliance.enabled`). They are not affected by `disabled_categories`, which applies only to `REQUEST_AUDIT` and `TRANSPORT_AUDIT`. + +### Event fields + +Each `REQUEST_AUDIT` event includes: + +- `@timestamp` --- When the event occurred +- `audit_cluster_name`, `audit_node_name`, `audit_node_id` --- Cluster and node identity +- `audit_rest_request_method`, `audit_rest_request_path` --- HTTP method and path +- `audit_request_body` --- Request body (configurable) +- `audit_request_remote_address` --- Client source IP +- `audit_trace_indices` --- Target indices (raw patterns) +- `audit_trace_resolved_indices` --- Resolved concrete indices (when `resolve_indices: true`) +- `audit_transport_request_type` --- Transport request class (e.g., `IndexRequest`, `SearchRequest`) +- `audit_request_layer` --- `REST` or `TRANSPORT` +- `audit_rest_request_headers` --- HTTP headers (sensitive headers excluded) + +### Identity in standalone mode + +Identity information varies by security mode: + +- **SSL-only with mTLS**: The client certificate's subject DN is logged as `audit_request_effective_user` (e.g., `CN=my-app,OU=engineering,O=myorg`). +- **SSL-only without mTLS**: Only the source IP address is captured. +- **Security disabled**: Only the source IP address is captured. + +## Configuration + +All standalone audit settings are configured in `opensearch.yml` for initial values and can be dynamically updated at runtime using the [Cluster settings API]({{site.url}}{{site.baseurl}}/api-reference/cluster-api/cluster-settings/). No security index is required. + +Standalone mode does not use the [Audit logs]({{site.url}}{{site.baseurl}}/security/access-control/api/#audit-logs) REST API or `audit.yml`---those manage the security index and require fine-grained access control. In standalone mode, use the Cluster settings API instead. + +### Dynamic configuration + +All filter and compliance settings can be changed at runtime without restarting the cluster: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.config.log_request_body": false + } +} +``` +{% include copy.html %} + +Dynamic settings override the values in `opensearch.yml` and persist across cluster restarts. + +### Dynamic settings reference + +The following settings are all dynamic---they can be set in `opensearch.yml` for initial values and updated at runtime via `PUT _cluster/settings`. Types are shown as placeholders: + +```yml +# Global toggle +plugins.security.audit.enabled: + +# Filter settings +plugins.security.audit.config.log_request_body: +plugins.security.audit.config.resolve_indices: +plugins.security.audit.config.resolve_bulk_requests: +plugins.security.audit.config.exclude_sensitive_headers: +plugins.security.audit.config.enable_rest: +plugins.security.audit.config.enable_transport: +plugins.security.audit.config.disabled_categories: +plugins.security.audit.config.disabled_rest_categories: +plugins.security.audit.config.disabled_transport_categories: +plugins.security.audit.config.ignore_users: +plugins.security.audit.config.ignore_requests: +plugins.security.audit.config.ignore_headers: +plugins.security.audit.config.body_logging_exclusions: + +# Compliance settings +plugins.security.audit.compliance.enabled: +plugins.security.audit.compliance.write_metadata_only: +plugins.security.audit.compliance.write_log_diffs: +plugins.security.audit.compliance.write_watched_indices: +plugins.security.audit.compliance.write_ignore_users: +plugins.security.audit.compliance.read_metadata_only: +plugins.security.audit.compliance.read_watched_fields: +plugins.security.audit.compliance.read_ignore_users: +plugins.security.audit.compliance.external_config: +plugins.security.audit.compliance.internal_config: +``` +{% include copy.html %} + +Static settings (`enable_standalone`, `action_groups.`, `log4j.enable_mdc_routing`, sink connection settings, and the thread pool settings) require a node restart and cannot be changed with the cluster settings API. + +### Available filter settings + +The following settings control what is logged. Configure them in `opensearch.yml` or update dynamically via `PUT _cluster/settings`: + +Setting | Default | Description +:--- | :--- | :--- +`plugins.security.audit.config.enable_rest` | `true` | Enable REST-layer audit events. +`plugins.security.audit.config.enable_transport` | `true` | Enable transport-layer audit events. +`plugins.security.audit.config.log_request_body` | `true` | Include the request body in audit events. +`plugins.security.audit.config.resolve_indices` | `true` | Resolve wildcard index patterns to concrete indices. +`plugins.security.audit.config.resolve_bulk_requests` | `false` | Log individual sub-operations in bulk requests. +`plugins.security.audit.config.exclude_sensitive_headers` | `true` | Exclude sensitive headers (e.g., `Authorization`) from audit events. +`plugins.security.audit.config.disabled_categories` | `[]` | Request-tracking categories to disable (e.g., `["REQUEST_AUDIT"]`). Does not affect `COMPLIANCE_*` categories. +`plugins.security.audit.config.disabled_rest_categories` | `["AUTHENTICATED", "GRANTED_PRIVILEGES"]` | REST-layer categories to disable. On a deprecation path---prefer `disabled_categories`. +`plugins.security.audit.config.disabled_transport_categories` | `["AUTHENTICATED", "GRANTED_PRIVILEGES"]` | Transport-layer categories to disable. On a deprecation path---prefer `disabled_categories`. +`plugins.security.audit.config.ignore_users` | `["kibanaserver"]` | Users whose requests are not logged. +`plugins.security.audit.config.ignore_requests` | `[]` | Action patterns or REST paths to exclude (e.g., `["cluster:monitor/*"]`). +`plugins.security.audit.config.ignore_headers` | `[]` | HTTP headers to exclude from audit events. + +### Toggling audit on/off at runtime + +You can enable or disable audit logging without restarting the cluster: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.security.audit.enabled": false + } +} +``` +{% include copy.html %} + +Set the value to `true` to re-enable audit logging. + +## Compliance tracking + +Document-level compliance tracking works in standalone mode for both reads and writes. + +### Document write tracking + +To track writes to specific indices, configure the watched indices: + +```yml +plugins.security.audit.compliance.enabled: true +plugins.security.audit.compliance.write_watched_indices: + - "sensitive-data-*" + - "financial-records" +``` +{% include copy.html %} + +Write events are logged with the `COMPLIANCE_DOC_WRITE` category and include the document ID, index name, and shard ID. When `write_log_diffs: true`, the event includes a diff between the previous and current document content. + +### Document read tracking + +To track reads of specific fields in specific indices, configure `read_watched_fields`. As a cluster setting, this is a list of strings---each entry is a comma-separated string whose first token is an index pattern and whose remaining tokens are field patterns. If no field patterns are given for an index, all fields (`*`) are watched: + +```yml +plugins.security.audit.compliance.enabled: true +plugins.security.audit.compliance.read_watched_fields: + - "sensitive-data-*,ssn,credit_card" + - "hr-records,salary,performance_rating" +``` +{% include copy.html %} + +Read events are logged with the `COMPLIANCE_DOC_READ` category and include the field values that were accessed. + +### Compliance settings + +Setting | Default | Description +:--- | :--- | :--- +`plugins.security.audit.compliance.enabled` | `true` | Enable compliance tracking. Compliance events are only produced for the indices and fields configured in the watched settings. +`plugins.security.audit.compliance.write_metadata_only` | `false` | Log only metadata for write events (no document content). +`plugins.security.audit.compliance.read_metadata_only` | `false` | Log only metadata for read events (no field values). +`plugins.security.audit.compliance.write_log_diffs` | `false` | Include diffs between old and new document content. +`plugins.security.audit.compliance.write_watched_indices` | `[]` | Index patterns to watch for write compliance events. +`plugins.security.audit.compliance.read_watched_fields` | `[]` | Index-and-fields patterns to watch for read compliance events. Each entry is a comma-separated string: `,,...`. +`plugins.security.audit.compliance.write_ignore_users` | `["kibanaserver"]` | Users whose document writes are not tracked for compliance. +`plugins.security.audit.compliance.read_ignore_users` | `["kibanaserver"]` | Users whose document reads are not tracked for compliance. +`plugins.security.audit.compliance.external_config` | `false` | Log the external configuration (`opensearch.yml` and environment) once at startup. +`plugins.security.audit.compliance.internal_config` | `false` | Log changes to the internal security configuration. + +All compliance settings are dynamic and can be updated via `PUT _cluster/settings`. + +## Example configurations + +### SSL-only mode with Log4j sink + +This configuration enables audit logging in an SSL-only cluster, writing events to a Log4j logger: + +```yml +plugins.security.ssl_only: true + +# TLS configuration +plugins.security.ssl.transport.pemcert_filepath: node-cert.pem +plugins.security.ssl.transport.pemkey_filepath: node-key.pem +plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem +plugins.security.ssl.http.enabled: true +plugins.security.ssl.http.pemcert_filepath: node-cert.pem +plugins.security.ssl.http.pemkey_filepath: node-key.pem +plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem + +# Standalone audit logging +plugins.security.audit.enable_standalone: true +plugins.security.audit.type: log4j + +# Audit filter settings +plugins.security.audit.config.log_request_body: true +plugins.security.audit.config.resolve_indices: true +plugins.security.audit.config.exclude_sensitive_headers: true +plugins.security.audit.config.ignore_requests: + - "cluster:monitor/*" + - "indices:monitor/*" +``` +{% include copy.html %} + +### Security-disabled mode with internal index sink + +This configuration enables audit logging in a cluster with security disabled, storing events in an internal OpenSearch index: + +```yml +plugins.security.disabled: true + +# Standalone audit logging +plugins.security.audit.enable_standalone: true +plugins.security.audit.type: internal_opensearch + +# Audit filter settings +plugins.security.audit.config.log_request_body: true +plugins.security.audit.config.resolve_indices: true +plugins.security.audit.config.resolve_bulk_requests: true + +# Compliance tracking +plugins.security.audit.compliance.enabled: true +plugins.security.audit.compliance.write_watched_indices: + - "financial-*" + - "pii-*" +``` +{% include copy.html %} + +With this configuration, audit events are written to a daily rolling index named `security-auditlog-YYYY.MM.dd` by default.