Security Plugin
The OpenSearch Security Plugin handles authentication, authorization, TLS,
audit logging, and tenants. The official Docker image
(opensearchproject/opensearch:3.3.1) ships with it pre-installed.
The legacy source-built 3.4.0-SNAPSHOT does not include it — the
plugin only becomes available after the Coolify migration.
Bootstrap
Section titled “Bootstrap”On first start, the demo configuration creates an admin / admin user.
Change the admin password before opening to traffic.
# Inside the running container (one time, on a fresh install)docker exec -it <container> bashcd /usr/share/opensearch/plugins/opensearch-security/tools./securityadmin.sh -cd ../../../config/opensearch-security/ \ -icl -nhnv \ -cacert ../../../config/kirk-root-ca.pem \ -cert ../../../config/kirk.pem \ -key ../../../config/kirk-key.pemManaging Users via Dashboards UI
Section titled “Managing Users via Dashboards UI”After bootstrap, prefer the UI for user/role management — no YAML, no bcrypt.
- Open Dashboards →
https://analytics.logrite.ai/pxe/ - Log in as
admin/admin(change immediately on first use) - Hamburger menu → Management → Security
Create Service Users
Section titled “Create Service Users”Internal users → Create internal user
For each Logrite service, create one account with a generated password
(openssl rand -base64 32) and store the password in 1Password / Bitwarden:
| Username | Used by |
|---|---|
logrite_app | Backend proxy, semantic-api, ai-service, mcp-server |
logrite_readonly | Future read-only dashboards |
dashboards_svc | OpenSearch Dashboards itself (or use built-in kibanaserver) |
Create Roles
Section titled “Create Roles”Roles → Create role
Example logrite_app_role:
- Cluster permissions:
cluster_monitor,cluster_composite_ops, plus the per-feature grants below. - Index permissions:
- Index patterns:
*-logrite,*_semantic,compliance-logs - Allowed actions:
indices_all
- Index patterns:
- Tenant permissions:
global_tenant→ Read/Write
Per-feature cluster grants — every Logrite UI feature that talks to OS via the backend proxy needs the matching cluster:* action allow-listed here, otherwise the security plugin returns 403 security_exception and the UI sees a generic proxy error:
| Feature | Required cluster permissions |
|---|---|
Semantic Search (EmbeddingService.getDeployedModel, neural query) | cluster:admin/opensearch/ml/models/search, cluster:admin/opensearch/ml/models/get, cluster:admin/opensearch/ml/predict, cluster:admin/opensearch/ml/connectors/search, cluster:admin/opensearch/ml/connectors/get |
| Anomaly Detectors view (read-only) | cluster:admin/opendistro/ad/detector/search, cluster:admin/opendistro/ad/detector/info, cluster:admin/opendistro/ad/detector/jobmanagement, cluster:admin/opendistro/ad/detectors/get, cluster:admin/opendistro/ad/result/search, cluster:admin/opendistro/ad/tasks/search |
| Alerts + Notifications views (read-only) | cluster:admin/opendistro/alerting/monitor/search, cluster:admin/opendistro/alerting/monitor/get, cluster:admin/opendistro/alerting/destination/get, cluster:admin/opendistro/alerting/alerts/get, cluster:admin/opensearch/alerting/alerts/get, cluster:admin/opendistro/alerting/findings/get, cluster:admin/opendistro/alerting/findings/search, cluster:admin/opensearch/alerting/findings/get, cluster:admin/opensearch/alerting/findings/search, cluster:admin/opensearch/notifications/channels/get, cluster:admin/opensearch/notifications/configs/get |
| Index State Management + Rollups + Transforms (read-only) | cluster:admin/opendistro/ism/policy/search, cluster:admin/opendistro/ism/policy/get, cluster:admin/opendistro/ism/managedindex/explain, cluster:admin/opendistro/rollup/get, cluster:admin/opendistro/rollup/search, cluster:admin/opendistro/transform/get, cluster:admin/opendistro/transform/search, indices:admin/index_template/get |
OSD via backend proxy (/api/v1/dashboards/*) | OSD authenticates as dashboards-svc via Basic auth injected by OpenSearchDashboardsProxyController. The OSD plugin wrapper APIs it calls (/api/alerting/*, /api/anomaly_detectors/*, /api/notifications/*, /api/ism/*) reach OS as the same dashboards-svc identity. dashboards-svc is mapped into logrite_app_role (in addition to dashboards_role/kibana_user/kibana_server/readall) so it inherits the read-only plugin perms above. Specifically required for /api/alerting/alerts: cluster:admin/opendistro/alerting/alerts/get (and the cluster:admin/opensearch/alerting/alerts/get namespace-variant). Without this mapping OSD returns 200 {"ok":false,"err":"[security_exception] no permissions for [...]"}. |
The live source of truth is /home/victor/logrite/config/opensearch/security/roles.yml (bind-mounted into the OS container). Add new perms there and also patch the running role via PATCH /_plugins/_security/api/roles/logrite_app_role so the change takes effect without an OS restart.
Map Users to Roles
Section titled “Map Users to Roles”Roles → click logrite_app_role → Mapped users → Manage mapping → add logrite_app
Distributing Credentials
Section titled “Distributing Credentials”Set the same plain-text password as env vars in each service (Coolify “Environment Variables” panel):
OPENSEARCH_USERNAME=logrite_appOPENSEARCH_PASSWORD=<generated>All Logrite services already read these vars and fall back to no-auth when unset — see Security Hardening for the contract.
Rotating a Password
Section titled “Rotating a Password”- Dashboards UI → Internal users → click user → Edit → set new password
- Update Coolify env var for every service using that account
- Redeploy each service
No YAML, no securityadmin.sh.
Reserved Users
Section titled “Reserved Users”admin, kibanaserver, logstash, readall are marked reserved: true
and cannot be deleted. Either change their password or remove them from
their default role mapping (e.g. unbind admin from all_access once a
real admin exists).
TLS Notes
Section titled “TLS Notes”The official image enables transport TLS with self-signed demo certs. For production:
- Replace
kirk.pem,node.pem, and root CA with real certs - Set
plugins.security.ssl.http.enabled: trueinopensearch.yml - Update every client to use
https://and trust the CA
The proxy controller (OpenSearchProxyController.java) speaks plain HTTP
to localhost:9200 inside the same network — TLS becomes load-bearing
only when OpenSearch is on a different host.