OpenSearch least-privilege credentials
deadair needs read access to two things:
- Security Analytics detector metadata.
- OpenSearch index, alias, and data-stream resolution, plus source inventory, freshness, and optional field metadata.
It does not need detector writes, document writes, index management, or user/role management.
Live integration tests cover OpenSearch 2.19.6 and 3.7.0. Each version is scanned with only the roles below. The tests exercise native input resolution and require representative write attempts to be rejected.
Roles
Use the built-in security_analytics_read_access role for Security Analytics metadata.
Add a small index-monitor role for source inventory and freshness:
// PUT _plugins/_security/api/roles/deadair_index_monitor
{
"cluster_permissions": [
"cluster_monitor"
],
"index_permissions": [
{
"index_patterns": ["*"],
"allowed_actions": [
"read",
"indices_monitor"
]
}
]
}
Assign both roles to the deadair user or backend role:
security_analytics_read_accessdeadair_index_monitor
Narrow index_patterns from "*" when telemetry follows known patterns such as logs-*,
winlogbeat-*, or audit-*. deadair can report only on sources visible to its role.
That visibility affects verdicts. If a detector expects winlogbeat-* but the role can read only
logs-*, deadair sees no matching source even if Winlogbeat indices exist. deadair check confirms
that required API calls are allowed; it cannot prove that a scoped role includes every source your
detectors use. After tightening the role, verify at least one known-good detector and source in the
first JSON report before triaging no-match findings.
Basic auth
export DEADAIR_BACKEND=opensearch
export DEADAIR_OPENSEARCH_URL=https://opensearch.example.internal:9200
export DEADAIR_OPENSEARCH_USERNAME=deadair
export DEADAIR_OPENSEARCH_PASSWORD=<password>
deadair check
deadair scan
For a long-running service, keep the password in a file with 0600 permissions:
install -m 0600 /dev/null /etc/deadair/opensearch-password
printf '%s' '<password>' > /etc/deadair/opensearch-password
deadair serve \
--backend opensearch \
--opensearch-url https://opensearch.example.internal:9200 \
--opensearch-username deadair \
--opensearch-password-file /etc/deadair/opensearch-password
API key auth
API key auth is supported when your OpenSearch deployment accepts Authorization: ApiKey.
export DEADAIR_BACKEND=opensearch
export DEADAIR_OPENSEARCH_URL=https://opensearch.example.internal:9200
export DEADAIR_OPENSEARCH_API_KEY=<api key>
deadair scan
Calls deadair makes
GET /for backend version discoveryPOST /_plugins/_security_analytics/detectors/_searchGET /_resolve/index/<expression>?ignore_unavailable=trueGET /_data_stream/_statsGET /_cat/indices?format=json&h=index,docs.count,store.size&bytes=bPOST /<index>/_searchwithsize: 0aggregations for freshnessGET /<index>/_field_capswhen--schemais enabled
If an audit shows deadair requesting detector writes, document writes, index creation/deletion, or user and role management APIs, treat that as a bug.