Design AtlasMart human and service access with narrowly scoped Elasticsearch roles, index privileges, Kibana-space privileges, and observable authorization failures instead of shared superuser credentials.

Users, Roles, Cluster/Index/Application Privileges, Spaces, and Least-Privilege Design

Design equivalent AtlasMart retention intent in Elastic and OpenSearch while documenting non-equivalent lifecycle, tiering, policy-update, simulation, and managed-service behavior.

Intermediate → Advanced115–150 minutesUsers, roles, privileges & Kibana SpacesElasticsearch 9.5.3 · Kibana 9.5.3 · OpenSearch comparison: 3.8.0Last reviewed: September 2026

Learning outcomes

AtlasMart needs a search frontend, an ingest worker, an analyst-facing Kibana space and an operations team. Giving every component the same “app-user” role is convenient until the search frontend can delete indices or the ingest worker can read internal cost fields. This lesson designs privileges around jobs-to-be-done and proves denials are part of the contract.

01

Build separate search and ingest roles with the minimum cluster/index privileges required by their workflows.

02

Distinguish Elasticsearch cluster/index privileges from Kibana application/space privileges.

03

Use users as test principals while planning machine credentials separately.

04

Validate least privilege with positive requests, explicit 403 failures and has-privileges evidence.

05

Explain why Kibana Spaces organize and authorize Kibana content but do not replace Elasticsearch index authorization.

Chapter baseline reviewed 11 September 2026

Examples target the official self-managed Elasticsearch 9.5.3 / Kibana 9.5.3 distribution, reviewed 11 September 2026. The lab reuses atlasmart-es at https://localhost:9200, the generated HTTP CA copied earlier as atlasmart-es-http-ca, and ELASTIC_PASSWORD only as a bootstrap administrator credential. Use curl --cacert; never teach -k as an Elasticsearch security shortcut. The official distribution includes a bundled OpenJDK and Elastic recommends using it; no external JVM is required by this lab. Kibana examples assume 9.5.3 when UI behavior matters. OpenSearch 3.8.0 is mentioned only to mark non-portable boundaries; Chapter 20 teaches its Security plugin separately.

Subscription boundary

Encrypted communications, native/file authentication, core role-based access control, Kibana Spaces, and API-key management are available in the free Basic self-managed distribution. Document/field-level security and Elasticsearch/Kibana audit logging are subscription-sensitive features; verify the current Elastic subscription matrix for your deployment before using them as mandatory controls. The mandatory lab therefore succeeds on Basic with index-level RBAC, separate identities and short-lived API keys, and presents DLS/FLS/audit as an optional extension plus a deterministic fallback.

Execution note

The generation environment does not run the AtlasMart Docker cluster, so requests are deterministic lab instructions and response fragments are expected shapes/invariants, not fabricated captures. Record your own certificate fingerprints/expiry, 401/403 evidence, key identifiers/expiration, audit events where licensed, and application p95/p99 latency under authenticated load.

1. Start from operations, then choose privileges

Principal Required operations Privileges deliberately excluded
atlasmart-search Search/get field metadata on product index write, delete, mappings, security admin, snapshots
atlasmart-ingest Create/index product documents in prepared index read/search if not operationally required; cluster admin; security admin
atlasmart-analyst Read approved data plus Kibana feature/space access index writes and cluster admin
atlasmart-security-admin Manage identities/roles/keys during controlled administration Not embedded in application runtime

Privilege names are versioned API contracts, not English suggestions. Read the current privilege reference and test the exact requests your application issues. For example, Kibana commonly needs view_index_metadata alongside read; a bare search-only role may break field-capability discovery.

2. Create a read/search role

Least-privilege search role
PUT /_security/role/atlasmart_search_role
{
  "cluster": [],
  "indices": [
    {
      "names": ["atlasmart-products-secure-v1"],
      "privileges": ["read", "view_index_metadata"]
    }
  ]
}

POST /_security/user/atlasmart_search_user
{
  "password": "$SET_OUT_OF_BAND",
  "roles": ["atlasmart_search_role"],
  "full_name": "AtlasMart search lab principal"
}

Do not literally send $SET_OUT_OF_BAND. Set the password through your local secure workflow. The HTML intentionally contains no reusable secret.

Prove allowed and forbidden operations
# Allowed: expect HTTP 200.
curl --cacert "$ES_CA" -u "$SEARCH_USER:$SEARCH_PASSWORD" \
  "$ES_URL/atlasmart-products-secure-v1/_search?size=1"

# Forbidden: expect HTTP 403, not 200.
curl --cacert "$ES_CA" -u "$SEARCH_USER:$SEARCH_PASSWORD" \
  -X DELETE "$ES_URL/atlasmart-products-secure-v1"

A 403 is a successful security test: authentication succeeded, then authorization denied the action. A 401 instead points to an authentication problem.

3. Create a distinct ingest role

For a pre-created index with strict mappings, the ingest worker does not need security-management or snapshot privileges. Choose create_doc if the contract is append-only and duplicate IDs should fail rather than overwrite; choose broader write privileges only when the application genuinely updates/deletes documents.

Append-oriented ingest role
PUT /_security/role/atlasmart_ingest_role
{
  "cluster": [],
  "indices": [
    {
      "names": ["atlasmart-products-secure-v1"],
      "privileges": ["create_doc"]
    }
  ]
}

POST /_security/user/atlasmart_ingest_user
{
  "password": "$SET_OUT_OF_BAND",
  "roles": ["atlasmart_ingest_role"]
}
Boundary test
# Expected success: create a new id.
PUT atlasmart-products-secure-v1/_create/P-SEC-1
{
  "sku":"AM-SEC-1", "name":"Secure Lab Keyboard", "category":"office",
  "tenant_id":"tenant-a", "price":109.00, "cost_internal":71.20,
  "updated_at":"2026-09-11T14:00:00Z"
}

# Expected authorization failure if read was not granted.
GET atlasmart-products-secure-v1/_search

4. Measure the role, not your memory of the role

Has-privileges check for the current principal
POST /_security/user/_has_privileges
{
  "cluster": ["manage_security", "manage", "monitor"],
  "index": [
    {
      "names": ["atlasmart-products-secure-v1"],
      "privileges": ["read", "create_doc", "delete_index", "view_index_metadata"]
    }
  ]
}

Use this API in security regression tests. It makes privilege drift visible when roles are changed. A role name such as “read_only” is not evidence; the evaluated privileges and real request outcomes are.

5. Kibana Spaces add UI/saved-object authorization, not index security

A Kibana space scopes saved objects and feature access. Users can see only spaces granted by their roles. However, hiding Discover or placing dashboards in a space does not revoke Elasticsearch index privileges. Conversely, a user can have Elasticsearch read privileges but no Kibana-space access. Keep both layers explicit.

Common mistake

“The Finance dashboard is in a private Kibana space, therefore the underlying index is private.” That is false unless Elasticsearch index privileges also restrict access. Kibana feature visibility is not an index-access control.

When Kibana is part of AtlasMart, manage Kibana feature/space privileges with the Kibana role-management APIs/UI appropriate to 9.5.3 rather than hand-editing opaque application privilege strings without validation.

6. Role accumulation can widen access

Elasticsearch privileges are additive across roles. A narrow AtlasMart role can be defeated by assigning a second broad role. Security review must therefore inspect the complete effective role set. This becomes especially important with DLS/FLS in Lesson 4, where another unrestricted role on the same index can widen what a user sees.

Inspect users and roles during review
GET /_security/user/atlasmart_search_user
GET /_security/role/atlasmart_search_role
GET /_security/user/atlasmart_ingest_user
GET /_security/role/atlasmart_ingest_role

7. Production judgment

Least privilege reduces blast radius but adds operational work: role versioning, deployment ordering, smoke tests and break-glass procedures. Store role definitions as reviewed configuration artifacts. Test them against actual client behavior in staging. Avoid granting broad wildcard index patterns such as * merely to “make Kibana work.” When a service needs a new operation, add the smallest privilege after observing the concrete failure.

Check your understanding

  1. What is the key difference between 401 and 403 in this lab?
  2. Why separate search and ingest identities?
  3. What does view_index_metadata provide?
  4. Do Kibana Spaces secure Elasticsearch indices by themselves?
  5. Why inspect all assigned roles?
Review the answers

1. 401 means the request was not authenticated; 403 means it authenticated but authorization denied the operation.

2. They require different privileges, so compromise of one should not automatically grant the other’s capabilities.

3. Read access to index/data-stream metadata such as field capabilities/mappings needed by many read/Kibana workflows without granting document writes.

4. No. Space/feature privileges govern Kibana content and UI access; index authorization is enforced separately by Elasticsearch roles.

5. Privileges are additive; a second broad role can silently defeat a narrow least-privilege role.

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.