ES|QL|DS: Prevent credential leak in audit log #159730

Open
luigidellaquila opened 1:45pm on September 18, 2026 wants to merge 1 commit into elastic/elasticsearch main from
esql/ds/audit_log_creds
Diff Delta:
0
About 0 Diff Delta/hour
Classified as:  General

luigidellaquila's Description of Work

PUT /_query/data_source/{name} exposed credentials (S3 access_key/secret_key/session_token, GCS credentials/access_token, Azure connection_string/key/sas_token) through two separate audit-log vectors:

Vector 1 β€” request body. With xpack.security.audit.logfile.events.emit_request_body: true, the authentication_success event recorded the full body including plaintext credential values.

Vector 2 β€” query string. The handler accepted the data source definition via the source/source_content_type query parameters. The query string is written unfiltered into url.query on authentication_failed events (audited by default), so credentials in the query string reached the audit log on any failed authentication attempt β€” regardless of emit_request_body.

Fix

Vector 1 β€” RestPutDataSourceAction now implements RestRequestFilter, returning credential field names as settings.<name> dotted paths. SecurityRestFilter strips these from the request body before the authentication_success audit event is written.

Vector 2 β€” The handler now calls contentParser() instead of contentOrSourceParamParser(), rejecting any request that carries the definition in source/source_content_type query parameters with HTTP 400. This mirrors the approach used by RestPutUserAction.

How secret field names flow to the handler



  1. DataSourceValidator gains a default Set<String> secretSettingNames() (returns empty by default).


  2. FileDataSourceValidator gains a withSecretFieldNames(Set<String>) builder method that stores the provider's credential field names.

  3. Each provider plugin (S3DataSourcePlugin, GcsDataSourcePlugin, AzureDataSourcePlugin) chains .withSecretFieldNames(...) when building its validator.


  4. EsqlPlugin.createComponents() collects all secret names from registered validators into a volatile field.


  5. EsqlPlugin.getRestHandlers() passes the collected names to RestPutDataSourceAction.

Tests



  • AuditIT (integration): two new tests β€” testFilteringOfDataSourceCredentials asserts that credential values are absent from the request.body field of the authentication_success audit event; testDataSourceDefinitionInQueryStringRejected asserts HTTP 400 when the definition is sent in query params.


  • RestPutDataSourceActionTests (unit, new): asserts that getFilteredFields() produces the correct settings.<name> paths for S3, GCS, and Azure credential sets.

Breaking change

Clients that currently send the data source definition in source/source_content_type query parameters will receive HTTP 400. The body-only constraint is intentional and mirrors PUT /_security/user/{name}.

Closes elastic/esql-planning#1990

0 total changed files
Review complete πŸ’ͺ
Reviewer: 1. Additional work: 0