Skip to content

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.

On first start, the demo configuration creates an admin / admin user. Change the admin password before opening to traffic.

Terminal window
# Inside the running container (one time, on a fresh install)
docker exec -it <container> bash
cd /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.pem

After bootstrap, prefer the UI for user/role management — no YAML, no bcrypt.

  1. Open Dashboards → https://analytics.logrite.ai/pxe/
  2. Log in as admin / admin (change immediately on first use)
  3. Hamburger menu → Management → Security

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:

UsernameUsed by
logrite_appBackend proxy, semantic-api, ai-service, mcp-server
logrite_readonlyFuture read-only dashboards
dashboards_svcOpenSearch Dashboards itself (or use built-in kibanaserver)

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
  • 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:

FeatureRequired 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.

Roles → click logrite_app_role → Mapped users → Manage mapping → add logrite_app

Set the same plain-text password as env vars in each service (Coolify “Environment Variables” panel):

OPENSEARCH_USERNAME=logrite_app
OPENSEARCH_PASSWORD=<generated>

All Logrite services already read these vars and fall back to no-auth when unset — see Security Hardening for the contract.

  1. Dashboards UI → Internal users → click user → Edit → set new password
  2. Update Coolify env var for every service using that account
  3. Redeploy each service

No YAML, no securityadmin.sh.

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).

The official image enables transport TLS with self-signed demo certs. For production:

  1. Replace kirk.pem, node.pem, and root CA with real certs
  2. Set plugins.security.ssl.http.enabled: true in opensearch.yml
  3. 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.