Translate AtlasMart application jobs into OpenSearch internal users, narrowly scoped roles, role mappings, action groups, index permissions, cluster permissions, and explicit 403 acceptance tests.

Users, Roles, Role Mappings, Action Groups, Index Permissions, and Cluster Permissions

Build least-privilege OpenSearch security with observable identity, authorization, fine-grained read controls, credential lifecycle, and explicit Elasticsearch comparison boundaries.

Intermediate → Advanced120–160 minutesOpenSearch Security · Chapter 20 · Lesson 02OpenSearch 3.8.0 · OpenSearch Dashboards 3.8.0 · Elastic comparison: 9.5.3Last reviewed: September 2026

Learning outcomes

AtlasMart now has a trustworthy OpenSearch endpoint, but the application still authenticates as admin. A stolen frontend secret would therefore become a cluster-administration incident. This lesson decomposes application access into internal users, roles, role mappings and action groups, then treats a 403 as positive evidence that the boundary works.

01

Explain the difference between an internal user, backend role, OpenSearch security role and role mapping.

02

Create separate reader and ingester roles with narrow index/cluster permissions instead of wildcard application access.

03

Use action groups as named permission bundles without assuming every bundle is safe for every application.

04

Prove role resolution with authinfo and explicit 2xx/403 tests.

05

Distinguish Dashboards tenant permission from data-index permission.

Chapter baseline

Examples target upstream self-managed OpenSearch 3.8.0 / OpenSearch Dashboards 3.8.0, released 4 August 2026, with the bundled Security plugin. The lab reuses the earlier single-node atlasmart-os container at https://localhost:9201 and OPENSEARCH_INITIAL_ADMIN_PASSWORD only for the disposable demo bootstrap. The upstream demo certificate is intentionally not a production PKI contract, so earlier local labs may use -k only against this isolated demo endpoint. Production must use hostname-valid certificates and normal CA verification. OpenSearch 3.8 distributions use the bundled Java runtime unless you intentionally supply a supported alternative. Elasticsearch 9.5.3 / Kibana 9.5.3 appears only for equivalent-intent comparisons; its /_security APIs, realms, Spaces and service-account model are not OpenSearch Security-plugin APIs.

Configuration-state rule

The Security plugin stores active configuration in its security system index. The YAML files are initialization/deployment inputs, not automatically live state. Before using securityadmin.sh on an established cluster, back up the current configuration; a broad directory load can overwrite resources created later through REST/Dashboards. Prefer REST/Dashboards for ongoing non-reserved users/roles and apply individual configuration types only when file-based administration is genuinely required.

Execution note

The generation environment does not run the AtlasMart Docker cluster. Requests below are deterministic lab instructions and response fragments are expected shapes/invariants, not fabricated captures. Record your own certificate DN/fingerprint/expiry, authinfo identity, role-resolution evidence, 200/403 behavior, tenant visibility, DLS/FLS results, API-key ID/expiry/revocation, audit events, and p95/p99 latency under authenticated load.

1. Identity and authorization vocabulary

Object Meaning Common mistake
Internal user Username/password identity stored by the Security plugin Embedding the admin user in an application.
Backend role Group/role attribute arriving from an identity backend or attached to a user Assuming it grants access by itself.
Security role OpenSearch permission document: cluster, index, DLS/FLS, tenant permissions Using all_access because a single request failed.
Role mapping Connects users/backend roles/hosts to security roles Mapping an overly broad LDAP group to a powerful role.
Action group Named bundle of low-level actions Treating a convenient broad bundle as automatically least-privilege.

Authentication can succeed while authorization remains empty. That state is useful: it proves the backend accepted the identity but no mapping grants actions. Diagnose mappings rather than adding wildcard permissions.

2. Create the AtlasMart fixture and reader role

Admin creates a strict lab index
PUT atlasmart-products-secure-v1
{
  "settings": {"number_of_shards": 1, "number_of_replicas": 0},
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "sku": {"type":"keyword"},
      "name": {"type":"text", "fields":{"keyword":{"type":"keyword"}}},
      "tenant_id": {"type":"keyword"},
      "category": {"type":"keyword"},
      "price": {"type":"scaled_float", "scaling_factor":100},
      "cost_internal": {"type":"scaled_float", "scaling_factor":100},
      "updated_at": {"type":"date"}
    }
  }
}
Create a direct-API reader role
PUT _plugins/_security/api/roles/atlasmart_reader
{
  "cluster_permissions": [],
  "index_permissions": [
    {
      "index_patterns": ["atlasmart-products-secure-v1"],
      "fls": [],
      "masked_fields": [],
      "allowed_actions": ["read"]
    }
  ],
  "tenant_permissions": []
}

For a backend service that only executes direct searches, no Dashboards tenant permission is needed. If a human must use OpenSearch Dashboards, add the appropriate Dashboards role/tenant permissions separately rather than widening the data role.

3. Create a lab internal user and map it to the role

Internal-user and role-mapping APIs
PUT _plugins/_security/api/internalusers/atlasmart_reader_user
{
  "password": "<SET_OUT_OF_BAND>"
}

PUT _plugins/_security/api/rolesmapping/atlasmart_reader
{
  "users": ["atlasmart_reader_user"],
  "backend_roles": [],
  "hosts": []
}

Do not place the real password in Git, lesson HTML, shell history or screenshots. Use a local secret workflow and rotate/delete the lab user during cleanup. The internal database is excellent for a deterministic lab; a production organization with central identity may instead map backend roles from LDAP/OIDC/JWT or another supported mechanism.

Observe identity and role mapping
curl -k -u "$OS_READER_USER:$OS_READER_PASSWORD"   https://localhost:9201/_plugins/_security/authinfo?pretty

4. Make denials part of the application contract

Allowed read versus forbidden destructive operation
# Expected 200.
curl -k -u "$OS_READER_USER:$OS_READER_PASSWORD"   'https://localhost:9201/atlasmart-products-secure-v1/_search?size=1'

# Expected 403. If this succeeds, the role is too broad.
curl -k -u "$OS_READER_USER:$OS_READER_PASSWORD"   -X DELETE 'https://localhost:9201/atlasmart-products-secure-v1'

A 401 means identity authentication failed. A 403 means the principal authenticated but lacks the requested action. Keep both cases in integration tests because they diagnose different layers.

5. Build a separate ingester role

Index-write role without security administration
PUT _plugins/_security/api/roles/atlasmart_ingester
{
  "cluster_permissions": [],
  "index_permissions": [
    {
      "index_patterns": ["atlasmart-products-secure-v1"],
      "fls": [],
      "masked_fields": [],
      "allowed_actions": ["write"]
    }
  ],
  "tenant_permissions": []
}

The static write action group is convenient, but always inspect whether its included actions match the business contract. If AtlasMart is append-only, a narrower custom action group or API-specific permission set can reduce accidental update/delete capability. Do not blindly use *, indices_all or all_access to silence authorization errors.

6. Tenants do not authorize data

OpenSearch Dashboards tenants isolate saved objects such as dashboards and visualizations. Index permissions still decide what the user can query through OpenSearch. A user can have read access to an atlasmart_ops tenant yet receive 403 from the product index, or have direct API read access to the index while lacking the tenant. Those are independent controls.

Optional human-analyst tenant permission
PUT _plugins/_security/api/roles/atlasmart_analyst
{
  "cluster_permissions": ["cluster_composite_ops_ro"],
  "index_permissions": [{
    "index_patterns": ["atlasmart-products-secure-v1"],
    "allowed_actions": ["read"]
  }],
  "tenant_permissions": [{
    "tenant_patterns": ["atlasmart_ops"],
    "allowed_actions": ["kibana_all_read"]
  }]
}

7. Production judgment

Version-control role intent, not secrets. Review every wildcard. Keep service roles separate from human roles. Monitor authorization failures for both regressions and attack signals. When a request fails after an upgrade, compare the exact missing action against current role/action-group documentation rather than immediately broadening permissions.

Check your understanding

  1. What does a backend role do by itself?
  2. Why test a 403 deliberately?
  3. Is a Dashboards tenant a data-security boundary?
  4. Why avoid all_access for an application?
  5. When should YAML files be preferred over REST for routine users?
Review the answers

1. Nothing until a role mapping connects it to an OpenSearch security role.

2. It proves the authenticated principal cannot perform an operation outside its contract.

3. It is a saved-object/UI tenancy boundary; index authorization is separate.

4. It creates cluster-wide blast radius far beyond normal search or ingest needs.

5. Generally not for routine non-reserved resources; current guidance favors REST/Dashboards after initialization.

Summary and next step

Preserve the evidence, assumptions, version boundaries, and safety checks established in this lesson. Carry them into the next lesson—or, at the end of the capstone, into the production runbook—rather than treating this lesson as an isolated recipe.

References

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.