ES account permissions
A dedicated Elasticsearch account for the gateway: read on log indices, read / write on its own .rst_copilot_* indices, optionally read on alerts and osquery results. Kibana steps and the API version.
The gateway is read-only on your log indices and keeps all of its own state under the .rst_copilot_* prefix (12 hidden indices, one wildcard covers them). Create a dedicated user; do not use the elastic superuser.
Role
| Index pattern | Privileges | For | Required |
|---|---|---|---|
Your logs, e.g. logs-*, filebeat-*, winlogbeat-* | read, view_index_metadata | Smart query, field dictionary, investigation evidence | ✅ |
.rst_copilot_* | create_index, read, write, manage | Audit, conversations, knowledge base, learning library, reports, analysis records, alerts, cursors, notification config and queue, assets, user state | ✅ |
.alerts-security.alerts-*, .internal.alerts-security.alerts-* | read, view_index_metadata | Live alerts polling, Batch triage | With alerts |
logs-osquery_manager.result-* | read, view_index_metadata | Baseline | With baseline |
baseline-* | create_index, read, write, manage | Baseline rules / results / runs | With baseline |
Cluster privilege: monitor (Platform health's cluster-level checks and "list indices" need it; without it those checks show "unavailable", everything else works).
.alerts-security.alerts-* and friends are hidden indices: the Kibana role page's index dropdown will not autocomplete them - type the pattern and press Enter. No "include restricted indices" switch is needed.
In Kibana
Stack Management → Security → Roles → Create role, named rst_copilot_gateway.
Cluster privileges: tick monitor.
Index privileges: one row per line of the table above - pattern(s) + privileges.
Users → Create user rst_copilot_gateway, assign the role.
Put the credentials in .env as ES_USER / ES_PASSWORD, or "Test connection" and save under Settings.
Via the API
PUT _security/role/rst_copilot_gateway
{
"cluster": ["monitor"],
"indices": [
{ "names": ["logs-*", "filebeat-*", "winlogbeat-*"], "privileges": ["read", "view_index_metadata"] },
{ "names": [".rst_copilot_*", "baseline-*"], "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"] }Verifying
curl -k https://<hostname>/readyzes_write must be ok. denied = missing create / write on .rst_copilot_*; the gateway log says es_write_denied. If "Test connection" under Settings reports "this account cannot list indices", monitor or read on the target indices is missing.
Index whitelist
Privileges decide what the gateway can read; RST_INDEX_WHITELIST (or the whitelist under Settings) decides what it will read. Use both: give the account only the indices it needs, then narrow again with the whitelist. A model trying to query outside it is refused, visible in an investigation's retrieval trace.
Configuration reference
Every setting in .env: required ones, security, ES connection, models and reasoning, alert ingest, scheduled reports, baseline, audit and retention. Values changed in the UI win.
Enterprise SSO
Analysts sign in with their corporate account: Caddy → oauth2-proxy → the IdP (Entra ID / Okta / Keycloak / AD). Roles map from IdP groups; audit traces to a person.