Elasticsearch account permissions
The role for a dedicated gateway account in Elasticsearch, how to create it in Kibana or with the API, and how to connect with an API key instead.
The gateway reads log indices only and writes its own state to hidden indices under the .rst_copilot_* prefix. Create a dedicated account for it instead of using the elastic superuser.
Role privileges
Cluster privileges
| Privilege | Purpose | Required |
|---|---|---|
monitor | Connectivity check (es in /readyz), cluster checks and index listing in Platform health | Yes |
manage_ilm, manage_index_templates | Audit written to an ILM data stream | When RST_ILM_BOOTSTRAP=true |
Without monitor, /readyz returns not_ready with ping returned False for es, and every Platform health check shows as unknown.
Index privileges
| Index pattern | Privileges | Purpose | Required |
|---|---|---|---|
Log indices, for example logs-*, filebeat-*, winlogbeat-* | read, view_index_metadata | Ask AI, field dictionary, investigation evidence | Yes |
.rst_copilot_* | create_index, read, write, manage | Audit, conversations, knowledge base, learned solutions, reports, analysis records, alerts, cursors, notification config and queue, assets, user state | Yes |
.alerts-security.alerts-*, .internal.alerts-security.alerts-* | read, view_index_metadata | Alerts polling, Triage | With alert features |
logs-osquery_manager.result-* | read, view_index_metadata | Baseline checks | With baseline |
baseline-*, eol-catalog | create_index, read, write, manage | Baseline rules, results and runs, and the software end-of-life catalog the gateway creates | With baseline |
baseline-* and eol-catalog have no .rst_copilot_ prefix, so the wildcard in the row above does not cover them. Without them the baseline page has no rules and runs return 403.
Kibana feature privileges
| Space | Feature privilege | Purpose | Required |
|---|---|---|---|
default | Discover: Read | Open in Kibana | When KIBANA_URL is set and Kibana uses the gateway account |
Without it the gateway cannot find a data view, and Open in Kibana reports "No Kibana data view matches index <index>", even when the data view exists in Kibana.
Create the account in Kibana
Steps
- In Kibana, open Stack Management > Security > Roles and select Create role. Name it
rst_copilot_gateway. - Under Cluster privileges, add
monitor. WithRST_ILM_BOOTSTRAP=true, also addmanage_ilmandmanage_index_templates. - Under Index privileges, add one row per index group from the table above.
- If
KIBANA_URLis set, select Add Kibana privilege under Kibana, choose thedefaultspace, and set Discover to Read in the feature list. - Under Users, select Create user with the username
rst_copilot_gatewayand assign the role. - Put the account in
.envasES_USERandES_PASSWORD, or test the connection in Settings and save it there. To use an API key instead, see Use an API key.
Hidden indices such as .alerts-security.alerts-* are not autocompleted in the index dropdown. Type the pattern directly; you do not need the restricted-indices switch.
Create the account with the API
PUT _security/role/rst_copilot_gateway
{
"cluster": ["monitor"],
"indices": [
{ "names": ["logs-*", "filebeat-*", "winlogbeat-*"], "privileges": ["read", "view_index_metadata"] },
{ "names": [".rst_copilot_*", "baseline-*", "eol-catalog"], "privileges": ["create_index", "read", "write", "manage"] },
{ "names": [".alerts-security.alerts-*", ".internal.alerts-security.alerts-*", "logs-osquery_manager.result-*"], "privileges": ["read", "view_index_metadata"] }
]
}
PUT _security/user/rst_copilot_gateway
{ "password": "<strong password>", "roles": ["rst_copilot_gateway"] }With RST_ILM_BOOTSTRAP=true, set cluster to ["monitor", "manage_ilm", "manage_index_templates"].
Kibana feature privileges can only be set through the Kibana role API. The request replaces the whole role, so include the cluster and index privileges above in the elasticsearch section, or they are removed:
curl -u elastic -X PUT "https://<Kibana address>/api/security/role/rst_copilot_gateway" \
-H "kbn-xsrf: true" -H "Content-Type: application/json" -d '
{
"elasticsearch": {
"cluster": ["monitor"],
"indices": [
{ "names": ["logs-*", "filebeat-*", "winlogbeat-*"], "privileges": ["read", "view_index_metadata"] },
{ "names": [".rst_copilot_*", "baseline-*", "eol-catalog"], "privileges": ["create_index", "read", "write", "manage"] },
{ "names": [".alerts-security.alerts-*", ".internal.alerts-security.alerts-*", "logs-osquery_manager.result-*"], "privileges": ["read", "view_index_metadata"] }
]
},
"kibana": [
{ "base": [], "feature": { "discover": ["read"] }, "spaces": ["default"] }
]
}'Use an API key
The gateway can connect to Elasticsearch with an API key instead of a username and password. An API key has the privileges of the account it is issued for, so create the rst_copilot_gateway account and role as above first, then issue a key for that account.
Steps
-
As an administrator, issue a key for
rst_copilot_gateway:POST _security/api_key/grant { "grant_type": "password", "username": "rst_copilot_gateway", "password": "<strong password>", "api_key": { "name": "rst-copilot-gateway" } }You can also sign in to Kibana as
rst_copilot_gatewayand create it under Stack Management > Security > API keys. -
Put the
encodedvalue from the response in.envasES_API_KEY. -
Restart the gateway.
ES_API_KEY takes precedence over ES_USER / ES_PASSWORD. When no KIBANA_* credentials are set, Kibana calls use the same key. ES_API_KEY can only be set in .env; there is no field for it in Settings.
Verify the privileges
curl -k https://<hostname>/readyzes_write must be ok. denied means the account cannot create or write .rst_copilot_* indices, and the gateway log shows es_write_denied. not_ready with ping returned False for es means the account is missing the cluster privilege monitor, or the address, certificate or credentials are wrong.
If the connection test in Settings reports "Connected, but this account cannot list indices", the account is missing monitor or read on the target indices.
Index allowlist
Privileges decide what the gateway can read; the index allowlist (RST_INDEX_WHITELIST, or Index allowlist in Settings) decides what it actually queries. Set both: grant only the indices you need, then narrow further with the allowlist. The gateway refuses any model query outside the allowlist, and the refusal appears in the retrieval trace of an alert investigation.
Configuration reference
Every key in .env: required keys, login and accounts, Elasticsearch connection, model and reasoning, live alerts, scheduled reports and baseline, audit and retention, resource limits.
SSO
Analysts sign in with a corporate account. Caddy hands authentication to oauth2-proxy and the customer IdP (Entra ID, Okta, Keycloak, AD), and roles map from IdP groups.