[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-elastic-cloud-access-management":3,"mdc-xx2kko-key":34,"related-repo-elastic-cloud-access-management":3973,"related-org-elastic-cloud-access-management":4056},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":32,"mdContent":33},"cloud-access-management","manage Elastic Cloud organization access","Manage Elastic Cloud organization access: invite users, assign roles to Serverless projects, and create or revoke Cloud API keys. Use when granting, modifying, or auditing user access.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"elastic","Elastic","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Felastic.png",[12,16,19,20],{"name":13,"slug":14,"type":15},"Permissions","permissions","tag",{"name":17,"slug":18,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},"Cloud","cloud",531,"https:\u002F\u002Fgithub.com\u002Felastic\u002Fagent-skills","2026-07-12T07:46:44.946285",null,41,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":31},[],"Official Elastic Skills","https:\u002F\u002Fgithub.com\u002Felastic\u002Fagent-skills\u002Ftree\u002FHEAD\u002Fskills\u002Fcloud\u002Faccess-management","---\nname: cloud-access-management\ndescription: >\n  Manage Elastic Cloud organization access: invite users, assign roles to Serverless\n  projects, and create or revoke Cloud API keys. Use when granting, modifying, or\n  auditing user access.\ncompatibility: >\n  Requires Python 3.8+, network access to the Elastic Cloud API (api.elastic-cloud.com)\n  and optionally to a Serverless Elasticsearch endpoint for custom role operations.\n  Environment variables: EC_API_KEY (required, set by cloud-setup), ELASTICSEARCH_URL\n  and ELASTICSEARCH_API_KEY (required only for custom roles).\nmetadata:\n  author: elastic\n  version: 0.1.0\n---\n\n# Cloud Access Management\n\nManage identity and access for an Elastic Cloud organization and its Serverless projects: invite users, assign\npredefined or custom roles, and manage Cloud API keys.\n\n> **Prerequisite:** This skill assumes the **cloud-setup** skill has already run — `EC_API_KEY` is set in the\n> environment and the organization context is established. If `EC_API_KEY` is missing, instruct the agent to invoke\n> **cloud-setup** first. Do NOT prompt the user for an API key directly.\n\nFor project creation, see the **cloud-create-project** skill. For day-2 project operations (list, update, delete), see\n**cloud-manage-project**. For Elasticsearch-level role management (native users, role mappings, DLS\u002FFLS), see the\n**elasticsearch-authz** skill.\n\nFor detailed API endpoints and request schemas, see [references\u002Fapi-reference.md](references\u002Fapi-reference.md).\n\n## Jobs to Be Done\n\n- Invite a user to the organization and assign them a Serverless project role\n- List organization members and their current role assignments\n- Update a user's roles (org-level or project-level)\n- Remove a user from the organization\n- Create an additional Cloud API key with scoped roles and expiration\n- Create a Cloud API key that can also call Elasticsearch and Kibana APIs on Serverless projects\n- List and revoke Cloud API keys\n- Create a custom role inside a Serverless project with ES cluster, index, and Kibana privileges\n- Assign or remove a custom role for a user on a Serverless project using the Cloud API's `application_roles`\n- Translate a natural-language access request into invite, role, and API key tasks\n\n## Prerequisites and permissions\n\n| Item                 | Description                                                                                             |\n| -------------------- | ------------------------------------------------------------------------------------------------------- |\n| **EC_API_KEY**       | Cloud API key (set by **cloud-setup**). Required for all operations.                                    |\n| **Organization ID**  | Auto-discovered using `GET \u002Forganizations`. Do not ask the user for it.                                 |\n| **Project endpoint** | Elasticsearch endpoint of a Serverless project. Required only for custom role operations.               |\n| **ES credentials**   | API key or credentials with `manage_security` privilege on the project. Required only for custom roles. |\n| **Org owner role**   | Only Organization owners can create and manage Cloud API keys. Required for API key operations.         |\n\nRun `python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members` to verify that `EC_API_KEY` is valid\nand auto-discover the org ID before proceeding with any operation.\n\n### Operation-level permissions\n\nThe following permissions are required for common access management operations in Elastic Cloud Serverless.\n\n| Operation                          | Required permission                                            |\n| ---------------------------------- | -------------------------------------------------------------- |\n| Invite \u002F remove members            | Organization owner (`organization-admin`)                      |\n| Assign or remove roles             | Organization owner (`organization-admin`)                      |\n| Create \u002F revoke Cloud API keys     | Organization owner (`organization-admin`)                      |\n| List members, invitations, or keys | Any organization member                                        |\n| Create \u002F delete custom roles       | `manage_security` cluster privilege on the project ES endpoint |\n\nThis skill does not perform a separate role pre-check. Attempt the requested operation and let the API enforce\nauthorization. If the API returns an authorization error (for example, `403 Forbidden`), stop and ask the user to verify\nthe provided API key permissions.\n\n### Manual setup fallback (when cloud-setup is unavailable)\n\nIf this skill is installed standalone and `cloud-setup` is not available, instruct the user to configure Cloud\nenvironment variables manually before running commands. Never ask the user to paste API keys in chat.\n\n| Variable                | Required    | Description                                                                                       |\n| ----------------------- | ----------- | ------------------------------------------------------------------------------------------------- |\n| `EC_API_KEY`            | Yes         | Elastic Cloud API key with Organization owner role.                                               |\n| `EC_BASE_URL`           | No          | Cloud API base URL (default: `https:\u002F\u002Fapi.elastic-cloud.com`).                                    |\n| `ELASTICSEARCH_URL`     | Conditional | Elasticsearch URL. Required only for custom role operations.                                      |\n| `ELASTICSEARCH_API_KEY` | Conditional | Elasticsearch API key with `manage_security` privilege. Required only for custom role operations. |\n\n> **Note:** If `EC_API_KEY` is missing, or the user does not have a Cloud API key yet, direct the user to generate one\n> at [Elastic Cloud API keys](https:\u002F\u002Fcloud.elastic.co\u002Faccount\u002Fkeys), then configure it locally using the steps below.\n\nPreferred method (agent-friendly): create a `.env` file in the project root:\n\n```bash\nEC_API_KEY=your-api-key\nEC_BASE_URL=https:\u002F\u002Fapi.elastic-cloud.com\n# Only needed for custom role operations against the project Elasticsearch endpoint:\n# ELASTICSEARCH_URL=https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\n# ELASTICSEARCH_API_KEY=\u003Cyour-es-manage-security-api-key>\n```\n\nAll `cloud\u002F*` scripts auto-load `.env` from the working directory.\n\nAlternative: export directly in the terminal:\n\n```bash\nexport EC_API_KEY=\"\u003Cyour-cloud-api-key>\"\nexport EC_BASE_URL=\"https:\u002F\u002Fapi.elastic-cloud.com\"\n# Only needed for custom role operations against the project Elasticsearch endpoint:\n# export ELASTICSEARCH_URL=\"https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\"\n# export ELASTICSEARCH_API_KEY=\"\u003Cyour-es-manage-security-api-key>\"\n```\n\nTerminal exports may not be visible to sandboxed agents running in separate shell sessions, so prefer `.env` when using\nan agent.\n\n## Decomposing Access Requests\n\nWhen the user describes access in natural language (for example, \"add Alice to my search project as a developer\"), break\nthe request into discrete tasks before executing.\n\n### Step 1 — Identify the components\n\n| Component        | Question to answer                                                  |\n| ---------------- | ------------------------------------------------------------------- |\n| **Who**          | New org member (invite) or existing member (role update)?           |\n| **What**         | Which Serverless project(s) or org-level access?                    |\n| **Access level** | Predefined role (Admin\u002FDeveloper\u002FViewer\u002FEditor) or custom role?     |\n| **API key?**     | Does the request also need a Cloud API key for programmatic access? |\n\n### Step 2 — Check if a predefined role fits\n\nConsult the [predefined roles table](#predefined-roles) below. Prefer predefined roles — only create a custom role when\npredefined roles do not provide the required granularity.\n\n### Step 3 — Check existing state\n\nBefore creating or inviting, check what already exists:\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-api-keys\n```\n\nIf the user is already a member, skip the invitation and update their roles instead.\n\n**For API key requests**, only Organization owners can create and manage Cloud API keys. If the authenticated user does\nnot have the `organization-admin` role, API key operations will fail with a 403 error. Review the existing keys returned\nby `list-api-keys`. If an active key already exists **for the same purpose or task** with the required roles and\nsufficient remaining lifetime, reuse it instead of creating a new one. Two keys with identical permissions are fine when\nthey serve different purposes (for example, separate CI pipelines), but creating a second key for the same task is\nunnecessary and increases the management burden.\n\n### Step 4 — Run\n\nRun the appropriate command(s) from `skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py`. Confirm destructive\nactions (remove member, revoke key) with the user before executing.\n\n### Step 5 — Verify\n\nAfter execution, list members or keys again to confirm the change took effect.\n\n## Predefined Roles\n\n### Organization-level roles\n\n| Role               | Cloud API `role_id`  | Description                                |\n| ------------------ | -------------------- | ------------------------------------------ |\n| Organization owner | `organization-admin` | Full admin over org, deployments, projects |\n| Billing admin      | `billing-admin`      | Manage billing details only                |\n\n### Serverless project-level roles\n\n| Role           | Cloud API `role_id` | Available on          | Description                                          |\n| -------------- | ------------------- | --------------------- | ---------------------------------------------------- |\n| Admin          | `admin`             | Search, Obs, Security | Full project management, superuser on sign-in        |\n| Developer      | `developer`         | Search only           | Create indices, API keys, connectors, visualizations |\n| Viewer         | `viewer`            | Search, Obs, Security | Read-only access to project data and features        |\n| Editor         | `editor`            | Obs, Security         | Configure project features, read-only data indices   |\n| Tier 1 analyst | `t1_analyst`        | Security only         | Alert triage, general read, create dashboards        |\n| Tier 2 analyst | `t2_analyst`        | Security only         | Alert triage, begin investigations, create cases     |\n| Tier 3 analyst | `t3_analyst`        | Security only         | Deep investigation, rules, lists, response actions   |\n| SOC manager    | `soc_manager`       | Security only         | Alerts, cases, endpoint policy, response actions     |\n| Rule author    | `rule_author`       | Security only         | Detection engineering, rule creation                 |\n\nProject-level roles are assigned during invitation (`POST \u002Forganizations\u002F{org_id}\u002Finvitations`) or using the role\nassignment update (`POST \u002Fusers\u002F{user_id}\u002Frole_assignments`). See\n[references\u002Fapi-reference.md](references\u002Fapi-reference.md) for the `role_assignments` JSON schema including the\n`project` scope.\n\n## Custom Roles (Serverless)\n\nWhen predefined roles lack the required granularity, create a custom role inside the Serverless project using the\nElasticsearch security API and assign it to users through the Cloud API's `application_roles` field.\n\n> **Security: do not assign a predefined Cloud role separately when using a custom role.** Custom roles implicitly grant\n> Viewer-level Cloud access for the project scope. If you also assign `viewer` (or any other predefined role) as a\n> separate Cloud role assignment for the same project, the user receives the **union** of both roles when they SSO into\n> the project — the Viewer stack role is broader than most custom roles and will override the restrictions you intended.\n\n### How custom role assignment works\n\n- **Predefined roles** (`viewer`, `developer`, `admin`, etc.) are assigned via Cloud APIs (`invite-user`,\n  `assign-role`). When the user SSOs into the project, they receive the stack role mapped to their Cloud role (for\n  example, Cloud `viewer` maps to the `viewer` stack role).\n- **Custom roles** are created in the project via the Elasticsearch security API (`create-custom-role`) and assigned via\n  the Cloud API's `application_roles` field (`assign-custom-role`). When `application_roles` is set, the user gets\n  **only** the specified custom role on SSO — not the default stack role for their Cloud role.\n- The `assign-custom-role` command sets `role_id` to the project-type Viewer role (`elasticsearch-viewer`,\n  `observability-viewer`, or `security-viewer`) and sets `application_roles` to the custom role name. This ensures the\n  user can see and access the project in the Cloud console but receives only the custom role's restricted permissions\n  inside the project.\n- Cloud API keys can also use `application_roles` to gain ES\u002FKibana API access on Serverless projects. See\n  [Cloud API Keys — ES and Kibana API Access](#cloud-api-keys--es-and-kibana-api-access) below for details.\n\n### Canonical custom-role onboarding flow\n\n1. Create the custom role in the project (`create-custom-role`).\n2. Invite the user to the organization if they are not already a member (`invite-user`). Do **not** include project role\n   assignments in the invitation — the custom role assignment in the next step handles project access.\n3. Assign the custom role to the user (`assign-custom-role --user-id ... --project-id ... --custom-role-name ...`).\n4. Verify with `list-members` and `list-roles`.\n\n### Create a custom role\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name marketing-analyst \\\n  --body '{\"cluster\":[],\"indices\":[{\"names\":[\"marketing-*\"],\"privileges\":[\"read\",\"view_index_metadata\"]}]}'\n```\n\nThis calls `PUT \u002F_security\u002Frole\u002F{name}` on the project Elasticsearch endpoint.\n\n### Naming constraints\n\nRole names must begin with a letter or digit and contain only letters, digits, `_`, `-`, and `.`. Run-as privileges are\nnot available in Serverless.\n\n### When to use custom roles versus predefined\n\n| Scenario                                   | Use             |\n| ------------------------------------------ | --------------- |\n| Standard admin\u002Fdeveloper\u002Fviewer access     | Predefined role |\n| Read-only access to specific index pattern | Custom role     |\n| DLS or FLS restrictions                    | Custom role     |\n| Kibana feature-level access control        | Custom role     |\n\nFor advanced DLS\u002FFLS patterns (templated queries, ABAC), see the **elasticsearch-authz** skill.\n\n## Cloud API Keys — ES and Kibana API Access\n\nCloud API keys can now optionally access Elasticsearch and Kibana APIs on Serverless projects, in addition to the Cloud\nAPI. This enables a single credential for both control plane (Cloud API) and data plane (ES\u002FKibana API) operations — for\nexample, a CI pipeline that creates a project via Cloud API and then indexes data via ES API.\n\n### How it works\n\nAdd `application_roles` to the key's `role_assignments` at creation time. This field accepts an array of predefined role\nnames (`admin`, `developer`, `viewer`, and solution-specific roles like `t1_analyst`, `editor`) or custom role names\ncreated in the project via `PUT \u002F_security\u002Frole\u002F{name}`. Predefined roles are available in every project by default.\nCustom roles must be created individually in each project where the key should have access — if a referenced custom role\ndoes not exist in a project, the key silently gets no access there.\n\n### Critical rule: no implicit inheritance\n\nUnlike users, API keys **never** inherit stack roles from their `role_id`. If `application_roles` is omitted or empty,\nthe key has Cloud API access only. Calling an ES or Kibana endpoint with such a key returns **403 Forbidden**. This is\nby design for backward compatibility — existing keys without `application_roles` continue to work as Cloud-only keys.\n\n### Scoping modes\n\n- **Project-scoped** (preferred) — grants access to specific projects or all projects of a given type. Uses the\n  `project` key in `role_assignments` with `application_roles` on each entry. **Use this by default** unless the user\n  explicitly needs cross-project access.\n\n- **Organization-scoped** — grants access to **all current and future projects** in the organization. Uses the\n  `organization` key in `role_assignments` with `application_roles`. **This is the broadest possible data-plane scope.**\n  Only use when the key genuinely needs access to every project (for example, platform automation or cross-project\n  search across the whole org). Always confirm with the user before creating an org-scoped key with `application_roles`,\n  as it grants ES\u002FKibana access to projects that may not exist yet.\n\n> **Custom roles and org-scoped access:** When using a custom role name in `application_roles` with organization-scoped\n> assignments, the custom role must exist in each project where you want the key to have access. If a project does not\n> have that custom role defined (via `PUT \u002F_security\u002Frole\u002F{name}`), the key silently gets no access to that project — no\n> error is raised. For org-wide access, prefer predefined roles (`admin`, `developer`, `viewer`) which are available in\n> every project by default. If you must use custom roles across multiple projects, ensure the role is created in each\n> target project first.\n\n> **Agent guidance:** When a user asks for an API key with ES\u002FKibana access, default to project-scoped assignments. Only\n> suggest organization-scoped `application_roles` if the user explicitly needs access across all projects. Confirm the\n> intent before proceeding — org-scoped access applies to future projects too. If the user specifies a custom role name\n> with org-scoped access, warn them that the role must be defined in each project individually.\n\n### Examples\n\n**Project-scoped key with developer ES access** (using `--stack-access` convenience flag):\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"CI pipeline - ES ingest\" \\\n  --expiration 30d \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"developer\",\"organization_id\":\"$ORG_ID\",\"all\":true}]}}' \\\n  --stack-access developer\n```\n\n**Organization-scoped key with admin ES access** (access to ALL projects — use with caution):\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"Platform automation\" \\\n  --expiration 7d \\\n  --roles '{\"organization\":[{\"role_id\":\"organization-admin\",\"organization_id\":\"$ORG_ID\"}]}' \\\n  --stack-access admin\n```\n\n**Project-scoped key with a custom role** (raw JSON):\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"Marketing ETL\" \\\n  --expiration 14d \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"elasticsearch-viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"],\"application_roles\":[\"marketing-writer\"]}]}}'\n```\n\nReplace `$ORG_ID` and `$PROJECT_ID` with the actual organization and project IDs. Use `list-members` to discover the org\nID.\n\n> **Common mistake:** If your API key gets a 403 when calling an ES or Kibana endpoint, the most likely cause is missing\n> `application_roles`. Unlike users, API keys must have explicit `application_roles` to access the stack — the `role_id`\n> alone is not sufficient.\n\n## Examples\n\n### Invite a user as a Viewer on a search project\n\n**Prompt:** \"Add `alice@example.com` to my search project with read-only access.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py invite-user \\\n  --emails alice@example.com \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}'\n```\n\nReplace `$ORG_ID` and `$PROJECT_ID` with the actual IDs. The Viewer role is assigned when the invitation is accepted.\nFor custom role access, use `assign-custom-role` after the user has accepted the invitation — do not combine a\npredefined role assignment with a custom role for the same project.\n\n### Create a CI\u002FCD API key\n\n**Prompt:** \"Create an API key for our CI pipeline that expires in 30 days with editor access to all deployments.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"CI\u002FCD pipeline\" \\\n  --expiration \"30d\" \\\n  --roles '{\"deployment\":[{\"role_id\":\"deployment-editor\",\"all\":true}]}'\n```\n\nThe actual key value is written to a secure temp file (0600 permissions). The stdout JSON contains a `_secret_file` path\ninstead of the raw secret. Tell the user to retrieve the key from that file — it is shown only once. When the CI\npipeline no longer needs this key, revoke it using `delete-api-key` to avoid unused keys accumulating.\n\n### Create a CI\u002FCD API key with ES access\n\n**Prompt:** \"Create an API key for our CI pipeline that can index data into our search projects.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"CI pipeline - ES ingest\" \\\n  --expiration 30d \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"developer\",\"organization_id\":\"$ORG_ID\",\"all\":true}]}}' \\\n  --stack-access developer\n```\n\nReplace `$ORG_ID` with the actual organization ID. The `--stack-access` flag injects `application_roles: [\"developer\"]`\ninto the role assignments, granting the key developer-level ES\u002FKibana API access on all Elasticsearch projects. Without\n`--stack-access` (or explicit `application_roles` in the JSON), the key would only have Cloud API access and receive 403\non ES\u002FKibana calls.\n\n### Create a custom role for marketing data\n\n**Prompt:** \"Create a role that gives read-only access to marketing-\\* indices on my search project.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name marketing-reader \\\n  --body '{\"cluster\":[],\"indices\":[{\"names\":[\"marketing-*\"],\"privileges\":[\"read\",\"view_index_metadata\"]}]}'\n```\n\nThen assign the custom role to a user using the `assign-custom-role` command, which sets `application_roles` in the\nCloud API role assignment.\n\n### Full custom-role flow for read-only dashboards\n\n**Prompt:** \"Add `bob@example.com` to my search project with read-only dashboard access.\"\n\n```bash\n# 1) Create custom role in the project\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name dashboard-reader \\\n  --body '{\"cluster\":[],\"indices\":[],\"applications\":[{\"application\":\"kibana-.kibana\",\"privileges\":[\"feature_dashboard.read\"],\"resources\":[\"*\"]}]}'\n\n# 2) Invite user to the organization (no project roles — custom role handles access)\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py invite-user \\\n  --emails bob@example.com\n\n# 3) After invitation is accepted, assign the custom role via application_roles\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py assign-custom-role \\\n  --user-id \"$USER_ID\" \\\n  --project-id \"$PROJECT_ID\" \\\n  --project-type elasticsearch \\\n  --custom-role-name dashboard-reader\n```\n\nThe user receives Viewer-level Cloud access (can see the project in the console) and **only** `dashboard-reader`\npermissions when they SSO into the project. Do not also assign `viewer` as a separate Cloud role for this project —\ndoing so would grant the broader Viewer stack role and override the custom role's restrictions.\n\n### Update a user's project role\n\n**Prompt:** \"Promote Bob to admin on our observability project.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py assign-role \\\n  --user-id \"$USER_ID\" \\\n  --roles '{\"project\":{\"observability\":[{\"role_id\":\"admin\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}'\n```\n\nReplace `$USER_ID`, `$ORG_ID`, and `$PROJECT_ID` with actual values. Use `list-members` to look up the user ID. To\nremove a role assignment, use `remove-role-assignment` with the same `--roles` schema.\n\n### List all members and their roles\n\n**Prompt:** \"Show me who has access to my organization.\"\n\n```bash\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members\n```\n\nThe output includes each member's user ID, email, and assigned roles.\n\n## Guidelines\n\n- If `EC_API_KEY` is not set, do not prompt the user — instruct the agent to invoke **cloud-setup** first.\n- Always confirm destructive actions (remove member, revoke key) with the user before executing.\n- Prefer predefined roles over custom roles when they satisfy the access requirement.\n- API keys created here are additional keys for CI\u002FCD, scoped access, or team members. The initial key is managed by\n  **cloud-setup**.\n- **Secrets are never printed to stdout or stderr.** The script replaces sensitive fields (`key`, `token`,\n  `invitation_token`) with a `REDACTED` placeholder in stdout and writes the full unredacted response to a temporary\n  file with 0600 (owner-read-only) permissions. The stdout JSON includes a `_secret_file` path pointing to that file.\n  **Never attempt to read, extract, or summarize the contents of the secret file.** If the user asks for the key, tell\n  them to open the file at the `_secret_file` path. After the user retrieves the secret, advise them to delete the file.\n- Cloud API keys inherit roles at creation and cannot be updated — revoke and recreate to change roles.\n- **API key hygiene — minimize, scope, and expire:**\n  - Before creating a key, always run `list-api-keys` and check whether an existing key **for the same purpose or task**\n    already has the required roles and sufficient remaining lifetime. Keys with identical permissions serving different\n    purposes (for example, two separate CI pipelines) are legitimate — the goal is to avoid redundant keys for the same\n    task.\n  - Always set an `--expiration` that matches the intended task lifetime. Short-lived tasks (CI runs, one-time\n    migrations) should use short-lived keys (for example, `1d`, `7d`).\n  - After a task is complete, prompt the user to revoke any keys that are no longer needed using `delete-api-key`. This\n    applies to both short-lived and long-running keys.\n  - Long-running keys (for example, monitoring pipelines) should still have a defined expiration and be rotated\n    periodically rather than set to never expire.\n- Each organization supports up to 500 active API keys. Default expiration is 3 months.\n- Invitations expire after 72 hours by default. Resend if the user has not accepted.\n- For SAML SSO configuration, refer to\n  [Elastic Cloud SAML docs](https:\u002F\u002Fwww.elastic.co\u002Fdocs\u002Fdeploy-manage\u002Fusers-roles\u002Fcloud-organization\u002Fconfigure-saml-authentication).\n- **Custom role security — do not over-assign:** Never assign a predefined Cloud role (for example, `viewer`) for a\n  project when using `assign-custom-role` for the same project. The custom role assignment implicitly grants\n  Viewer-level Cloud access. Adding a predefined role on top widens the user's in-project permissions beyond what the\n  custom role intended.\n- If a custom role exists but the user cannot access the project, verify the role was assigned with `assign-custom-role`\n  (which uses `application_roles` in the Cloud API). Creating a custom role alone does not grant project access — the\n  Cloud API assignment is required.\n- For network-level security (traffic filters, private links), see the **cloud-network-security** skill.\n- For ES-level role management beyond Cloud roles (native users, DLS\u002FFLS), see **elasticsearch-authz**.\n",{"data":35,"body":39},{"name":4,"description":6,"compatibility":36,"metadata":37},"Requires Python 3.8+, network access to the Elastic Cloud API (api.elastic-cloud.com) and optionally to a Serverless Elasticsearch endpoint for custom role operations. Environment variables: EC_API_KEY (required, set by cloud-setup), ELASTICSEARCH_URL and ELASTICSEARCH_API_KEY (required only for custom roles).\n",{"author":8,"version":38},"0.1.0",{"type":40,"children":41},"root",[42,50,56,100,126,139,146,207,213,342,362,369,374,484,497,503,515,642,672,685,764,784,789,880,892,898,903,909,995,1001,1014,1020,1025,1067,1072,1104,1110,1123,1129,1134,1140,1146,1221,1227,1499,1542,1548,1560,1587,1593,1772,1778,1844,1850,1918,1931,1937,1964,1970,2042,2052,2057,2062,2068,2126,2132,2171,2177,2269,2315,2335,2341,2359,2468,2478,2580,2590,2676,2703,2737,2742,2748,2766,2830,2854,2860,2869,2963,2984,2990,2999,3096,3136,3142,3151,3212,3231,3237,3253,3495,3521,3527,3536,3606,3652,3658,3667,3689,3694,3700,3967],{"type":43,"tag":44,"props":45,"children":46},"element","h1",{"id":4},[47],{"type":48,"value":49},"text","Cloud Access Management",{"type":43,"tag":51,"props":52,"children":53},"p",{},[54],{"type":48,"value":55},"Manage identity and access for an Elastic Cloud organization and its Serverless projects: invite users, assign\npredefined or custom roles, and manage Cloud API keys.",{"type":43,"tag":57,"props":58,"children":59},"blockquote",{},[60],{"type":43,"tag":51,"props":61,"children":62},{},[63,69,71,76,78,85,87,92,94,98],{"type":43,"tag":64,"props":65,"children":66},"strong",{},[67],{"type":48,"value":68},"Prerequisite:",{"type":48,"value":70}," This skill assumes the ",{"type":43,"tag":64,"props":72,"children":73},{},[74],{"type":48,"value":75},"cloud-setup",{"type":48,"value":77}," skill has already run — ",{"type":43,"tag":79,"props":80,"children":82},"code",{"className":81},[],[83],{"type":48,"value":84},"EC_API_KEY",{"type":48,"value":86}," is set in the\nenvironment and the organization context is established. If ",{"type":43,"tag":79,"props":88,"children":90},{"className":89},[],[91],{"type":48,"value":84},{"type":48,"value":93}," is missing, instruct the agent to invoke\n",{"type":43,"tag":64,"props":95,"children":96},{},[97],{"type":48,"value":75},{"type":48,"value":99}," first. Do NOT prompt the user for an API key directly.",{"type":43,"tag":51,"props":101,"children":102},{},[103,105,110,112,117,119,124],{"type":48,"value":104},"For project creation, see the ",{"type":43,"tag":64,"props":106,"children":107},{},[108],{"type":48,"value":109},"cloud-create-project",{"type":48,"value":111}," skill. For day-2 project operations (list, update, delete), see\n",{"type":43,"tag":64,"props":113,"children":114},{},[115],{"type":48,"value":116},"cloud-manage-project",{"type":48,"value":118},". For Elasticsearch-level role management (native users, role mappings, DLS\u002FFLS), see the\n",{"type":43,"tag":64,"props":120,"children":121},{},[122],{"type":48,"value":123},"elasticsearch-authz",{"type":48,"value":125}," skill.",{"type":43,"tag":51,"props":127,"children":128},{},[129,131,137],{"type":48,"value":130},"For detailed API endpoints and request schemas, see ",{"type":43,"tag":132,"props":133,"children":135},"a",{"href":134},"references\u002Fapi-reference.md",[136],{"type":48,"value":134},{"type":48,"value":138},".",{"type":43,"tag":140,"props":141,"children":143},"h2",{"id":142},"jobs-to-be-done",[144],{"type":48,"value":145},"Jobs to Be Done",{"type":43,"tag":147,"props":148,"children":149},"ul",{},[150,156,161,166,171,176,181,186,191,202],{"type":43,"tag":151,"props":152,"children":153},"li",{},[154],{"type":48,"value":155},"Invite a user to the organization and assign them a Serverless project role",{"type":43,"tag":151,"props":157,"children":158},{},[159],{"type":48,"value":160},"List organization members and their current role assignments",{"type":43,"tag":151,"props":162,"children":163},{},[164],{"type":48,"value":165},"Update a user's roles (org-level or project-level)",{"type":43,"tag":151,"props":167,"children":168},{},[169],{"type":48,"value":170},"Remove a user from the organization",{"type":43,"tag":151,"props":172,"children":173},{},[174],{"type":48,"value":175},"Create an additional Cloud API key with scoped roles and expiration",{"type":43,"tag":151,"props":177,"children":178},{},[179],{"type":48,"value":180},"Create a Cloud API key that can also call Elasticsearch and Kibana APIs on Serverless projects",{"type":43,"tag":151,"props":182,"children":183},{},[184],{"type":48,"value":185},"List and revoke Cloud API keys",{"type":43,"tag":151,"props":187,"children":188},{},[189],{"type":48,"value":190},"Create a custom role inside a Serverless project with ES cluster, index, and Kibana privileges",{"type":43,"tag":151,"props":192,"children":193},{},[194,196],{"type":48,"value":195},"Assign or remove a custom role for a user on a Serverless project using the Cloud API's ",{"type":43,"tag":79,"props":197,"children":199},{"className":198},[],[200],{"type":48,"value":201},"application_roles",{"type":43,"tag":151,"props":203,"children":204},{},[205],{"type":48,"value":206},"Translate a natural-language access request into invite, role, and API key tasks",{"type":43,"tag":140,"props":208,"children":210},{"id":209},"prerequisites-and-permissions",[211],{"type":48,"value":212},"Prerequisites and permissions",{"type":43,"tag":214,"props":215,"children":216},"table",{},[217,236],{"type":43,"tag":218,"props":219,"children":220},"thead",{},[221],{"type":43,"tag":222,"props":223,"children":224},"tr",{},[225,231],{"type":43,"tag":226,"props":227,"children":228},"th",{},[229],{"type":48,"value":230},"Item",{"type":43,"tag":226,"props":232,"children":233},{},[234],{"type":48,"value":235},"Description",{"type":43,"tag":237,"props":238,"children":239},"tbody",{},[240,262,286,302,326],{"type":43,"tag":222,"props":241,"children":242},{},[243,251],{"type":43,"tag":244,"props":245,"children":246},"td",{},[247],{"type":43,"tag":64,"props":248,"children":249},{},[250],{"type":48,"value":84},{"type":43,"tag":244,"props":252,"children":253},{},[254,256,260],{"type":48,"value":255},"Cloud API key (set by ",{"type":43,"tag":64,"props":257,"children":258},{},[259],{"type":48,"value":75},{"type":48,"value":261},"). Required for all operations.",{"type":43,"tag":222,"props":263,"children":264},{},[265,273],{"type":43,"tag":244,"props":266,"children":267},{},[268],{"type":43,"tag":64,"props":269,"children":270},{},[271],{"type":48,"value":272},"Organization ID",{"type":43,"tag":244,"props":274,"children":275},{},[276,278,284],{"type":48,"value":277},"Auto-discovered using ",{"type":43,"tag":79,"props":279,"children":281},{"className":280},[],[282],{"type":48,"value":283},"GET \u002Forganizations",{"type":48,"value":285},". Do not ask the user for it.",{"type":43,"tag":222,"props":287,"children":288},{},[289,297],{"type":43,"tag":244,"props":290,"children":291},{},[292],{"type":43,"tag":64,"props":293,"children":294},{},[295],{"type":48,"value":296},"Project endpoint",{"type":43,"tag":244,"props":298,"children":299},{},[300],{"type":48,"value":301},"Elasticsearch endpoint of a Serverless project. Required only for custom role operations.",{"type":43,"tag":222,"props":303,"children":304},{},[305,313],{"type":43,"tag":244,"props":306,"children":307},{},[308],{"type":43,"tag":64,"props":309,"children":310},{},[311],{"type":48,"value":312},"ES credentials",{"type":43,"tag":244,"props":314,"children":315},{},[316,318,324],{"type":48,"value":317},"API key or credentials with ",{"type":43,"tag":79,"props":319,"children":321},{"className":320},[],[322],{"type":48,"value":323},"manage_security",{"type":48,"value":325}," privilege on the project. Required only for custom roles.",{"type":43,"tag":222,"props":327,"children":328},{},[329,337],{"type":43,"tag":244,"props":330,"children":331},{},[332],{"type":43,"tag":64,"props":333,"children":334},{},[335],{"type":48,"value":336},"Org owner role",{"type":43,"tag":244,"props":338,"children":339},{},[340],{"type":48,"value":341},"Only Organization owners can create and manage Cloud API keys. Required for API key operations.",{"type":43,"tag":51,"props":343,"children":344},{},[345,347,353,355,360],{"type":48,"value":346},"Run ",{"type":43,"tag":79,"props":348,"children":350},{"className":349},[],[351],{"type":48,"value":352},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members",{"type":48,"value":354}," to verify that ",{"type":43,"tag":79,"props":356,"children":358},{"className":357},[],[359],{"type":48,"value":84},{"type":48,"value":361}," is valid\nand auto-discover the org ID before proceeding with any operation.",{"type":43,"tag":363,"props":364,"children":366},"h3",{"id":365},"operation-level-permissions",[367],{"type":48,"value":368},"Operation-level permissions",{"type":43,"tag":51,"props":370,"children":371},{},[372],{"type":48,"value":373},"The following permissions are required for common access management operations in Elastic Cloud Serverless.",{"type":43,"tag":214,"props":375,"children":376},{},[377,393],{"type":43,"tag":218,"props":378,"children":379},{},[380],{"type":43,"tag":222,"props":381,"children":382},{},[383,388],{"type":43,"tag":226,"props":384,"children":385},{},[386],{"type":48,"value":387},"Operation",{"type":43,"tag":226,"props":389,"children":390},{},[391],{"type":48,"value":392},"Required permission",{"type":43,"tag":237,"props":394,"children":395},{},[396,417,435,453,466],{"type":43,"tag":222,"props":397,"children":398},{},[399,404],{"type":43,"tag":244,"props":400,"children":401},{},[402],{"type":48,"value":403},"Invite \u002F remove members",{"type":43,"tag":244,"props":405,"children":406},{},[407,409,415],{"type":48,"value":408},"Organization owner (",{"type":43,"tag":79,"props":410,"children":412},{"className":411},[],[413],{"type":48,"value":414},"organization-admin",{"type":48,"value":416},")",{"type":43,"tag":222,"props":418,"children":419},{},[420,425],{"type":43,"tag":244,"props":421,"children":422},{},[423],{"type":48,"value":424},"Assign or remove roles",{"type":43,"tag":244,"props":426,"children":427},{},[428,429,434],{"type":48,"value":408},{"type":43,"tag":79,"props":430,"children":432},{"className":431},[],[433],{"type":48,"value":414},{"type":48,"value":416},{"type":43,"tag":222,"props":436,"children":437},{},[438,443],{"type":43,"tag":244,"props":439,"children":440},{},[441],{"type":48,"value":442},"Create \u002F revoke Cloud API keys",{"type":43,"tag":244,"props":444,"children":445},{},[446,447,452],{"type":48,"value":408},{"type":43,"tag":79,"props":448,"children":450},{"className":449},[],[451],{"type":48,"value":414},{"type":48,"value":416},{"type":43,"tag":222,"props":454,"children":455},{},[456,461],{"type":43,"tag":244,"props":457,"children":458},{},[459],{"type":48,"value":460},"List members, invitations, or keys",{"type":43,"tag":244,"props":462,"children":463},{},[464],{"type":48,"value":465},"Any organization member",{"type":43,"tag":222,"props":467,"children":468},{},[469,474],{"type":43,"tag":244,"props":470,"children":471},{},[472],{"type":48,"value":473},"Create \u002F delete custom roles",{"type":43,"tag":244,"props":475,"children":476},{},[477,482],{"type":43,"tag":79,"props":478,"children":480},{"className":479},[],[481],{"type":48,"value":323},{"type":48,"value":483}," cluster privilege on the project ES endpoint",{"type":43,"tag":51,"props":485,"children":486},{},[487,489,495],{"type":48,"value":488},"This skill does not perform a separate role pre-check. Attempt the requested operation and let the API enforce\nauthorization. If the API returns an authorization error (for example, ",{"type":43,"tag":79,"props":490,"children":492},{"className":491},[],[493],{"type":48,"value":494},"403 Forbidden",{"type":48,"value":496},"), stop and ask the user to verify\nthe provided API key permissions.",{"type":43,"tag":363,"props":498,"children":500},{"id":499},"manual-setup-fallback-when-cloud-setup-is-unavailable",[501],{"type":48,"value":502},"Manual setup fallback (when cloud-setup is unavailable)",{"type":43,"tag":51,"props":504,"children":505},{},[506,508,513],{"type":48,"value":507},"If this skill is installed standalone and ",{"type":43,"tag":79,"props":509,"children":511},{"className":510},[],[512],{"type":48,"value":75},{"type":48,"value":514}," is not available, instruct the user to configure Cloud\nenvironment variables manually before running commands. Never ask the user to paste API keys in chat.",{"type":43,"tag":214,"props":516,"children":517},{},[518,538],{"type":43,"tag":218,"props":519,"children":520},{},[521],{"type":43,"tag":222,"props":522,"children":523},{},[524,529,534],{"type":43,"tag":226,"props":525,"children":526},{},[527],{"type":48,"value":528},"Variable",{"type":43,"tag":226,"props":530,"children":531},{},[532],{"type":48,"value":533},"Required",{"type":43,"tag":226,"props":535,"children":536},{},[537],{"type":48,"value":235},{"type":43,"tag":237,"props":539,"children":540},{},[541,562,592,614],{"type":43,"tag":222,"props":542,"children":543},{},[544,552,557],{"type":43,"tag":244,"props":545,"children":546},{},[547],{"type":43,"tag":79,"props":548,"children":550},{"className":549},[],[551],{"type":48,"value":84},{"type":43,"tag":244,"props":553,"children":554},{},[555],{"type":48,"value":556},"Yes",{"type":43,"tag":244,"props":558,"children":559},{},[560],{"type":48,"value":561},"Elastic Cloud API key with Organization owner role.",{"type":43,"tag":222,"props":563,"children":564},{},[565,574,579],{"type":43,"tag":244,"props":566,"children":567},{},[568],{"type":43,"tag":79,"props":569,"children":571},{"className":570},[],[572],{"type":48,"value":573},"EC_BASE_URL",{"type":43,"tag":244,"props":575,"children":576},{},[577],{"type":48,"value":578},"No",{"type":43,"tag":244,"props":580,"children":581},{},[582,584,590],{"type":48,"value":583},"Cloud API base URL (default: ",{"type":43,"tag":79,"props":585,"children":587},{"className":586},[],[588],{"type":48,"value":589},"https:\u002F\u002Fapi.elastic-cloud.com",{"type":48,"value":591},").",{"type":43,"tag":222,"props":593,"children":594},{},[595,604,609],{"type":43,"tag":244,"props":596,"children":597},{},[598],{"type":43,"tag":79,"props":599,"children":601},{"className":600},[],[602],{"type":48,"value":603},"ELASTICSEARCH_URL",{"type":43,"tag":244,"props":605,"children":606},{},[607],{"type":48,"value":608},"Conditional",{"type":43,"tag":244,"props":610,"children":611},{},[612],{"type":48,"value":613},"Elasticsearch URL. Required only for custom role operations.",{"type":43,"tag":222,"props":615,"children":616},{},[617,626,630],{"type":43,"tag":244,"props":618,"children":619},{},[620],{"type":43,"tag":79,"props":621,"children":623},{"className":622},[],[624],{"type":48,"value":625},"ELASTICSEARCH_API_KEY",{"type":43,"tag":244,"props":627,"children":628},{},[629],{"type":48,"value":608},{"type":43,"tag":244,"props":631,"children":632},{},[633,635,640],{"type":48,"value":634},"Elasticsearch API key with ",{"type":43,"tag":79,"props":636,"children":638},{"className":637},[],[639],{"type":48,"value":323},{"type":48,"value":641}," privilege. Required only for custom role operations.",{"type":43,"tag":57,"props":643,"children":644},{},[645],{"type":43,"tag":51,"props":646,"children":647},{},[648,653,655,660,662,670],{"type":43,"tag":64,"props":649,"children":650},{},[651],{"type":48,"value":652},"Note:",{"type":48,"value":654}," If ",{"type":43,"tag":79,"props":656,"children":658},{"className":657},[],[659],{"type":48,"value":84},{"type":48,"value":661}," is missing, or the user does not have a Cloud API key yet, direct the user to generate one\nat ",{"type":43,"tag":132,"props":663,"children":667},{"href":664,"rel":665},"https:\u002F\u002Fcloud.elastic.co\u002Faccount\u002Fkeys",[666],"nofollow",[668],{"type":48,"value":669},"Elastic Cloud API keys",{"type":48,"value":671},", then configure it locally using the steps below.",{"type":43,"tag":51,"props":673,"children":674},{},[675,677,683],{"type":48,"value":676},"Preferred method (agent-friendly): create a ",{"type":43,"tag":79,"props":678,"children":680},{"className":679},[],[681],{"type":48,"value":682},".env",{"type":48,"value":684}," file in the project root:",{"type":43,"tag":686,"props":687,"children":692},"pre",{"className":688,"code":689,"language":690,"meta":691,"style":691},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","EC_API_KEY=your-api-key\nEC_BASE_URL=https:\u002F\u002Fapi.elastic-cloud.com\n# Only needed for custom role operations against the project Elasticsearch endpoint:\n# ELASTICSEARCH_URL=https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\n# ELASTICSEARCH_API_KEY=\u003Cyour-es-manage-security-api-key>\n","bash","",[693],{"type":43,"tag":79,"props":694,"children":695},{"__ignoreMap":691},[696,719,736,746,755],{"type":43,"tag":697,"props":698,"children":701},"span",{"class":699,"line":700},"line",1,[702,707,713],{"type":43,"tag":697,"props":703,"children":705},{"style":704},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[706],{"type":48,"value":84},{"type":43,"tag":697,"props":708,"children":710},{"style":709},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[711],{"type":48,"value":712},"=",{"type":43,"tag":697,"props":714,"children":716},{"style":715},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[717],{"type":48,"value":718},"your-api-key\n",{"type":43,"tag":697,"props":720,"children":722},{"class":699,"line":721},2,[723,727,731],{"type":43,"tag":697,"props":724,"children":725},{"style":704},[726],{"type":48,"value":573},{"type":43,"tag":697,"props":728,"children":729},{"style":709},[730],{"type":48,"value":712},{"type":43,"tag":697,"props":732,"children":733},{"style":715},[734],{"type":48,"value":735},"https:\u002F\u002Fapi.elastic-cloud.com\n",{"type":43,"tag":697,"props":737,"children":739},{"class":699,"line":738},3,[740],{"type":43,"tag":697,"props":741,"children":743},{"style":742},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[744],{"type":48,"value":745},"# Only needed for custom role operations against the project Elasticsearch endpoint:\n",{"type":43,"tag":697,"props":747,"children":749},{"class":699,"line":748},4,[750],{"type":43,"tag":697,"props":751,"children":752},{"style":742},[753],{"type":48,"value":754},"# ELASTICSEARCH_URL=https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\n",{"type":43,"tag":697,"props":756,"children":758},{"class":699,"line":757},5,[759],{"type":43,"tag":697,"props":760,"children":761},{"style":742},[762],{"type":48,"value":763},"# ELASTICSEARCH_API_KEY=\u003Cyour-es-manage-security-api-key>\n",{"type":43,"tag":51,"props":765,"children":766},{},[767,769,775,777,782],{"type":48,"value":768},"All ",{"type":43,"tag":79,"props":770,"children":772},{"className":771},[],[773],{"type":48,"value":774},"cloud\u002F*",{"type":48,"value":776}," scripts auto-load ",{"type":43,"tag":79,"props":778,"children":780},{"className":779},[],[781],{"type":48,"value":682},{"type":48,"value":783}," from the working directory.",{"type":43,"tag":51,"props":785,"children":786},{},[787],{"type":48,"value":788},"Alternative: export directly in the terminal:",{"type":43,"tag":686,"props":790,"children":792},{"className":688,"code":791,"language":690,"meta":691,"style":691},"export EC_API_KEY=\"\u003Cyour-cloud-api-key>\"\nexport EC_BASE_URL=\"https:\u002F\u002Fapi.elastic-cloud.com\"\n# Only needed for custom role operations against the project Elasticsearch endpoint:\n# export ELASTICSEARCH_URL=\"https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\"\n# export ELASTICSEARCH_API_KEY=\"\u003Cyour-es-manage-security-api-key>\"\n",[793],{"type":43,"tag":79,"props":794,"children":795},{"__ignoreMap":691},[796,829,857,864,872],{"type":43,"tag":697,"props":797,"children":798},{"class":699,"line":700},[799,805,810,814,819,824],{"type":43,"tag":697,"props":800,"children":802},{"style":801},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[803],{"type":48,"value":804},"export",{"type":43,"tag":697,"props":806,"children":807},{"style":704},[808],{"type":48,"value":809}," EC_API_KEY",{"type":43,"tag":697,"props":811,"children":812},{"style":709},[813],{"type":48,"value":712},{"type":43,"tag":697,"props":815,"children":816},{"style":709},[817],{"type":48,"value":818},"\"",{"type":43,"tag":697,"props":820,"children":821},{"style":715},[822],{"type":48,"value":823},"\u003Cyour-cloud-api-key>",{"type":43,"tag":697,"props":825,"children":826},{"style":709},[827],{"type":48,"value":828},"\"\n",{"type":43,"tag":697,"props":830,"children":831},{"class":699,"line":721},[832,836,841,845,849,853],{"type":43,"tag":697,"props":833,"children":834},{"style":801},[835],{"type":48,"value":804},{"type":43,"tag":697,"props":837,"children":838},{"style":704},[839],{"type":48,"value":840}," EC_BASE_URL",{"type":43,"tag":697,"props":842,"children":843},{"style":709},[844],{"type":48,"value":712},{"type":43,"tag":697,"props":846,"children":847},{"style":709},[848],{"type":48,"value":818},{"type":43,"tag":697,"props":850,"children":851},{"style":715},[852],{"type":48,"value":589},{"type":43,"tag":697,"props":854,"children":855},{"style":709},[856],{"type":48,"value":828},{"type":43,"tag":697,"props":858,"children":859},{"class":699,"line":738},[860],{"type":43,"tag":697,"props":861,"children":862},{"style":742},[863],{"type":48,"value":745},{"type":43,"tag":697,"props":865,"children":866},{"class":699,"line":748},[867],{"type":43,"tag":697,"props":868,"children":869},{"style":742},[870],{"type":48,"value":871},"# export ELASTICSEARCH_URL=\"https:\u002F\u002F\u003Cproject-id>.es.\u003Cregion>.elastic-cloud.com\"\n",{"type":43,"tag":697,"props":873,"children":874},{"class":699,"line":757},[875],{"type":43,"tag":697,"props":876,"children":877},{"style":742},[878],{"type":48,"value":879},"# export ELASTICSEARCH_API_KEY=\"\u003Cyour-es-manage-security-api-key>\"\n",{"type":43,"tag":51,"props":881,"children":882},{},[883,885,890],{"type":48,"value":884},"Terminal exports may not be visible to sandboxed agents running in separate shell sessions, so prefer ",{"type":43,"tag":79,"props":886,"children":888},{"className":887},[],[889],{"type":48,"value":682},{"type":48,"value":891}," when using\nan agent.",{"type":43,"tag":140,"props":893,"children":895},{"id":894},"decomposing-access-requests",[896],{"type":48,"value":897},"Decomposing Access Requests",{"type":43,"tag":51,"props":899,"children":900},{},[901],{"type":48,"value":902},"When the user describes access in natural language (for example, \"add Alice to my search project as a developer\"), break\nthe request into discrete tasks before executing.",{"type":43,"tag":363,"props":904,"children":906},{"id":905},"step-1-identify-the-components",[907],{"type":48,"value":908},"Step 1 — Identify the components",{"type":43,"tag":214,"props":910,"children":911},{},[912,928],{"type":43,"tag":218,"props":913,"children":914},{},[915],{"type":43,"tag":222,"props":916,"children":917},{},[918,923],{"type":43,"tag":226,"props":919,"children":920},{},[921],{"type":48,"value":922},"Component",{"type":43,"tag":226,"props":924,"children":925},{},[926],{"type":48,"value":927},"Question to answer",{"type":43,"tag":237,"props":929,"children":930},{},[931,947,963,979],{"type":43,"tag":222,"props":932,"children":933},{},[934,942],{"type":43,"tag":244,"props":935,"children":936},{},[937],{"type":43,"tag":64,"props":938,"children":939},{},[940],{"type":48,"value":941},"Who",{"type":43,"tag":244,"props":943,"children":944},{},[945],{"type":48,"value":946},"New org member (invite) or existing member (role update)?",{"type":43,"tag":222,"props":948,"children":949},{},[950,958],{"type":43,"tag":244,"props":951,"children":952},{},[953],{"type":43,"tag":64,"props":954,"children":955},{},[956],{"type":48,"value":957},"What",{"type":43,"tag":244,"props":959,"children":960},{},[961],{"type":48,"value":962},"Which Serverless project(s) or org-level access?",{"type":43,"tag":222,"props":964,"children":965},{},[966,974],{"type":43,"tag":244,"props":967,"children":968},{},[969],{"type":43,"tag":64,"props":970,"children":971},{},[972],{"type":48,"value":973},"Access level",{"type":43,"tag":244,"props":975,"children":976},{},[977],{"type":48,"value":978},"Predefined role (Admin\u002FDeveloper\u002FViewer\u002FEditor) or custom role?",{"type":43,"tag":222,"props":980,"children":981},{},[982,990],{"type":43,"tag":244,"props":983,"children":984},{},[985],{"type":43,"tag":64,"props":986,"children":987},{},[988],{"type":48,"value":989},"API key?",{"type":43,"tag":244,"props":991,"children":992},{},[993],{"type":48,"value":994},"Does the request also need a Cloud API key for programmatic access?",{"type":43,"tag":363,"props":996,"children":998},{"id":997},"step-2-check-if-a-predefined-role-fits",[999],{"type":48,"value":1000},"Step 2 — Check if a predefined role fits",{"type":43,"tag":51,"props":1002,"children":1003},{},[1004,1006,1012],{"type":48,"value":1005},"Consult the ",{"type":43,"tag":132,"props":1007,"children":1009},{"href":1008},"#predefined-roles",[1010],{"type":48,"value":1011},"predefined roles table",{"type":48,"value":1013}," below. Prefer predefined roles — only create a custom role when\npredefined roles do not provide the required granularity.",{"type":43,"tag":363,"props":1015,"children":1017},{"id":1016},"step-3-check-existing-state",[1018],{"type":48,"value":1019},"Step 3 — Check existing state",{"type":43,"tag":51,"props":1021,"children":1022},{},[1023],{"type":48,"value":1024},"Before creating or inviting, check what already exists:",{"type":43,"tag":686,"props":1026,"children":1028},{"className":688,"code":1027,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-api-keys\n",[1029],{"type":43,"tag":79,"props":1030,"children":1031},{"__ignoreMap":691},[1032,1051],{"type":43,"tag":697,"props":1033,"children":1034},{"class":699,"line":700},[1035,1041,1046],{"type":43,"tag":697,"props":1036,"children":1038},{"style":1037},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1039],{"type":48,"value":1040},"python3",{"type":43,"tag":697,"props":1042,"children":1043},{"style":715},[1044],{"type":48,"value":1045}," skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py",{"type":43,"tag":697,"props":1047,"children":1048},{"style":715},[1049],{"type":48,"value":1050}," list-members\n",{"type":43,"tag":697,"props":1052,"children":1053},{"class":699,"line":721},[1054,1058,1062],{"type":43,"tag":697,"props":1055,"children":1056},{"style":1037},[1057],{"type":48,"value":1040},{"type":43,"tag":697,"props":1059,"children":1060},{"style":715},[1061],{"type":48,"value":1045},{"type":43,"tag":697,"props":1063,"children":1064},{"style":715},[1065],{"type":48,"value":1066}," list-api-keys\n",{"type":43,"tag":51,"props":1068,"children":1069},{},[1070],{"type":48,"value":1071},"If the user is already a member, skip the invitation and update their roles instead.",{"type":43,"tag":51,"props":1073,"children":1074},{},[1075,1080,1082,1087,1089,1095,1097,1102],{"type":43,"tag":64,"props":1076,"children":1077},{},[1078],{"type":48,"value":1079},"For API key requests",{"type":48,"value":1081},", only Organization owners can create and manage Cloud API keys. If the authenticated user does\nnot have the ",{"type":43,"tag":79,"props":1083,"children":1085},{"className":1084},[],[1086],{"type":48,"value":414},{"type":48,"value":1088}," role, API key operations will fail with a 403 error. Review the existing keys returned\nby ",{"type":43,"tag":79,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":48,"value":1094},"list-api-keys",{"type":48,"value":1096},". If an active key already exists ",{"type":43,"tag":64,"props":1098,"children":1099},{},[1100],{"type":48,"value":1101},"for the same purpose or task",{"type":48,"value":1103}," with the required roles and\nsufficient remaining lifetime, reuse it instead of creating a new one. Two keys with identical permissions are fine when\nthey serve different purposes (for example, separate CI pipelines), but creating a second key for the same task is\nunnecessary and increases the management burden.",{"type":43,"tag":363,"props":1105,"children":1107},{"id":1106},"step-4-run",[1108],{"type":48,"value":1109},"Step 4 — Run",{"type":43,"tag":51,"props":1111,"children":1112},{},[1113,1115,1121],{"type":48,"value":1114},"Run the appropriate command(s) from ",{"type":43,"tag":79,"props":1116,"children":1118},{"className":1117},[],[1119],{"type":48,"value":1120},"skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py",{"type":48,"value":1122},". Confirm destructive\nactions (remove member, revoke key) with the user before executing.",{"type":43,"tag":363,"props":1124,"children":1126},{"id":1125},"step-5-verify",[1127],{"type":48,"value":1128},"Step 5 — Verify",{"type":43,"tag":51,"props":1130,"children":1131},{},[1132],{"type":48,"value":1133},"After execution, list members or keys again to confirm the change took effect.",{"type":43,"tag":140,"props":1135,"children":1137},{"id":1136},"predefined-roles",[1138],{"type":48,"value":1139},"Predefined Roles",{"type":43,"tag":363,"props":1141,"children":1143},{"id":1142},"organization-level-roles",[1144],{"type":48,"value":1145},"Organization-level roles",{"type":43,"tag":214,"props":1147,"children":1148},{},[1149,1175],{"type":43,"tag":218,"props":1150,"children":1151},{},[1152],{"type":43,"tag":222,"props":1153,"children":1154},{},[1155,1160,1171],{"type":43,"tag":226,"props":1156,"children":1157},{},[1158],{"type":48,"value":1159},"Role",{"type":43,"tag":226,"props":1161,"children":1162},{},[1163,1165],{"type":48,"value":1164},"Cloud API ",{"type":43,"tag":79,"props":1166,"children":1168},{"className":1167},[],[1169],{"type":48,"value":1170},"role_id",{"type":43,"tag":226,"props":1172,"children":1173},{},[1174],{"type":48,"value":235},{"type":43,"tag":237,"props":1176,"children":1177},{},[1178,1199],{"type":43,"tag":222,"props":1179,"children":1180},{},[1181,1186,1194],{"type":43,"tag":244,"props":1182,"children":1183},{},[1184],{"type":48,"value":1185},"Organization owner",{"type":43,"tag":244,"props":1187,"children":1188},{},[1189],{"type":43,"tag":79,"props":1190,"children":1192},{"className":1191},[],[1193],{"type":48,"value":414},{"type":43,"tag":244,"props":1195,"children":1196},{},[1197],{"type":48,"value":1198},"Full admin over org, deployments, projects",{"type":43,"tag":222,"props":1200,"children":1201},{},[1202,1207,1216],{"type":43,"tag":244,"props":1203,"children":1204},{},[1205],{"type":48,"value":1206},"Billing admin",{"type":43,"tag":244,"props":1208,"children":1209},{},[1210],{"type":43,"tag":79,"props":1211,"children":1213},{"className":1212},[],[1214],{"type":48,"value":1215},"billing-admin",{"type":43,"tag":244,"props":1217,"children":1218},{},[1219],{"type":48,"value":1220},"Manage billing details only",{"type":43,"tag":363,"props":1222,"children":1224},{"id":1223},"serverless-project-level-roles",[1225],{"type":48,"value":1226},"Serverless project-level roles",{"type":43,"tag":214,"props":1228,"children":1229},{},[1230,1258],{"type":43,"tag":218,"props":1231,"children":1232},{},[1233],{"type":43,"tag":222,"props":1234,"children":1235},{},[1236,1240,1249,1254],{"type":43,"tag":226,"props":1237,"children":1238},{},[1239],{"type":48,"value":1159},{"type":43,"tag":226,"props":1241,"children":1242},{},[1243,1244],{"type":48,"value":1164},{"type":43,"tag":79,"props":1245,"children":1247},{"className":1246},[],[1248],{"type":48,"value":1170},{"type":43,"tag":226,"props":1250,"children":1251},{},[1252],{"type":48,"value":1253},"Available on",{"type":43,"tag":226,"props":1255,"children":1256},{},[1257],{"type":48,"value":235},{"type":43,"tag":237,"props":1259,"children":1260},{},[1261,1288,1315,1341,1368,1395,1421,1447,1473],{"type":43,"tag":222,"props":1262,"children":1263},{},[1264,1269,1278,1283],{"type":43,"tag":244,"props":1265,"children":1266},{},[1267],{"type":48,"value":1268},"Admin",{"type":43,"tag":244,"props":1270,"children":1271},{},[1272],{"type":43,"tag":79,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":48,"value":1277},"admin",{"type":43,"tag":244,"props":1279,"children":1280},{},[1281],{"type":48,"value":1282},"Search, Obs, Security",{"type":43,"tag":244,"props":1284,"children":1285},{},[1286],{"type":48,"value":1287},"Full project management, superuser on sign-in",{"type":43,"tag":222,"props":1289,"children":1290},{},[1291,1296,1305,1310],{"type":43,"tag":244,"props":1292,"children":1293},{},[1294],{"type":48,"value":1295},"Developer",{"type":43,"tag":244,"props":1297,"children":1298},{},[1299],{"type":43,"tag":79,"props":1300,"children":1302},{"className":1301},[],[1303],{"type":48,"value":1304},"developer",{"type":43,"tag":244,"props":1306,"children":1307},{},[1308],{"type":48,"value":1309},"Search only",{"type":43,"tag":244,"props":1311,"children":1312},{},[1313],{"type":48,"value":1314},"Create indices, API keys, connectors, visualizations",{"type":43,"tag":222,"props":1316,"children":1317},{},[1318,1323,1332,1336],{"type":43,"tag":244,"props":1319,"children":1320},{},[1321],{"type":48,"value":1322},"Viewer",{"type":43,"tag":244,"props":1324,"children":1325},{},[1326],{"type":43,"tag":79,"props":1327,"children":1329},{"className":1328},[],[1330],{"type":48,"value":1331},"viewer",{"type":43,"tag":244,"props":1333,"children":1334},{},[1335],{"type":48,"value":1282},{"type":43,"tag":244,"props":1337,"children":1338},{},[1339],{"type":48,"value":1340},"Read-only access to project data and features",{"type":43,"tag":222,"props":1342,"children":1343},{},[1344,1349,1358,1363],{"type":43,"tag":244,"props":1345,"children":1346},{},[1347],{"type":48,"value":1348},"Editor",{"type":43,"tag":244,"props":1350,"children":1351},{},[1352],{"type":43,"tag":79,"props":1353,"children":1355},{"className":1354},[],[1356],{"type":48,"value":1357},"editor",{"type":43,"tag":244,"props":1359,"children":1360},{},[1361],{"type":48,"value":1362},"Obs, Security",{"type":43,"tag":244,"props":1364,"children":1365},{},[1366],{"type":48,"value":1367},"Configure project features, read-only data indices",{"type":43,"tag":222,"props":1369,"children":1370},{},[1371,1376,1385,1390],{"type":43,"tag":244,"props":1372,"children":1373},{},[1374],{"type":48,"value":1375},"Tier 1 analyst",{"type":43,"tag":244,"props":1377,"children":1378},{},[1379],{"type":43,"tag":79,"props":1380,"children":1382},{"className":1381},[],[1383],{"type":48,"value":1384},"t1_analyst",{"type":43,"tag":244,"props":1386,"children":1387},{},[1388],{"type":48,"value":1389},"Security only",{"type":43,"tag":244,"props":1391,"children":1392},{},[1393],{"type":48,"value":1394},"Alert triage, general read, create dashboards",{"type":43,"tag":222,"props":1396,"children":1397},{},[1398,1403,1412,1416],{"type":43,"tag":244,"props":1399,"children":1400},{},[1401],{"type":48,"value":1402},"Tier 2 analyst",{"type":43,"tag":244,"props":1404,"children":1405},{},[1406],{"type":43,"tag":79,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":48,"value":1411},"t2_analyst",{"type":43,"tag":244,"props":1413,"children":1414},{},[1415],{"type":48,"value":1389},{"type":43,"tag":244,"props":1417,"children":1418},{},[1419],{"type":48,"value":1420},"Alert triage, begin investigations, create cases",{"type":43,"tag":222,"props":1422,"children":1423},{},[1424,1429,1438,1442],{"type":43,"tag":244,"props":1425,"children":1426},{},[1427],{"type":48,"value":1428},"Tier 3 analyst",{"type":43,"tag":244,"props":1430,"children":1431},{},[1432],{"type":43,"tag":79,"props":1433,"children":1435},{"className":1434},[],[1436],{"type":48,"value":1437},"t3_analyst",{"type":43,"tag":244,"props":1439,"children":1440},{},[1441],{"type":48,"value":1389},{"type":43,"tag":244,"props":1443,"children":1444},{},[1445],{"type":48,"value":1446},"Deep investigation, rules, lists, response actions",{"type":43,"tag":222,"props":1448,"children":1449},{},[1450,1455,1464,1468],{"type":43,"tag":244,"props":1451,"children":1452},{},[1453],{"type":48,"value":1454},"SOC manager",{"type":43,"tag":244,"props":1456,"children":1457},{},[1458],{"type":43,"tag":79,"props":1459,"children":1461},{"className":1460},[],[1462],{"type":48,"value":1463},"soc_manager",{"type":43,"tag":244,"props":1465,"children":1466},{},[1467],{"type":48,"value":1389},{"type":43,"tag":244,"props":1469,"children":1470},{},[1471],{"type":48,"value":1472},"Alerts, cases, endpoint policy, response actions",{"type":43,"tag":222,"props":1474,"children":1475},{},[1476,1481,1490,1494],{"type":43,"tag":244,"props":1477,"children":1478},{},[1479],{"type":48,"value":1480},"Rule author",{"type":43,"tag":244,"props":1482,"children":1483},{},[1484],{"type":43,"tag":79,"props":1485,"children":1487},{"className":1486},[],[1488],{"type":48,"value":1489},"rule_author",{"type":43,"tag":244,"props":1491,"children":1492},{},[1493],{"type":48,"value":1389},{"type":43,"tag":244,"props":1495,"children":1496},{},[1497],{"type":48,"value":1498},"Detection engineering, rule creation",{"type":43,"tag":51,"props":1500,"children":1501},{},[1502,1504,1510,1512,1518,1520,1524,1526,1532,1534,1540],{"type":48,"value":1503},"Project-level roles are assigned during invitation (",{"type":43,"tag":79,"props":1505,"children":1507},{"className":1506},[],[1508],{"type":48,"value":1509},"POST \u002Forganizations\u002F{org_id}\u002Finvitations",{"type":48,"value":1511},") or using the role\nassignment update (",{"type":43,"tag":79,"props":1513,"children":1515},{"className":1514},[],[1516],{"type":48,"value":1517},"POST \u002Fusers\u002F{user_id}\u002Frole_assignments",{"type":48,"value":1519},"). See\n",{"type":43,"tag":132,"props":1521,"children":1522},{"href":134},[1523],{"type":48,"value":134},{"type":48,"value":1525}," for the ",{"type":43,"tag":79,"props":1527,"children":1529},{"className":1528},[],[1530],{"type":48,"value":1531},"role_assignments",{"type":48,"value":1533}," JSON schema including the\n",{"type":43,"tag":79,"props":1535,"children":1537},{"className":1536},[],[1538],{"type":48,"value":1539},"project",{"type":48,"value":1541}," scope.",{"type":43,"tag":140,"props":1543,"children":1545},{"id":1544},"custom-roles-serverless",[1546],{"type":48,"value":1547},"Custom Roles (Serverless)",{"type":43,"tag":51,"props":1549,"children":1550},{},[1551,1553,1558],{"type":48,"value":1552},"When predefined roles lack the required granularity, create a custom role inside the Serverless project using the\nElasticsearch security API and assign it to users through the Cloud API's ",{"type":43,"tag":79,"props":1554,"children":1556},{"className":1555},[],[1557],{"type":48,"value":201},{"type":48,"value":1559}," field.",{"type":43,"tag":57,"props":1561,"children":1562},{},[1563],{"type":43,"tag":51,"props":1564,"children":1565},{},[1566,1571,1573,1578,1580,1585],{"type":43,"tag":64,"props":1567,"children":1568},{},[1569],{"type":48,"value":1570},"Security: do not assign a predefined Cloud role separately when using a custom role.",{"type":48,"value":1572}," Custom roles implicitly grant\nViewer-level Cloud access for the project scope. If you also assign ",{"type":43,"tag":79,"props":1574,"children":1576},{"className":1575},[],[1577],{"type":48,"value":1331},{"type":48,"value":1579}," (or any other predefined role) as a\nseparate Cloud role assignment for the same project, the user receives the ",{"type":43,"tag":64,"props":1581,"children":1582},{},[1583],{"type":48,"value":1584},"union",{"type":48,"value":1586}," of both roles when they SSO into\nthe project — the Viewer stack role is broader than most custom roles and will override the restrictions you intended.",{"type":43,"tag":363,"props":1588,"children":1590},{"id":1589},"how-custom-role-assignment-works",[1591],{"type":48,"value":1592},"How custom role assignment works",{"type":43,"tag":147,"props":1594,"children":1595},{},[1596,1656,1703,1752],{"type":43,"tag":151,"props":1597,"children":1598},{},[1599,1604,1606,1611,1613,1618,1619,1624,1626,1632,1634,1640,1642,1647,1649,1654],{"type":43,"tag":64,"props":1600,"children":1601},{},[1602],{"type":48,"value":1603},"Predefined roles",{"type":48,"value":1605}," (",{"type":43,"tag":79,"props":1607,"children":1609},{"className":1608},[],[1610],{"type":48,"value":1331},{"type":48,"value":1612},", ",{"type":43,"tag":79,"props":1614,"children":1616},{"className":1615},[],[1617],{"type":48,"value":1304},{"type":48,"value":1612},{"type":43,"tag":79,"props":1620,"children":1622},{"className":1621},[],[1623],{"type":48,"value":1277},{"type":48,"value":1625},", etc.) are assigned via Cloud APIs (",{"type":43,"tag":79,"props":1627,"children":1629},{"className":1628},[],[1630],{"type":48,"value":1631},"invite-user",{"type":48,"value":1633},",\n",{"type":43,"tag":79,"props":1635,"children":1637},{"className":1636},[],[1638],{"type":48,"value":1639},"assign-role",{"type":48,"value":1641},"). When the user SSOs into the project, they receive the stack role mapped to their Cloud role (for\nexample, Cloud ",{"type":43,"tag":79,"props":1643,"children":1645},{"className":1644},[],[1646],{"type":48,"value":1331},{"type":48,"value":1648}," maps to the ",{"type":43,"tag":79,"props":1650,"children":1652},{"className":1651},[],[1653],{"type":48,"value":1331},{"type":48,"value":1655}," stack role).",{"type":43,"tag":151,"props":1657,"children":1658},{},[1659,1664,1666,1672,1674,1679,1681,1687,1689,1694,1696,1701],{"type":43,"tag":64,"props":1660,"children":1661},{},[1662],{"type":48,"value":1663},"Custom roles",{"type":48,"value":1665}," are created in the project via the Elasticsearch security API (",{"type":43,"tag":79,"props":1667,"children":1669},{"className":1668},[],[1670],{"type":48,"value":1671},"create-custom-role",{"type":48,"value":1673},") and assigned via\nthe Cloud API's ",{"type":43,"tag":79,"props":1675,"children":1677},{"className":1676},[],[1678],{"type":48,"value":201},{"type":48,"value":1680}," field (",{"type":43,"tag":79,"props":1682,"children":1684},{"className":1683},[],[1685],{"type":48,"value":1686},"assign-custom-role",{"type":48,"value":1688},"). When ",{"type":43,"tag":79,"props":1690,"children":1692},{"className":1691},[],[1693],{"type":48,"value":201},{"type":48,"value":1695}," is set, the user gets\n",{"type":43,"tag":64,"props":1697,"children":1698},{},[1699],{"type":48,"value":1700},"only",{"type":48,"value":1702}," the specified custom role on SSO — not the default stack role for their Cloud role.",{"type":43,"tag":151,"props":1704,"children":1705},{},[1706,1708,1713,1715,1720,1722,1728,1729,1735,1737,1743,1745,1750],{"type":48,"value":1707},"The ",{"type":43,"tag":79,"props":1709,"children":1711},{"className":1710},[],[1712],{"type":48,"value":1686},{"type":48,"value":1714}," command sets ",{"type":43,"tag":79,"props":1716,"children":1718},{"className":1717},[],[1719],{"type":48,"value":1170},{"type":48,"value":1721}," to the project-type Viewer role (",{"type":43,"tag":79,"props":1723,"children":1725},{"className":1724},[],[1726],{"type":48,"value":1727},"elasticsearch-viewer",{"type":48,"value":1633},{"type":43,"tag":79,"props":1730,"children":1732},{"className":1731},[],[1733],{"type":48,"value":1734},"observability-viewer",{"type":48,"value":1736},", or ",{"type":43,"tag":79,"props":1738,"children":1740},{"className":1739},[],[1741],{"type":48,"value":1742},"security-viewer",{"type":48,"value":1744},") and sets ",{"type":43,"tag":79,"props":1746,"children":1748},{"className":1747},[],[1749],{"type":48,"value":201},{"type":48,"value":1751}," to the custom role name. This ensures the\nuser can see and access the project in the Cloud console but receives only the custom role's restricted permissions\ninside the project.",{"type":43,"tag":151,"props":1753,"children":1754},{},[1755,1757,1762,1764,1770],{"type":48,"value":1756},"Cloud API keys can also use ",{"type":43,"tag":79,"props":1758,"children":1760},{"className":1759},[],[1761],{"type":48,"value":201},{"type":48,"value":1763}," to gain ES\u002FKibana API access on Serverless projects. See\n",{"type":43,"tag":132,"props":1765,"children":1767},{"href":1766},"#cloud-api-keys--es-and-kibana-api-access",[1768],{"type":48,"value":1769},"Cloud API Keys — ES and Kibana API Access",{"type":48,"value":1771}," below for details.",{"type":43,"tag":363,"props":1773,"children":1775},{"id":1774},"canonical-custom-role-onboarding-flow",[1776],{"type":48,"value":1777},"Canonical custom-role onboarding flow",{"type":43,"tag":1779,"props":1780,"children":1781},"ol",{},[1782,1793,1812,1824],{"type":43,"tag":151,"props":1783,"children":1784},{},[1785,1787,1792],{"type":48,"value":1786},"Create the custom role in the project (",{"type":43,"tag":79,"props":1788,"children":1790},{"className":1789},[],[1791],{"type":48,"value":1671},{"type":48,"value":591},{"type":43,"tag":151,"props":1794,"children":1795},{},[1796,1798,1803,1805,1810],{"type":48,"value":1797},"Invite the user to the organization if they are not already a member (",{"type":43,"tag":79,"props":1799,"children":1801},{"className":1800},[],[1802],{"type":48,"value":1631},{"type":48,"value":1804},"). Do ",{"type":43,"tag":64,"props":1806,"children":1807},{},[1808],{"type":48,"value":1809},"not",{"type":48,"value":1811}," include project role\nassignments in the invitation — the custom role assignment in the next step handles project access.",{"type":43,"tag":151,"props":1813,"children":1814},{},[1815,1817,1823],{"type":48,"value":1816},"Assign the custom role to the user (",{"type":43,"tag":79,"props":1818,"children":1820},{"className":1819},[],[1821],{"type":48,"value":1822},"assign-custom-role --user-id ... --project-id ... --custom-role-name ...",{"type":48,"value":591},{"type":43,"tag":151,"props":1825,"children":1826},{},[1827,1829,1835,1837,1843],{"type":48,"value":1828},"Verify with ",{"type":43,"tag":79,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":48,"value":1834},"list-members",{"type":48,"value":1836}," and ",{"type":43,"tag":79,"props":1838,"children":1840},{"className":1839},[],[1841],{"type":48,"value":1842},"list-roles",{"type":48,"value":138},{"type":43,"tag":363,"props":1845,"children":1847},{"id":1846},"create-a-custom-role",[1848],{"type":48,"value":1849},"Create a custom role",{"type":43,"tag":686,"props":1851,"children":1853},{"className":688,"code":1852,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name marketing-analyst \\\n  --body '{\"cluster\":[],\"indices\":[{\"names\":[\"marketing-*\"],\"privileges\":[\"read\",\"view_index_metadata\"]}]}'\n",[1854],{"type":43,"tag":79,"props":1855,"children":1856},{"__ignoreMap":691},[1857,1878,1895],{"type":43,"tag":697,"props":1858,"children":1859},{"class":699,"line":700},[1860,1864,1868,1873],{"type":43,"tag":697,"props":1861,"children":1862},{"style":1037},[1863],{"type":48,"value":1040},{"type":43,"tag":697,"props":1865,"children":1866},{"style":715},[1867],{"type":48,"value":1045},{"type":43,"tag":697,"props":1869,"children":1870},{"style":715},[1871],{"type":48,"value":1872}," create-custom-role",{"type":43,"tag":697,"props":1874,"children":1875},{"style":704},[1876],{"type":48,"value":1877}," \\\n",{"type":43,"tag":697,"props":1879,"children":1880},{"class":699,"line":721},[1881,1886,1891],{"type":43,"tag":697,"props":1882,"children":1883},{"style":715},[1884],{"type":48,"value":1885},"  --role-name",{"type":43,"tag":697,"props":1887,"children":1888},{"style":715},[1889],{"type":48,"value":1890}," marketing-analyst",{"type":43,"tag":697,"props":1892,"children":1893},{"style":704},[1894],{"type":48,"value":1877},{"type":43,"tag":697,"props":1896,"children":1897},{"class":699,"line":738},[1898,1903,1908,1913],{"type":43,"tag":697,"props":1899,"children":1900},{"style":715},[1901],{"type":48,"value":1902},"  --body",{"type":43,"tag":697,"props":1904,"children":1905},{"style":709},[1906],{"type":48,"value":1907}," '",{"type":43,"tag":697,"props":1909,"children":1910},{"style":715},[1911],{"type":48,"value":1912},"{\"cluster\":[],\"indices\":[{\"names\":[\"marketing-*\"],\"privileges\":[\"read\",\"view_index_metadata\"]}]}",{"type":43,"tag":697,"props":1914,"children":1915},{"style":709},[1916],{"type":48,"value":1917},"'\n",{"type":43,"tag":51,"props":1919,"children":1920},{},[1921,1923,1929],{"type":48,"value":1922},"This calls ",{"type":43,"tag":79,"props":1924,"children":1926},{"className":1925},[],[1927],{"type":48,"value":1928},"PUT \u002F_security\u002Frole\u002F{name}",{"type":48,"value":1930}," on the project Elasticsearch endpoint.",{"type":43,"tag":363,"props":1932,"children":1934},{"id":1933},"naming-constraints",[1935],{"type":48,"value":1936},"Naming constraints",{"type":43,"tag":51,"props":1938,"children":1939},{},[1940,1942,1948,1949,1955,1957,1962],{"type":48,"value":1941},"Role names must begin with a letter or digit and contain only letters, digits, ",{"type":43,"tag":79,"props":1943,"children":1945},{"className":1944},[],[1946],{"type":48,"value":1947},"_",{"type":48,"value":1612},{"type":43,"tag":79,"props":1950,"children":1952},{"className":1951},[],[1953],{"type":48,"value":1954},"-",{"type":48,"value":1956},", and ",{"type":43,"tag":79,"props":1958,"children":1960},{"className":1959},[],[1961],{"type":48,"value":138},{"type":48,"value":1963},". Run-as privileges are\nnot available in Serverless.",{"type":43,"tag":363,"props":1965,"children":1967},{"id":1966},"when-to-use-custom-roles-versus-predefined",[1968],{"type":48,"value":1969},"When to use custom roles versus predefined",{"type":43,"tag":214,"props":1971,"children":1972},{},[1973,1989],{"type":43,"tag":218,"props":1974,"children":1975},{},[1976],{"type":43,"tag":222,"props":1977,"children":1978},{},[1979,1984],{"type":43,"tag":226,"props":1980,"children":1981},{},[1982],{"type":48,"value":1983},"Scenario",{"type":43,"tag":226,"props":1985,"children":1986},{},[1987],{"type":48,"value":1988},"Use",{"type":43,"tag":237,"props":1990,"children":1991},{},[1992,2005,2018,2030],{"type":43,"tag":222,"props":1993,"children":1994},{},[1995,2000],{"type":43,"tag":244,"props":1996,"children":1997},{},[1998],{"type":48,"value":1999},"Standard admin\u002Fdeveloper\u002Fviewer access",{"type":43,"tag":244,"props":2001,"children":2002},{},[2003],{"type":48,"value":2004},"Predefined role",{"type":43,"tag":222,"props":2006,"children":2007},{},[2008,2013],{"type":43,"tag":244,"props":2009,"children":2010},{},[2011],{"type":48,"value":2012},"Read-only access to specific index pattern",{"type":43,"tag":244,"props":2014,"children":2015},{},[2016],{"type":48,"value":2017},"Custom role",{"type":43,"tag":222,"props":2019,"children":2020},{},[2021,2026],{"type":43,"tag":244,"props":2022,"children":2023},{},[2024],{"type":48,"value":2025},"DLS or FLS restrictions",{"type":43,"tag":244,"props":2027,"children":2028},{},[2029],{"type":48,"value":2017},{"type":43,"tag":222,"props":2031,"children":2032},{},[2033,2038],{"type":43,"tag":244,"props":2034,"children":2035},{},[2036],{"type":48,"value":2037},"Kibana feature-level access control",{"type":43,"tag":244,"props":2039,"children":2040},{},[2041],{"type":48,"value":2017},{"type":43,"tag":51,"props":2043,"children":2044},{},[2045,2047,2051],{"type":48,"value":2046},"For advanced DLS\u002FFLS patterns (templated queries, ABAC), see the ",{"type":43,"tag":64,"props":2048,"children":2049},{},[2050],{"type":48,"value":123},{"type":48,"value":125},{"type":43,"tag":140,"props":2053,"children":2055},{"id":2054},"cloud-api-keys-es-and-kibana-api-access",[2056],{"type":48,"value":1769},{"type":43,"tag":51,"props":2058,"children":2059},{},[2060],{"type":48,"value":2061},"Cloud API keys can now optionally access Elasticsearch and Kibana APIs on Serverless projects, in addition to the Cloud\nAPI. This enables a single credential for both control plane (Cloud API) and data plane (ES\u002FKibana API) operations — for\nexample, a CI pipeline that creates a project via Cloud API and then indexes data via ES API.",{"type":43,"tag":363,"props":2063,"children":2065},{"id":2064},"how-it-works",[2066],{"type":48,"value":2067},"How it works",{"type":43,"tag":51,"props":2069,"children":2070},{},[2071,2073,2078,2080,2085,2087,2092,2093,2098,2099,2104,2106,2111,2112,2117,2119,2124],{"type":48,"value":2072},"Add ",{"type":43,"tag":79,"props":2074,"children":2076},{"className":2075},[],[2077],{"type":48,"value":201},{"type":48,"value":2079}," to the key's ",{"type":43,"tag":79,"props":2081,"children":2083},{"className":2082},[],[2084],{"type":48,"value":1531},{"type":48,"value":2086}," at creation time. This field accepts an array of predefined role\nnames (",{"type":43,"tag":79,"props":2088,"children":2090},{"className":2089},[],[2091],{"type":48,"value":1277},{"type":48,"value":1612},{"type":43,"tag":79,"props":2094,"children":2096},{"className":2095},[],[2097],{"type":48,"value":1304},{"type":48,"value":1612},{"type":43,"tag":79,"props":2100,"children":2102},{"className":2101},[],[2103],{"type":48,"value":1331},{"type":48,"value":2105},", and solution-specific roles like ",{"type":43,"tag":79,"props":2107,"children":2109},{"className":2108},[],[2110],{"type":48,"value":1384},{"type":48,"value":1612},{"type":43,"tag":79,"props":2113,"children":2115},{"className":2114},[],[2116],{"type":48,"value":1357},{"type":48,"value":2118},") or custom role names\ncreated in the project via ",{"type":43,"tag":79,"props":2120,"children":2122},{"className":2121},[],[2123],{"type":48,"value":1928},{"type":48,"value":2125},". Predefined roles are available in every project by default.\nCustom roles must be created individually in each project where the key should have access — if a referenced custom role\ndoes not exist in a project, the key silently gets no access there.",{"type":43,"tag":363,"props":2127,"children":2129},{"id":2128},"critical-rule-no-implicit-inheritance",[2130],{"type":48,"value":2131},"Critical rule: no implicit inheritance",{"type":43,"tag":51,"props":2133,"children":2134},{},[2135,2137,2142,2144,2149,2151,2156,2158,2162,2164,2169],{"type":48,"value":2136},"Unlike users, API keys ",{"type":43,"tag":64,"props":2138,"children":2139},{},[2140],{"type":48,"value":2141},"never",{"type":48,"value":2143}," inherit stack roles from their ",{"type":43,"tag":79,"props":2145,"children":2147},{"className":2146},[],[2148],{"type":48,"value":1170},{"type":48,"value":2150},". If ",{"type":43,"tag":79,"props":2152,"children":2154},{"className":2153},[],[2155],{"type":48,"value":201},{"type":48,"value":2157}," is omitted or empty,\nthe key has Cloud API access only. Calling an ES or Kibana endpoint with such a key returns ",{"type":43,"tag":64,"props":2159,"children":2160},{},[2161],{"type":48,"value":494},{"type":48,"value":2163},". This is\nby design for backward compatibility — existing keys without ",{"type":43,"tag":79,"props":2165,"children":2167},{"className":2166},[],[2168],{"type":48,"value":201},{"type":48,"value":2170}," continue to work as Cloud-only keys.",{"type":43,"tag":363,"props":2172,"children":2174},{"id":2173},"scoping-modes",[2175],{"type":48,"value":2176},"Scoping modes",{"type":43,"tag":147,"props":2178,"children":2179},{},[2180,2218],{"type":43,"tag":151,"props":2181,"children":2182},{},[2183,2188,2190,2195,2197,2202,2204,2209,2211,2216],{"type":43,"tag":64,"props":2184,"children":2185},{},[2186],{"type":48,"value":2187},"Project-scoped",{"type":48,"value":2189}," (preferred) — grants access to specific projects or all projects of a given type. Uses the\n",{"type":43,"tag":79,"props":2191,"children":2193},{"className":2192},[],[2194],{"type":48,"value":1539},{"type":48,"value":2196}," key in ",{"type":43,"tag":79,"props":2198,"children":2200},{"className":2199},[],[2201],{"type":48,"value":1531},{"type":48,"value":2203}," with ",{"type":43,"tag":79,"props":2205,"children":2207},{"className":2206},[],[2208],{"type":48,"value":201},{"type":48,"value":2210}," on each entry. ",{"type":43,"tag":64,"props":2212,"children":2213},{},[2214],{"type":48,"value":2215},"Use this by default",{"type":48,"value":2217}," unless the user\nexplicitly needs cross-project access.",{"type":43,"tag":151,"props":2219,"children":2220},{},[2221,2226,2228,2233,2235,2241,2242,2247,2248,2253,2255,2260,2262,2267],{"type":43,"tag":64,"props":2222,"children":2223},{},[2224],{"type":48,"value":2225},"Organization-scoped",{"type":48,"value":2227}," — grants access to ",{"type":43,"tag":64,"props":2229,"children":2230},{},[2231],{"type":48,"value":2232},"all current and future projects",{"type":48,"value":2234}," in the organization. Uses the\n",{"type":43,"tag":79,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":48,"value":2240},"organization",{"type":48,"value":2196},{"type":43,"tag":79,"props":2243,"children":2245},{"className":2244},[],[2246],{"type":48,"value":1531},{"type":48,"value":2203},{"type":43,"tag":79,"props":2249,"children":2251},{"className":2250},[],[2252],{"type":48,"value":201},{"type":48,"value":2254},". ",{"type":43,"tag":64,"props":2256,"children":2257},{},[2258],{"type":48,"value":2259},"This is the broadest possible data-plane scope.",{"type":48,"value":2261},"\nOnly use when the key genuinely needs access to every project (for example, platform automation or cross-project\nsearch across the whole org). Always confirm with the user before creating an org-scoped key with ",{"type":43,"tag":79,"props":2263,"children":2265},{"className":2264},[],[2266],{"type":48,"value":201},{"type":48,"value":2268},",\nas it grants ES\u002FKibana access to projects that may not exist yet.",{"type":43,"tag":57,"props":2270,"children":2271},{},[2272],{"type":43,"tag":51,"props":2273,"children":2274},{},[2275,2280,2282,2287,2289,2294,2296,2301,2302,2307,2308,2313],{"type":43,"tag":64,"props":2276,"children":2277},{},[2278],{"type":48,"value":2279},"Custom roles and org-scoped access:",{"type":48,"value":2281}," When using a custom role name in ",{"type":43,"tag":79,"props":2283,"children":2285},{"className":2284},[],[2286],{"type":48,"value":201},{"type":48,"value":2288}," with organization-scoped\nassignments, the custom role must exist in each project where you want the key to have access. If a project does not\nhave that custom role defined (via ",{"type":43,"tag":79,"props":2290,"children":2292},{"className":2291},[],[2293],{"type":48,"value":1928},{"type":48,"value":2295},"), the key silently gets no access to that project — no\nerror is raised. For org-wide access, prefer predefined roles (",{"type":43,"tag":79,"props":2297,"children":2299},{"className":2298},[],[2300],{"type":48,"value":1277},{"type":48,"value":1612},{"type":43,"tag":79,"props":2303,"children":2305},{"className":2304},[],[2306],{"type":48,"value":1304},{"type":48,"value":1612},{"type":43,"tag":79,"props":2309,"children":2311},{"className":2310},[],[2312],{"type":48,"value":1331},{"type":48,"value":2314},") which are available in\nevery project by default. If you must use custom roles across multiple projects, ensure the role is created in each\ntarget project first.",{"type":43,"tag":57,"props":2316,"children":2317},{},[2318],{"type":43,"tag":51,"props":2319,"children":2320},{},[2321,2326,2328,2333],{"type":43,"tag":64,"props":2322,"children":2323},{},[2324],{"type":48,"value":2325},"Agent guidance:",{"type":48,"value":2327}," When a user asks for an API key with ES\u002FKibana access, default to project-scoped assignments. Only\nsuggest organization-scoped ",{"type":43,"tag":79,"props":2329,"children":2331},{"className":2330},[],[2332],{"type":48,"value":201},{"type":48,"value":2334}," if the user explicitly needs access across all projects. Confirm the\nintent before proceeding — org-scoped access applies to future projects too. If the user specifies a custom role name\nwith org-scoped access, warn them that the role must be defined in each project individually.",{"type":43,"tag":363,"props":2336,"children":2338},{"id":2337},"examples",[2339],{"type":48,"value":2340},"Examples",{"type":43,"tag":51,"props":2342,"children":2343},{},[2344,2349,2351,2357],{"type":43,"tag":64,"props":2345,"children":2346},{},[2347],{"type":48,"value":2348},"Project-scoped key with developer ES access",{"type":48,"value":2350}," (using ",{"type":43,"tag":79,"props":2352,"children":2354},{"className":2353},[],[2355],{"type":48,"value":2356},"--stack-access",{"type":48,"value":2358}," convenience flag):",{"type":43,"tag":686,"props":2360,"children":2362},{"className":688,"code":2361,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"CI pipeline - ES ingest\" \\\n  --expiration 30d \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"developer\",\"organization_id\":\"$ORG_ID\",\"all\":true}]}}' \\\n  --stack-access developer\n",[2363],{"type":43,"tag":79,"props":2364,"children":2365},{"__ignoreMap":691},[2366,2386,2412,2429,2455],{"type":43,"tag":697,"props":2367,"children":2368},{"class":699,"line":700},[2369,2373,2377,2382],{"type":43,"tag":697,"props":2370,"children":2371},{"style":1037},[2372],{"type":48,"value":1040},{"type":43,"tag":697,"props":2374,"children":2375},{"style":715},[2376],{"type":48,"value":1045},{"type":43,"tag":697,"props":2378,"children":2379},{"style":715},[2380],{"type":48,"value":2381}," create-api-key",{"type":43,"tag":697,"props":2383,"children":2384},{"style":704},[2385],{"type":48,"value":1877},{"type":43,"tag":697,"props":2387,"children":2388},{"class":699,"line":721},[2389,2394,2399,2404,2408],{"type":43,"tag":697,"props":2390,"children":2391},{"style":715},[2392],{"type":48,"value":2393},"  --description",{"type":43,"tag":697,"props":2395,"children":2396},{"style":709},[2397],{"type":48,"value":2398}," \"",{"type":43,"tag":697,"props":2400,"children":2401},{"style":715},[2402],{"type":48,"value":2403},"CI pipeline - ES ingest",{"type":43,"tag":697,"props":2405,"children":2406},{"style":709},[2407],{"type":48,"value":818},{"type":43,"tag":697,"props":2409,"children":2410},{"style":704},[2411],{"type":48,"value":1877},{"type":43,"tag":697,"props":2413,"children":2414},{"class":699,"line":738},[2415,2420,2425],{"type":43,"tag":697,"props":2416,"children":2417},{"style":715},[2418],{"type":48,"value":2419},"  --expiration",{"type":43,"tag":697,"props":2421,"children":2422},{"style":715},[2423],{"type":48,"value":2424}," 30d",{"type":43,"tag":697,"props":2426,"children":2427},{"style":704},[2428],{"type":48,"value":1877},{"type":43,"tag":697,"props":2430,"children":2431},{"class":699,"line":748},[2432,2437,2441,2446,2451],{"type":43,"tag":697,"props":2433,"children":2434},{"style":715},[2435],{"type":48,"value":2436},"  --roles",{"type":43,"tag":697,"props":2438,"children":2439},{"style":709},[2440],{"type":48,"value":1907},{"type":43,"tag":697,"props":2442,"children":2443},{"style":715},[2444],{"type":48,"value":2445},"{\"project\":{\"elasticsearch\":[{\"role_id\":\"developer\",\"organization_id\":\"$ORG_ID\",\"all\":true}]}}",{"type":43,"tag":697,"props":2447,"children":2448},{"style":709},[2449],{"type":48,"value":2450},"'",{"type":43,"tag":697,"props":2452,"children":2453},{"style":704},[2454],{"type":48,"value":1877},{"type":43,"tag":697,"props":2456,"children":2457},{"class":699,"line":757},[2458,2463],{"type":43,"tag":697,"props":2459,"children":2460},{"style":715},[2461],{"type":48,"value":2462},"  --stack-access",{"type":43,"tag":697,"props":2464,"children":2465},{"style":715},[2466],{"type":48,"value":2467}," developer\n",{"type":43,"tag":51,"props":2469,"children":2470},{},[2471,2476],{"type":43,"tag":64,"props":2472,"children":2473},{},[2474],{"type":48,"value":2475},"Organization-scoped key with admin ES access",{"type":48,"value":2477}," (access to ALL projects — use with caution):",{"type":43,"tag":686,"props":2479,"children":2481},{"className":688,"code":2480,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"Platform automation\" \\\n  --expiration 7d \\\n  --roles '{\"organization\":[{\"role_id\":\"organization-admin\",\"organization_id\":\"$ORG_ID\"}]}' \\\n  --stack-access admin\n",[2482],{"type":43,"tag":79,"props":2483,"children":2484},{"__ignoreMap":691},[2485,2504,2528,2544,2568],{"type":43,"tag":697,"props":2486,"children":2487},{"class":699,"line":700},[2488,2492,2496,2500],{"type":43,"tag":697,"props":2489,"children":2490},{"style":1037},[2491],{"type":48,"value":1040},{"type":43,"tag":697,"props":2493,"children":2494},{"style":715},[2495],{"type":48,"value":1045},{"type":43,"tag":697,"props":2497,"children":2498},{"style":715},[2499],{"type":48,"value":2381},{"type":43,"tag":697,"props":2501,"children":2502},{"style":704},[2503],{"type":48,"value":1877},{"type":43,"tag":697,"props":2505,"children":2506},{"class":699,"line":721},[2507,2511,2515,2520,2524],{"type":43,"tag":697,"props":2508,"children":2509},{"style":715},[2510],{"type":48,"value":2393},{"type":43,"tag":697,"props":2512,"children":2513},{"style":709},[2514],{"type":48,"value":2398},{"type":43,"tag":697,"props":2516,"children":2517},{"style":715},[2518],{"type":48,"value":2519},"Platform automation",{"type":43,"tag":697,"props":2521,"children":2522},{"style":709},[2523],{"type":48,"value":818},{"type":43,"tag":697,"props":2525,"children":2526},{"style":704},[2527],{"type":48,"value":1877},{"type":43,"tag":697,"props":2529,"children":2530},{"class":699,"line":738},[2531,2535,2540],{"type":43,"tag":697,"props":2532,"children":2533},{"style":715},[2534],{"type":48,"value":2419},{"type":43,"tag":697,"props":2536,"children":2537},{"style":715},[2538],{"type":48,"value":2539}," 7d",{"type":43,"tag":697,"props":2541,"children":2542},{"style":704},[2543],{"type":48,"value":1877},{"type":43,"tag":697,"props":2545,"children":2546},{"class":699,"line":748},[2547,2551,2555,2560,2564],{"type":43,"tag":697,"props":2548,"children":2549},{"style":715},[2550],{"type":48,"value":2436},{"type":43,"tag":697,"props":2552,"children":2553},{"style":709},[2554],{"type":48,"value":1907},{"type":43,"tag":697,"props":2556,"children":2557},{"style":715},[2558],{"type":48,"value":2559},"{\"organization\":[{\"role_id\":\"organization-admin\",\"organization_id\":\"$ORG_ID\"}]}",{"type":43,"tag":697,"props":2561,"children":2562},{"style":709},[2563],{"type":48,"value":2450},{"type":43,"tag":697,"props":2565,"children":2566},{"style":704},[2567],{"type":48,"value":1877},{"type":43,"tag":697,"props":2569,"children":2570},{"class":699,"line":757},[2571,2575],{"type":43,"tag":697,"props":2572,"children":2573},{"style":715},[2574],{"type":48,"value":2462},{"type":43,"tag":697,"props":2576,"children":2577},{"style":715},[2578],{"type":48,"value":2579}," admin\n",{"type":43,"tag":51,"props":2581,"children":2582},{},[2583,2588],{"type":43,"tag":64,"props":2584,"children":2585},{},[2586],{"type":48,"value":2587},"Project-scoped key with a custom role",{"type":48,"value":2589}," (raw JSON):",{"type":43,"tag":686,"props":2591,"children":2593},{"className":688,"code":2592,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"Marketing ETL\" \\\n  --expiration 14d \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"elasticsearch-viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"],\"application_roles\":[\"marketing-writer\"]}]}}'\n",[2594],{"type":43,"tag":79,"props":2595,"children":2596},{"__ignoreMap":691},[2597,2616,2640,2656],{"type":43,"tag":697,"props":2598,"children":2599},{"class":699,"line":700},[2600,2604,2608,2612],{"type":43,"tag":697,"props":2601,"children":2602},{"style":1037},[2603],{"type":48,"value":1040},{"type":43,"tag":697,"props":2605,"children":2606},{"style":715},[2607],{"type":48,"value":1045},{"type":43,"tag":697,"props":2609,"children":2610},{"style":715},[2611],{"type":48,"value":2381},{"type":43,"tag":697,"props":2613,"children":2614},{"style":704},[2615],{"type":48,"value":1877},{"type":43,"tag":697,"props":2617,"children":2618},{"class":699,"line":721},[2619,2623,2627,2632,2636],{"type":43,"tag":697,"props":2620,"children":2621},{"style":715},[2622],{"type":48,"value":2393},{"type":43,"tag":697,"props":2624,"children":2625},{"style":709},[2626],{"type":48,"value":2398},{"type":43,"tag":697,"props":2628,"children":2629},{"style":715},[2630],{"type":48,"value":2631},"Marketing ETL",{"type":43,"tag":697,"props":2633,"children":2634},{"style":709},[2635],{"type":48,"value":818},{"type":43,"tag":697,"props":2637,"children":2638},{"style":704},[2639],{"type":48,"value":1877},{"type":43,"tag":697,"props":2641,"children":2642},{"class":699,"line":738},[2643,2647,2652],{"type":43,"tag":697,"props":2644,"children":2645},{"style":715},[2646],{"type":48,"value":2419},{"type":43,"tag":697,"props":2648,"children":2649},{"style":715},[2650],{"type":48,"value":2651}," 14d",{"type":43,"tag":697,"props":2653,"children":2654},{"style":704},[2655],{"type":48,"value":1877},{"type":43,"tag":697,"props":2657,"children":2658},{"class":699,"line":748},[2659,2663,2667,2672],{"type":43,"tag":697,"props":2660,"children":2661},{"style":715},[2662],{"type":48,"value":2436},{"type":43,"tag":697,"props":2664,"children":2665},{"style":709},[2666],{"type":48,"value":1907},{"type":43,"tag":697,"props":2668,"children":2669},{"style":715},[2670],{"type":48,"value":2671},"{\"project\":{\"elasticsearch\":[{\"role_id\":\"elasticsearch-viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"],\"application_roles\":[\"marketing-writer\"]}]}}",{"type":43,"tag":697,"props":2673,"children":2674},{"style":709},[2675],{"type":48,"value":1917},{"type":43,"tag":51,"props":2677,"children":2678},{},[2679,2681,2687,2688,2694,2696,2701],{"type":48,"value":2680},"Replace ",{"type":43,"tag":79,"props":2682,"children":2684},{"className":2683},[],[2685],{"type":48,"value":2686},"$ORG_ID",{"type":48,"value":1836},{"type":43,"tag":79,"props":2689,"children":2691},{"className":2690},[],[2692],{"type":48,"value":2693},"$PROJECT_ID",{"type":48,"value":2695}," with the actual organization and project IDs. Use ",{"type":43,"tag":79,"props":2697,"children":2699},{"className":2698},[],[2700],{"type":48,"value":1834},{"type":48,"value":2702}," to discover the org\nID.",{"type":43,"tag":57,"props":2704,"children":2705},{},[2706],{"type":43,"tag":51,"props":2707,"children":2708},{},[2709,2714,2716,2721,2723,2728,2730,2735],{"type":43,"tag":64,"props":2710,"children":2711},{},[2712],{"type":48,"value":2713},"Common mistake:",{"type":48,"value":2715}," If your API key gets a 403 when calling an ES or Kibana endpoint, the most likely cause is missing\n",{"type":43,"tag":79,"props":2717,"children":2719},{"className":2718},[],[2720],{"type":48,"value":201},{"type":48,"value":2722},". Unlike users, API keys must have explicit ",{"type":43,"tag":79,"props":2724,"children":2726},{"className":2725},[],[2727],{"type":48,"value":201},{"type":48,"value":2729}," to access the stack — the ",{"type":43,"tag":79,"props":2731,"children":2733},{"className":2732},[],[2734],{"type":48,"value":1170},{"type":48,"value":2736},"\nalone is not sufficient.",{"type":43,"tag":140,"props":2738,"children":2740},{"id":2739},"examples-1",[2741],{"type":48,"value":2340},{"type":43,"tag":363,"props":2743,"children":2745},{"id":2744},"invite-a-user-as-a-viewer-on-a-search-project",[2746],{"type":48,"value":2747},"Invite a user as a Viewer on a search project",{"type":43,"tag":51,"props":2749,"children":2750},{},[2751,2756,2758,2764],{"type":43,"tag":64,"props":2752,"children":2753},{},[2754],{"type":48,"value":2755},"Prompt:",{"type":48,"value":2757}," \"Add ",{"type":43,"tag":79,"props":2759,"children":2761},{"className":2760},[],[2762],{"type":48,"value":2763},"alice@example.com",{"type":48,"value":2765}," to my search project with read-only access.\"",{"type":43,"tag":686,"props":2767,"children":2769},{"className":688,"code":2768,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py invite-user \\\n  --emails alice@example.com \\\n  --roles '{\"project\":{\"elasticsearch\":[{\"role_id\":\"viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}'\n",[2770],{"type":43,"tag":79,"props":2771,"children":2772},{"__ignoreMap":691},[2773,2793,2810],{"type":43,"tag":697,"props":2774,"children":2775},{"class":699,"line":700},[2776,2780,2784,2789],{"type":43,"tag":697,"props":2777,"children":2778},{"style":1037},[2779],{"type":48,"value":1040},{"type":43,"tag":697,"props":2781,"children":2782},{"style":715},[2783],{"type":48,"value":1045},{"type":43,"tag":697,"props":2785,"children":2786},{"style":715},[2787],{"type":48,"value":2788}," invite-user",{"type":43,"tag":697,"props":2790,"children":2791},{"style":704},[2792],{"type":48,"value":1877},{"type":43,"tag":697,"props":2794,"children":2795},{"class":699,"line":721},[2796,2801,2806],{"type":43,"tag":697,"props":2797,"children":2798},{"style":715},[2799],{"type":48,"value":2800},"  --emails",{"type":43,"tag":697,"props":2802,"children":2803},{"style":715},[2804],{"type":48,"value":2805}," alice@example.com",{"type":43,"tag":697,"props":2807,"children":2808},{"style":704},[2809],{"type":48,"value":1877},{"type":43,"tag":697,"props":2811,"children":2812},{"class":699,"line":738},[2813,2817,2821,2826],{"type":43,"tag":697,"props":2814,"children":2815},{"style":715},[2816],{"type":48,"value":2436},{"type":43,"tag":697,"props":2818,"children":2819},{"style":709},[2820],{"type":48,"value":1907},{"type":43,"tag":697,"props":2822,"children":2823},{"style":715},[2824],{"type":48,"value":2825},"{\"project\":{\"elasticsearch\":[{\"role_id\":\"viewer\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}",{"type":43,"tag":697,"props":2827,"children":2828},{"style":709},[2829],{"type":48,"value":1917},{"type":43,"tag":51,"props":2831,"children":2832},{},[2833,2834,2839,2840,2845,2847,2852],{"type":48,"value":2680},{"type":43,"tag":79,"props":2835,"children":2837},{"className":2836},[],[2838],{"type":48,"value":2686},{"type":48,"value":1836},{"type":43,"tag":79,"props":2841,"children":2843},{"className":2842},[],[2844],{"type":48,"value":2693},{"type":48,"value":2846}," with the actual IDs. The Viewer role is assigned when the invitation is accepted.\nFor custom role access, use ",{"type":43,"tag":79,"props":2848,"children":2850},{"className":2849},[],[2851],{"type":48,"value":1686},{"type":48,"value":2853}," after the user has accepted the invitation — do not combine a\npredefined role assignment with a custom role for the same project.",{"type":43,"tag":363,"props":2855,"children":2857},{"id":2856},"create-a-cicd-api-key",[2858],{"type":48,"value":2859},"Create a CI\u002FCD API key",{"type":43,"tag":51,"props":2861,"children":2862},{},[2863,2867],{"type":43,"tag":64,"props":2864,"children":2865},{},[2866],{"type":48,"value":2755},{"type":48,"value":2868}," \"Create an API key for our CI pipeline that expires in 30 days with editor access to all deployments.\"",{"type":43,"tag":686,"props":2870,"children":2872},{"className":688,"code":2871,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-api-key \\\n  --description \"CI\u002FCD pipeline\" \\\n  --expiration \"30d\" \\\n  --roles '{\"deployment\":[{\"role_id\":\"deployment-editor\",\"all\":true}]}'\n",[2873],{"type":43,"tag":79,"props":2874,"children":2875},{"__ignoreMap":691},[2876,2895,2919,2943],{"type":43,"tag":697,"props":2877,"children":2878},{"class":699,"line":700},[2879,2883,2887,2891],{"type":43,"tag":697,"props":2880,"children":2881},{"style":1037},[2882],{"type":48,"value":1040},{"type":43,"tag":697,"props":2884,"children":2885},{"style":715},[2886],{"type":48,"value":1045},{"type":43,"tag":697,"props":2888,"children":2889},{"style":715},[2890],{"type":48,"value":2381},{"type":43,"tag":697,"props":2892,"children":2893},{"style":704},[2894],{"type":48,"value":1877},{"type":43,"tag":697,"props":2896,"children":2897},{"class":699,"line":721},[2898,2902,2906,2911,2915],{"type":43,"tag":697,"props":2899,"children":2900},{"style":715},[2901],{"type":48,"value":2393},{"type":43,"tag":697,"props":2903,"children":2904},{"style":709},[2905],{"type":48,"value":2398},{"type":43,"tag":697,"props":2907,"children":2908},{"style":715},[2909],{"type":48,"value":2910},"CI\u002FCD pipeline",{"type":43,"tag":697,"props":2912,"children":2913},{"style":709},[2914],{"type":48,"value":818},{"type":43,"tag":697,"props":2916,"children":2917},{"style":704},[2918],{"type":48,"value":1877},{"type":43,"tag":697,"props":2920,"children":2921},{"class":699,"line":738},[2922,2926,2930,2935,2939],{"type":43,"tag":697,"props":2923,"children":2924},{"style":715},[2925],{"type":48,"value":2419},{"type":43,"tag":697,"props":2927,"children":2928},{"style":709},[2929],{"type":48,"value":2398},{"type":43,"tag":697,"props":2931,"children":2932},{"style":715},[2933],{"type":48,"value":2934},"30d",{"type":43,"tag":697,"props":2936,"children":2937},{"style":709},[2938],{"type":48,"value":818},{"type":43,"tag":697,"props":2940,"children":2941},{"style":704},[2942],{"type":48,"value":1877},{"type":43,"tag":697,"props":2944,"children":2945},{"class":699,"line":748},[2946,2950,2954,2959],{"type":43,"tag":697,"props":2947,"children":2948},{"style":715},[2949],{"type":48,"value":2436},{"type":43,"tag":697,"props":2951,"children":2952},{"style":709},[2953],{"type":48,"value":1907},{"type":43,"tag":697,"props":2955,"children":2956},{"style":715},[2957],{"type":48,"value":2958},"{\"deployment\":[{\"role_id\":\"deployment-editor\",\"all\":true}]}",{"type":43,"tag":697,"props":2960,"children":2961},{"style":709},[2962],{"type":48,"value":1917},{"type":43,"tag":51,"props":2964,"children":2965},{},[2966,2968,2974,2976,2982],{"type":48,"value":2967},"The actual key value is written to a secure temp file (0600 permissions). The stdout JSON contains a ",{"type":43,"tag":79,"props":2969,"children":2971},{"className":2970},[],[2972],{"type":48,"value":2973},"_secret_file",{"type":48,"value":2975}," path\ninstead of the raw secret. Tell the user to retrieve the key from that file — it is shown only once. When the CI\npipeline no longer needs this key, revoke it using ",{"type":43,"tag":79,"props":2977,"children":2979},{"className":2978},[],[2980],{"type":48,"value":2981},"delete-api-key",{"type":48,"value":2983}," to avoid unused keys accumulating.",{"type":43,"tag":363,"props":2985,"children":2987},{"id":2986},"create-a-cicd-api-key-with-es-access",[2988],{"type":48,"value":2989},"Create a CI\u002FCD API key with ES access",{"type":43,"tag":51,"props":2991,"children":2992},{},[2993,2997],{"type":43,"tag":64,"props":2994,"children":2995},{},[2996],{"type":48,"value":2755},{"type":48,"value":2998}," \"Create an API key for our CI pipeline that can index data into our search projects.\"",{"type":43,"tag":686,"props":3000,"children":3001},{"className":688,"code":2361,"language":690,"meta":691,"style":691},[3002],{"type":43,"tag":79,"props":3003,"children":3004},{"__ignoreMap":691},[3005,3024,3047,3062,3085],{"type":43,"tag":697,"props":3006,"children":3007},{"class":699,"line":700},[3008,3012,3016,3020],{"type":43,"tag":697,"props":3009,"children":3010},{"style":1037},[3011],{"type":48,"value":1040},{"type":43,"tag":697,"props":3013,"children":3014},{"style":715},[3015],{"type":48,"value":1045},{"type":43,"tag":697,"props":3017,"children":3018},{"style":715},[3019],{"type":48,"value":2381},{"type":43,"tag":697,"props":3021,"children":3022},{"style":704},[3023],{"type":48,"value":1877},{"type":43,"tag":697,"props":3025,"children":3026},{"class":699,"line":721},[3027,3031,3035,3039,3043],{"type":43,"tag":697,"props":3028,"children":3029},{"style":715},[3030],{"type":48,"value":2393},{"type":43,"tag":697,"props":3032,"children":3033},{"style":709},[3034],{"type":48,"value":2398},{"type":43,"tag":697,"props":3036,"children":3037},{"style":715},[3038],{"type":48,"value":2403},{"type":43,"tag":697,"props":3040,"children":3041},{"style":709},[3042],{"type":48,"value":818},{"type":43,"tag":697,"props":3044,"children":3045},{"style":704},[3046],{"type":48,"value":1877},{"type":43,"tag":697,"props":3048,"children":3049},{"class":699,"line":738},[3050,3054,3058],{"type":43,"tag":697,"props":3051,"children":3052},{"style":715},[3053],{"type":48,"value":2419},{"type":43,"tag":697,"props":3055,"children":3056},{"style":715},[3057],{"type":48,"value":2424},{"type":43,"tag":697,"props":3059,"children":3060},{"style":704},[3061],{"type":48,"value":1877},{"type":43,"tag":697,"props":3063,"children":3064},{"class":699,"line":748},[3065,3069,3073,3077,3081],{"type":43,"tag":697,"props":3066,"children":3067},{"style":715},[3068],{"type":48,"value":2436},{"type":43,"tag":697,"props":3070,"children":3071},{"style":709},[3072],{"type":48,"value":1907},{"type":43,"tag":697,"props":3074,"children":3075},{"style":715},[3076],{"type":48,"value":2445},{"type":43,"tag":697,"props":3078,"children":3079},{"style":709},[3080],{"type":48,"value":2450},{"type":43,"tag":697,"props":3082,"children":3083},{"style":704},[3084],{"type":48,"value":1877},{"type":43,"tag":697,"props":3086,"children":3087},{"class":699,"line":757},[3088,3092],{"type":43,"tag":697,"props":3089,"children":3090},{"style":715},[3091],{"type":48,"value":2462},{"type":43,"tag":697,"props":3093,"children":3094},{"style":715},[3095],{"type":48,"value":2467},{"type":43,"tag":51,"props":3097,"children":3098},{},[3099,3100,3105,3107,3112,3114,3120,3122,3127,3129,3134],{"type":48,"value":2680},{"type":43,"tag":79,"props":3101,"children":3103},{"className":3102},[],[3104],{"type":48,"value":2686},{"type":48,"value":3106}," with the actual organization ID. The ",{"type":43,"tag":79,"props":3108,"children":3110},{"className":3109},[],[3111],{"type":48,"value":2356},{"type":48,"value":3113}," flag injects ",{"type":43,"tag":79,"props":3115,"children":3117},{"className":3116},[],[3118],{"type":48,"value":3119},"application_roles: [\"developer\"]",{"type":48,"value":3121},"\ninto the role assignments, granting the key developer-level ES\u002FKibana API access on all Elasticsearch projects. Without\n",{"type":43,"tag":79,"props":3123,"children":3125},{"className":3124},[],[3126],{"type":48,"value":2356},{"type":48,"value":3128}," (or explicit ",{"type":43,"tag":79,"props":3130,"children":3132},{"className":3131},[],[3133],{"type":48,"value":201},{"type":48,"value":3135}," in the JSON), the key would only have Cloud API access and receive 403\non ES\u002FKibana calls.",{"type":43,"tag":363,"props":3137,"children":3139},{"id":3138},"create-a-custom-role-for-marketing-data",[3140],{"type":48,"value":3141},"Create a custom role for marketing data",{"type":43,"tag":51,"props":3143,"children":3144},{},[3145,3149],{"type":43,"tag":64,"props":3146,"children":3147},{},[3148],{"type":48,"value":2755},{"type":48,"value":3150}," \"Create a role that gives read-only access to marketing-* indices on my search project.\"",{"type":43,"tag":686,"props":3152,"children":3154},{"className":688,"code":3153,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name marketing-reader \\\n  --body '{\"cluster\":[],\"indices\":[{\"names\":[\"marketing-*\"],\"privileges\":[\"read\",\"view_index_metadata\"]}]}'\n",[3155],{"type":43,"tag":79,"props":3156,"children":3157},{"__ignoreMap":691},[3158,3177,3193],{"type":43,"tag":697,"props":3159,"children":3160},{"class":699,"line":700},[3161,3165,3169,3173],{"type":43,"tag":697,"props":3162,"children":3163},{"style":1037},[3164],{"type":48,"value":1040},{"type":43,"tag":697,"props":3166,"children":3167},{"style":715},[3168],{"type":48,"value":1045},{"type":43,"tag":697,"props":3170,"children":3171},{"style":715},[3172],{"type":48,"value":1872},{"type":43,"tag":697,"props":3174,"children":3175},{"style":704},[3176],{"type":48,"value":1877},{"type":43,"tag":697,"props":3178,"children":3179},{"class":699,"line":721},[3180,3184,3189],{"type":43,"tag":697,"props":3181,"children":3182},{"style":715},[3183],{"type":48,"value":1885},{"type":43,"tag":697,"props":3185,"children":3186},{"style":715},[3187],{"type":48,"value":3188}," marketing-reader",{"type":43,"tag":697,"props":3190,"children":3191},{"style":704},[3192],{"type":48,"value":1877},{"type":43,"tag":697,"props":3194,"children":3195},{"class":699,"line":738},[3196,3200,3204,3208],{"type":43,"tag":697,"props":3197,"children":3198},{"style":715},[3199],{"type":48,"value":1902},{"type":43,"tag":697,"props":3201,"children":3202},{"style":709},[3203],{"type":48,"value":1907},{"type":43,"tag":697,"props":3205,"children":3206},{"style":715},[3207],{"type":48,"value":1912},{"type":43,"tag":697,"props":3209,"children":3210},{"style":709},[3211],{"type":48,"value":1917},{"type":43,"tag":51,"props":3213,"children":3214},{},[3215,3217,3222,3224,3229],{"type":48,"value":3216},"Then assign the custom role to a user using the ",{"type":43,"tag":79,"props":3218,"children":3220},{"className":3219},[],[3221],{"type":48,"value":1686},{"type":48,"value":3223}," command, which sets ",{"type":43,"tag":79,"props":3225,"children":3227},{"className":3226},[],[3228],{"type":48,"value":201},{"type":48,"value":3230}," in the\nCloud API role assignment.",{"type":43,"tag":363,"props":3232,"children":3234},{"id":3233},"full-custom-role-flow-for-read-only-dashboards",[3235],{"type":48,"value":3236},"Full custom-role flow for read-only dashboards",{"type":43,"tag":51,"props":3238,"children":3239},{},[3240,3244,3245,3251],{"type":43,"tag":64,"props":3241,"children":3242},{},[3243],{"type":48,"value":2755},{"type":48,"value":2757},{"type":43,"tag":79,"props":3246,"children":3248},{"className":3247},[],[3249],{"type":48,"value":3250},"bob@example.com",{"type":48,"value":3252}," to my search project with read-only dashboard access.\"",{"type":43,"tag":686,"props":3254,"children":3256},{"className":688,"code":3255,"language":690,"meta":691,"style":691},"# 1) Create custom role in the project\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py create-custom-role \\\n  --role-name dashboard-reader \\\n  --body '{\"cluster\":[],\"indices\":[],\"applications\":[{\"application\":\"kibana-.kibana\",\"privileges\":[\"feature_dashboard.read\"],\"resources\":[\"*\"]}]}'\n\n# 2) Invite user to the organization (no project roles — custom role handles access)\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py invite-user \\\n  --emails bob@example.com\n\n# 3) After invitation is accepted, assign the custom role via application_roles\npython3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py assign-custom-role \\\n  --user-id \"$USER_ID\" \\\n  --project-id \"$PROJECT_ID\" \\\n  --project-type elasticsearch \\\n  --custom-role-name dashboard-reader\n",[3257],{"type":43,"tag":79,"props":3258,"children":3259},{"__ignoreMap":691},[3260,3268,3287,3303,3323,3332,3341,3361,3374,3382,3391,3412,3438,3463,3481],{"type":43,"tag":697,"props":3261,"children":3262},{"class":699,"line":700},[3263],{"type":43,"tag":697,"props":3264,"children":3265},{"style":742},[3266],{"type":48,"value":3267},"# 1) Create custom role in the project\n",{"type":43,"tag":697,"props":3269,"children":3270},{"class":699,"line":721},[3271,3275,3279,3283],{"type":43,"tag":697,"props":3272,"children":3273},{"style":1037},[3274],{"type":48,"value":1040},{"type":43,"tag":697,"props":3276,"children":3277},{"style":715},[3278],{"type":48,"value":1045},{"type":43,"tag":697,"props":3280,"children":3281},{"style":715},[3282],{"type":48,"value":1872},{"type":43,"tag":697,"props":3284,"children":3285},{"style":704},[3286],{"type":48,"value":1877},{"type":43,"tag":697,"props":3288,"children":3289},{"class":699,"line":738},[3290,3294,3299],{"type":43,"tag":697,"props":3291,"children":3292},{"style":715},[3293],{"type":48,"value":1885},{"type":43,"tag":697,"props":3295,"children":3296},{"style":715},[3297],{"type":48,"value":3298}," dashboard-reader",{"type":43,"tag":697,"props":3300,"children":3301},{"style":704},[3302],{"type":48,"value":1877},{"type":43,"tag":697,"props":3304,"children":3305},{"class":699,"line":748},[3306,3310,3314,3319],{"type":43,"tag":697,"props":3307,"children":3308},{"style":715},[3309],{"type":48,"value":1902},{"type":43,"tag":697,"props":3311,"children":3312},{"style":709},[3313],{"type":48,"value":1907},{"type":43,"tag":697,"props":3315,"children":3316},{"style":715},[3317],{"type":48,"value":3318},"{\"cluster\":[],\"indices\":[],\"applications\":[{\"application\":\"kibana-.kibana\",\"privileges\":[\"feature_dashboard.read\"],\"resources\":[\"*\"]}]}",{"type":43,"tag":697,"props":3320,"children":3321},{"style":709},[3322],{"type":48,"value":1917},{"type":43,"tag":697,"props":3324,"children":3325},{"class":699,"line":757},[3326],{"type":43,"tag":697,"props":3327,"children":3329},{"emptyLinePlaceholder":3328},true,[3330],{"type":48,"value":3331},"\n",{"type":43,"tag":697,"props":3333,"children":3335},{"class":699,"line":3334},6,[3336],{"type":43,"tag":697,"props":3337,"children":3338},{"style":742},[3339],{"type":48,"value":3340},"# 2) Invite user to the organization (no project roles — custom role handles access)\n",{"type":43,"tag":697,"props":3342,"children":3344},{"class":699,"line":3343},7,[3345,3349,3353,3357],{"type":43,"tag":697,"props":3346,"children":3347},{"style":1037},[3348],{"type":48,"value":1040},{"type":43,"tag":697,"props":3350,"children":3351},{"style":715},[3352],{"type":48,"value":1045},{"type":43,"tag":697,"props":3354,"children":3355},{"style":715},[3356],{"type":48,"value":2788},{"type":43,"tag":697,"props":3358,"children":3359},{"style":704},[3360],{"type":48,"value":1877},{"type":43,"tag":697,"props":3362,"children":3364},{"class":699,"line":3363},8,[3365,3369],{"type":43,"tag":697,"props":3366,"children":3367},{"style":715},[3368],{"type":48,"value":2800},{"type":43,"tag":697,"props":3370,"children":3371},{"style":715},[3372],{"type":48,"value":3373}," bob@example.com\n",{"type":43,"tag":697,"props":3375,"children":3377},{"class":699,"line":3376},9,[3378],{"type":43,"tag":697,"props":3379,"children":3380},{"emptyLinePlaceholder":3328},[3381],{"type":48,"value":3331},{"type":43,"tag":697,"props":3383,"children":3385},{"class":699,"line":3384},10,[3386],{"type":43,"tag":697,"props":3387,"children":3388},{"style":742},[3389],{"type":48,"value":3390},"# 3) After invitation is accepted, assign the custom role via application_roles\n",{"type":43,"tag":697,"props":3392,"children":3394},{"class":699,"line":3393},11,[3395,3399,3403,3408],{"type":43,"tag":697,"props":3396,"children":3397},{"style":1037},[3398],{"type":48,"value":1040},{"type":43,"tag":697,"props":3400,"children":3401},{"style":715},[3402],{"type":48,"value":1045},{"type":43,"tag":697,"props":3404,"children":3405},{"style":715},[3406],{"type":48,"value":3407}," assign-custom-role",{"type":43,"tag":697,"props":3409,"children":3410},{"style":704},[3411],{"type":48,"value":1877},{"type":43,"tag":697,"props":3413,"children":3415},{"class":699,"line":3414},12,[3416,3421,3425,3430,3434],{"type":43,"tag":697,"props":3417,"children":3418},{"style":715},[3419],{"type":48,"value":3420},"  --user-id",{"type":43,"tag":697,"props":3422,"children":3423},{"style":709},[3424],{"type":48,"value":2398},{"type":43,"tag":697,"props":3426,"children":3427},{"style":704},[3428],{"type":48,"value":3429},"$USER_ID",{"type":43,"tag":697,"props":3431,"children":3432},{"style":709},[3433],{"type":48,"value":818},{"type":43,"tag":697,"props":3435,"children":3436},{"style":704},[3437],{"type":48,"value":1877},{"type":43,"tag":697,"props":3439,"children":3441},{"class":699,"line":3440},13,[3442,3447,3451,3455,3459],{"type":43,"tag":697,"props":3443,"children":3444},{"style":715},[3445],{"type":48,"value":3446},"  --project-id",{"type":43,"tag":697,"props":3448,"children":3449},{"style":709},[3450],{"type":48,"value":2398},{"type":43,"tag":697,"props":3452,"children":3453},{"style":704},[3454],{"type":48,"value":2693},{"type":43,"tag":697,"props":3456,"children":3457},{"style":709},[3458],{"type":48,"value":818},{"type":43,"tag":697,"props":3460,"children":3461},{"style":704},[3462],{"type":48,"value":1877},{"type":43,"tag":697,"props":3464,"children":3466},{"class":699,"line":3465},14,[3467,3472,3477],{"type":43,"tag":697,"props":3468,"children":3469},{"style":715},[3470],{"type":48,"value":3471},"  --project-type",{"type":43,"tag":697,"props":3473,"children":3474},{"style":715},[3475],{"type":48,"value":3476}," elasticsearch",{"type":43,"tag":697,"props":3478,"children":3479},{"style":704},[3480],{"type":48,"value":1877},{"type":43,"tag":697,"props":3482,"children":3484},{"class":699,"line":3483},15,[3485,3490],{"type":43,"tag":697,"props":3486,"children":3487},{"style":715},[3488],{"type":48,"value":3489},"  --custom-role-name",{"type":43,"tag":697,"props":3491,"children":3492},{"style":715},[3493],{"type":48,"value":3494}," dashboard-reader\n",{"type":43,"tag":51,"props":3496,"children":3497},{},[3498,3500,3504,3506,3512,3514,3519],{"type":48,"value":3499},"The user receives Viewer-level Cloud access (can see the project in the console) and ",{"type":43,"tag":64,"props":3501,"children":3502},{},[3503],{"type":48,"value":1700},{"type":48,"value":3505}," ",{"type":43,"tag":79,"props":3507,"children":3509},{"className":3508},[],[3510],{"type":48,"value":3511},"dashboard-reader",{"type":48,"value":3513},"\npermissions when they SSO into the project. Do not also assign ",{"type":43,"tag":79,"props":3515,"children":3517},{"className":3516},[],[3518],{"type":48,"value":1331},{"type":48,"value":3520}," as a separate Cloud role for this project —\ndoing so would grant the broader Viewer stack role and override the custom role's restrictions.",{"type":43,"tag":363,"props":3522,"children":3524},{"id":3523},"update-a-users-project-role",[3525],{"type":48,"value":3526},"Update a user's project role",{"type":43,"tag":51,"props":3528,"children":3529},{},[3530,3534],{"type":43,"tag":64,"props":3531,"children":3532},{},[3533],{"type":48,"value":2755},{"type":48,"value":3535}," \"Promote Bob to admin on our observability project.\"",{"type":43,"tag":686,"props":3537,"children":3539},{"className":688,"code":3538,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py assign-role \\\n  --user-id \"$USER_ID\" \\\n  --roles '{\"project\":{\"observability\":[{\"role_id\":\"admin\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}'\n",[3540],{"type":43,"tag":79,"props":3541,"children":3542},{"__ignoreMap":691},[3543,3563,3586],{"type":43,"tag":697,"props":3544,"children":3545},{"class":699,"line":700},[3546,3550,3554,3559],{"type":43,"tag":697,"props":3547,"children":3548},{"style":1037},[3549],{"type":48,"value":1040},{"type":43,"tag":697,"props":3551,"children":3552},{"style":715},[3553],{"type":48,"value":1045},{"type":43,"tag":697,"props":3555,"children":3556},{"style":715},[3557],{"type":48,"value":3558}," assign-role",{"type":43,"tag":697,"props":3560,"children":3561},{"style":704},[3562],{"type":48,"value":1877},{"type":43,"tag":697,"props":3564,"children":3565},{"class":699,"line":721},[3566,3570,3574,3578,3582],{"type":43,"tag":697,"props":3567,"children":3568},{"style":715},[3569],{"type":48,"value":3420},{"type":43,"tag":697,"props":3571,"children":3572},{"style":709},[3573],{"type":48,"value":2398},{"type":43,"tag":697,"props":3575,"children":3576},{"style":704},[3577],{"type":48,"value":3429},{"type":43,"tag":697,"props":3579,"children":3580},{"style":709},[3581],{"type":48,"value":818},{"type":43,"tag":697,"props":3583,"children":3584},{"style":704},[3585],{"type":48,"value":1877},{"type":43,"tag":697,"props":3587,"children":3588},{"class":699,"line":738},[3589,3593,3597,3602],{"type":43,"tag":697,"props":3590,"children":3591},{"style":715},[3592],{"type":48,"value":2436},{"type":43,"tag":697,"props":3594,"children":3595},{"style":709},[3596],{"type":48,"value":1907},{"type":43,"tag":697,"props":3598,"children":3599},{"style":715},[3600],{"type":48,"value":3601},"{\"project\":{\"observability\":[{\"role_id\":\"admin\",\"organization_id\":\"$ORG_ID\",\"all\":false,\"project_ids\":[\"$PROJECT_ID\"]}]}}",{"type":43,"tag":697,"props":3603,"children":3604},{"style":709},[3605],{"type":48,"value":1917},{"type":43,"tag":51,"props":3607,"children":3608},{},[3609,3610,3615,3616,3621,3622,3627,3629,3634,3636,3642,3644,3650],{"type":48,"value":2680},{"type":43,"tag":79,"props":3611,"children":3613},{"className":3612},[],[3614],{"type":48,"value":3429},{"type":48,"value":1612},{"type":43,"tag":79,"props":3617,"children":3619},{"className":3618},[],[3620],{"type":48,"value":2686},{"type":48,"value":1956},{"type":43,"tag":79,"props":3623,"children":3625},{"className":3624},[],[3626],{"type":48,"value":2693},{"type":48,"value":3628}," with actual values. Use ",{"type":43,"tag":79,"props":3630,"children":3632},{"className":3631},[],[3633],{"type":48,"value":1834},{"type":48,"value":3635}," to look up the user ID. To\nremove a role assignment, use ",{"type":43,"tag":79,"props":3637,"children":3639},{"className":3638},[],[3640],{"type":48,"value":3641},"remove-role-assignment",{"type":48,"value":3643}," with the same ",{"type":43,"tag":79,"props":3645,"children":3647},{"className":3646},[],[3648],{"type":48,"value":3649},"--roles",{"type":48,"value":3651}," schema.",{"type":43,"tag":363,"props":3653,"children":3655},{"id":3654},"list-all-members-and-their-roles",[3656],{"type":48,"value":3657},"List all members and their roles",{"type":43,"tag":51,"props":3659,"children":3660},{},[3661,3665],{"type":43,"tag":64,"props":3662,"children":3663},{},[3664],{"type":48,"value":2755},{"type":48,"value":3666}," \"Show me who has access to my organization.\"",{"type":43,"tag":686,"props":3668,"children":3670},{"className":688,"code":3669,"language":690,"meta":691,"style":691},"python3 skills\u002Fcloud\u002Faccess-management\u002Fscripts\u002Fcloud_access.py list-members\n",[3671],{"type":43,"tag":79,"props":3672,"children":3673},{"__ignoreMap":691},[3674],{"type":43,"tag":697,"props":3675,"children":3676},{"class":699,"line":700},[3677,3681,3685],{"type":43,"tag":697,"props":3678,"children":3679},{"style":1037},[3680],{"type":48,"value":1040},{"type":43,"tag":697,"props":3682,"children":3683},{"style":715},[3684],{"type":48,"value":1045},{"type":43,"tag":697,"props":3686,"children":3687},{"style":715},[3688],{"type":48,"value":1050},{"type":43,"tag":51,"props":3690,"children":3691},{},[3692],{"type":48,"value":3693},"The output includes each member's user ID, email, and assigned roles.",{"type":43,"tag":140,"props":3695,"children":3697},{"id":3696},"guidelines",[3698],{"type":48,"value":3699},"Guidelines",{"type":43,"tag":147,"props":3701,"children":3702},{},[3703,3721,3726,3731,3741,3802,3807,3880,3885,3890,3903,3927,3946,3957],{"type":43,"tag":151,"props":3704,"children":3705},{},[3706,3708,3713,3715,3719],{"type":48,"value":3707},"If ",{"type":43,"tag":79,"props":3709,"children":3711},{"className":3710},[],[3712],{"type":48,"value":84},{"type":48,"value":3714}," is not set, do not prompt the user — instruct the agent to invoke ",{"type":43,"tag":64,"props":3716,"children":3717},{},[3718],{"type":48,"value":75},{"type":48,"value":3720}," first.",{"type":43,"tag":151,"props":3722,"children":3723},{},[3724],{"type":48,"value":3725},"Always confirm destructive actions (remove member, revoke key) with the user before executing.",{"type":43,"tag":151,"props":3727,"children":3728},{},[3729],{"type":48,"value":3730},"Prefer predefined roles over custom roles when they satisfy the access requirement.",{"type":43,"tag":151,"props":3732,"children":3733},{},[3734,3736,3740],{"type":48,"value":3735},"API keys created here are additional keys for CI\u002FCD, scoped access, or team members. The initial key is managed by\n",{"type":43,"tag":64,"props":3737,"children":3738},{},[3739],{"type":48,"value":75},{"type":48,"value":138},{"type":43,"tag":151,"props":3742,"children":3743},{},[3744,3749,3751,3757,3758,3764,3765,3771,3773,3779,3781,3786,3788,3793,3795,3800],{"type":43,"tag":64,"props":3745,"children":3746},{},[3747],{"type":48,"value":3748},"Secrets are never printed to stdout or stderr.",{"type":48,"value":3750}," The script replaces sensitive fields (",{"type":43,"tag":79,"props":3752,"children":3754},{"className":3753},[],[3755],{"type":48,"value":3756},"key",{"type":48,"value":1612},{"type":43,"tag":79,"props":3759,"children":3761},{"className":3760},[],[3762],{"type":48,"value":3763},"token",{"type":48,"value":1633},{"type":43,"tag":79,"props":3766,"children":3768},{"className":3767},[],[3769],{"type":48,"value":3770},"invitation_token",{"type":48,"value":3772},") with a ",{"type":43,"tag":79,"props":3774,"children":3776},{"className":3775},[],[3777],{"type":48,"value":3778},"REDACTED",{"type":48,"value":3780}," placeholder in stdout and writes the full unredacted response to a temporary\nfile with 0600 (owner-read-only) permissions. The stdout JSON includes a ",{"type":43,"tag":79,"props":3782,"children":3784},{"className":3783},[],[3785],{"type":48,"value":2973},{"type":48,"value":3787}," path pointing to that file.\n",{"type":43,"tag":64,"props":3789,"children":3790},{},[3791],{"type":48,"value":3792},"Never attempt to read, extract, or summarize the contents of the secret file.",{"type":48,"value":3794}," If the user asks for the key, tell\nthem to open the file at the ",{"type":43,"tag":79,"props":3796,"children":3798},{"className":3797},[],[3799],{"type":48,"value":2973},{"type":48,"value":3801}," path. After the user retrieves the secret, advise them to delete the file.",{"type":43,"tag":151,"props":3803,"children":3804},{},[3805],{"type":48,"value":3806},"Cloud API keys inherit roles at creation and cannot be updated — revoke and recreate to change roles.",{"type":43,"tag":151,"props":3808,"children":3809},{},[3810,3815],{"type":43,"tag":64,"props":3811,"children":3812},{},[3813],{"type":48,"value":3814},"API key hygiene — minimize, scope, and expire:",{"type":43,"tag":147,"props":3816,"children":3817},{},[3818,3836,3863,3875],{"type":43,"tag":151,"props":3819,"children":3820},{},[3821,3823,3828,3830,3834],{"type":48,"value":3822},"Before creating a key, always run ",{"type":43,"tag":79,"props":3824,"children":3826},{"className":3825},[],[3827],{"type":48,"value":1094},{"type":48,"value":3829}," and check whether an existing key ",{"type":43,"tag":64,"props":3831,"children":3832},{},[3833],{"type":48,"value":1101},{"type":48,"value":3835},"\nalready has the required roles and sufficient remaining lifetime. Keys with identical permissions serving different\npurposes (for example, two separate CI pipelines) are legitimate — the goal is to avoid redundant keys for the same\ntask.",{"type":43,"tag":151,"props":3837,"children":3838},{},[3839,3841,3847,3849,3855,3856,3862],{"type":48,"value":3840},"Always set an ",{"type":43,"tag":79,"props":3842,"children":3844},{"className":3843},[],[3845],{"type":48,"value":3846},"--expiration",{"type":48,"value":3848}," that matches the intended task lifetime. Short-lived tasks (CI runs, one-time\nmigrations) should use short-lived keys (for example, ",{"type":43,"tag":79,"props":3850,"children":3852},{"className":3851},[],[3853],{"type":48,"value":3854},"1d",{"type":48,"value":1612},{"type":43,"tag":79,"props":3857,"children":3859},{"className":3858},[],[3860],{"type":48,"value":3861},"7d",{"type":48,"value":591},{"type":43,"tag":151,"props":3864,"children":3865},{},[3866,3868,3873],{"type":48,"value":3867},"After a task is complete, prompt the user to revoke any keys that are no longer needed using ",{"type":43,"tag":79,"props":3869,"children":3871},{"className":3870},[],[3872],{"type":48,"value":2981},{"type":48,"value":3874},". This\napplies to both short-lived and long-running keys.",{"type":43,"tag":151,"props":3876,"children":3877},{},[3878],{"type":48,"value":3879},"Long-running keys (for example, monitoring pipelines) should still have a defined expiration and be rotated\nperiodically rather than set to never expire.",{"type":43,"tag":151,"props":3881,"children":3882},{},[3883],{"type":48,"value":3884},"Each organization supports up to 500 active API keys. Default expiration is 3 months.",{"type":43,"tag":151,"props":3886,"children":3887},{},[3888],{"type":48,"value":3889},"Invitations expire after 72 hours by default. Resend if the user has not accepted.",{"type":43,"tag":151,"props":3891,"children":3892},{},[3893,3895,3902],{"type":48,"value":3894},"For SAML SSO configuration, refer to\n",{"type":43,"tag":132,"props":3896,"children":3899},{"href":3897,"rel":3898},"https:\u002F\u002Fwww.elastic.co\u002Fdocs\u002Fdeploy-manage\u002Fusers-roles\u002Fcloud-organization\u002Fconfigure-saml-authentication",[666],[3900],{"type":48,"value":3901},"Elastic Cloud SAML docs",{"type":48,"value":138},{"type":43,"tag":151,"props":3904,"children":3905},{},[3906,3911,3913,3918,3920,3925],{"type":43,"tag":64,"props":3907,"children":3908},{},[3909],{"type":48,"value":3910},"Custom role security — do not over-assign:",{"type":48,"value":3912}," Never assign a predefined Cloud role (for example, ",{"type":43,"tag":79,"props":3914,"children":3916},{"className":3915},[],[3917],{"type":48,"value":1331},{"type":48,"value":3919},") for a\nproject when using ",{"type":43,"tag":79,"props":3921,"children":3923},{"className":3922},[],[3924],{"type":48,"value":1686},{"type":48,"value":3926}," for the same project. The custom role assignment implicitly grants\nViewer-level Cloud access. Adding a predefined role on top widens the user's in-project permissions beyond what the\ncustom role intended.",{"type":43,"tag":151,"props":3928,"children":3929},{},[3930,3932,3937,3939,3944],{"type":48,"value":3931},"If a custom role exists but the user cannot access the project, verify the role was assigned with ",{"type":43,"tag":79,"props":3933,"children":3935},{"className":3934},[],[3936],{"type":48,"value":1686},{"type":48,"value":3938},"\n(which uses ",{"type":43,"tag":79,"props":3940,"children":3942},{"className":3941},[],[3943],{"type":48,"value":201},{"type":48,"value":3945}," in the Cloud API). Creating a custom role alone does not grant project access — the\nCloud API assignment is required.",{"type":43,"tag":151,"props":3947,"children":3948},{},[3949,3951,3956],{"type":48,"value":3950},"For network-level security (traffic filters, private links), see the ",{"type":43,"tag":64,"props":3952,"children":3953},{},[3954],{"type":48,"value":3955},"cloud-network-security",{"type":48,"value":125},{"type":43,"tag":151,"props":3958,"children":3959},{},[3960,3962,3966],{"type":48,"value":3961},"For ES-level role management beyond Cloud roles (native users, DLS\u002FFLS), see ",{"type":43,"tag":64,"props":3963,"children":3964},{},[3965],{"type":48,"value":123},{"type":48,"value":138},{"type":43,"tag":3968,"props":3969,"children":3970},"style",{},[3971],{"type":48,"value":3972},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3974,"total":4055},[3975,3982,3995,4004,4018,4029,4044],{"slug":4,"name":4,"fn":5,"description":6,"org":3976,"tags":3977,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3978,3979,3980,3981],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":109,"name":109,"fn":3983,"description":3984,"org":3985,"tags":3986,"stars":23,"repoUrl":24,"updatedAt":3994},"create Elastic Cloud Serverless projects","Creates Elastic Cloud Serverless projects (Elasticsearch, Observability, or Security) via the REST API, saves credentials to file, and bootstraps a scoped Elasticsearch API key. Use when creating a new serverless project, provisioning a search or observability environment, or spinning up a new Elastic Cloud project.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3987,3988,3991],{"name":21,"slug":22,"type":15},{"name":3989,"slug":3990,"type":15},"Deployment","deployment",{"name":3992,"slug":3993,"type":15},"Elasticsearch","elasticsearch","2026-07-12T07:46:42.353362",{"slug":116,"name":116,"fn":3996,"description":3997,"org":3998,"tags":3999,"stars":23,"repoUrl":24,"updatedAt":4003},"manage Elastic Cloud Serverless projects","Manages existing Elastic Cloud Serverless projects: list, get, update, delete, reset credentials, resume, and load saved credentials. Connects to existing projects by resolving endpoints and acquiring scoped Elasticsearch API keys. Use when performing day-2 operations on serverless projects, connecting to an existing project, loading or resetting project credentials, or looking up project details.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4000,4001,4002],{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},{"name":17,"slug":18,"type":15},"2026-07-12T07:46:41.097412",{"slug":3955,"name":3955,"fn":4005,"description":4006,"org":4007,"tags":4008,"stars":23,"repoUrl":24,"updatedAt":4017},"manage Elastic Cloud network security","Manage Serverless network security (traffic filters): create, update, and delete IP filters and AWS PrivateLink VPC filters. Use when restricting network access or configuring private connectivity.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4009,4010,4011,4014],{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4012,"slug":4013,"type":15},"Networking","networking",{"name":4015,"slug":4016,"type":15},"Security","security","2026-07-12T07:46:43.675992",{"slug":75,"name":75,"fn":4019,"description":4020,"org":4021,"tags":4022,"stars":23,"repoUrl":24,"updatedAt":4028},"configure Elastic Cloud authentication","Configures Elastic Cloud authentication and environment defaults. Use when setting up EC_API_KEY, configuring Cloud API access, or when another cloud skill requires credentials.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4023,4026,4027],{"name":4024,"slug":4025,"type":15},"Authentication","authentication",{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},"2026-07-12T07:46:39.783105",{"slug":4030,"name":4030,"fn":4031,"description":4032,"org":4033,"tags":4034,"stars":23,"repoUrl":24,"updatedAt":4043},"elasticsearch-audit","configure Elasticsearch security audit logs","Enable, configure, and query Elasticsearch security audit logs. Use when the task involves audit logging setup, event filtering, or investigating security incidents like failed logins.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4035,4038,4039,4042],{"name":4036,"slug":4037,"type":15},"Audit","audit",{"name":3992,"slug":3993,"type":15},{"name":4040,"slug":4041,"type":15},"Logs","logs",{"name":4015,"slug":4016,"type":15},"2026-07-12T07:47:35.092599",{"slug":4045,"name":4045,"fn":4046,"description":4047,"org":4048,"tags":4049,"stars":23,"repoUrl":24,"updatedAt":4054},"elasticsearch-authn","configure Elasticsearch authentication realms","Authenticate to Elasticsearch using native, file-based, LDAP\u002FAD, SAML, OIDC, Kerberos, JWT, or certificate realms. Use when connecting with credentials, choosing a realm, or managing API keys. Assumes the target realms are already configured.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4050,4051,4052,4053],{"name":4024,"slug":4025,"type":15},{"name":9,"slug":8,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4015,"slug":4016,"type":15},"2026-07-12T07:47:41.474547",35,{"items":4057,"total":4178},[4058,4077,4094,4107,4114,4120,4126,4133,4139,4146,4153,4165],{"slug":4059,"name":4059,"fn":4060,"description":4061,"org":4062,"tags":4063,"stars":4074,"repoUrl":4075,"updatedAt":4076},"accessing-benchmark-results","retrieve and analyze Rally benchmark results","Retrieve Rally benchmark results from an external Elasticsearch metrics store. Use to list past races, get a single race's overall (per-task) results, chart a metric's trend across multiple runs, compare two races, or check whether a run converged — e.g. \"show me recent geonames races\", \"what's the service_time trend for nyc_taxis over the last 30 days?\", \"compare these two race-ids\". Applies when datastore.type = elasticsearch is set in ~\u002F.rally\u002Frally.ini.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4064,4067,4070,4071],{"name":4065,"slug":4066,"type":15},"Analytics","analytics",{"name":4068,"slug":4069,"type":15},"Data Analysis","data-analysis",{"name":9,"slug":8,"type":15},{"name":4072,"slug":4073,"type":15},"Performance","performance",2027,"https:\u002F\u002Fgithub.com\u002Felastic\u002Frally","2026-07-12T07:46:38.54144",{"slug":4078,"name":4078,"fn":4079,"description":4080,"org":4081,"tags":4082,"stars":4074,"repoUrl":4075,"updatedAt":4093},"developing-rally","develop and debug Rally source code","Work on Rally's own codebase, not running benchmarks with it. Use when setting up the dev environment, running Rally's tests or linters, navigating its source, debugging Rally's own code, or making changes to Rally itself.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4083,4086,4087,4090],{"name":4084,"slug":4085,"type":15},"Debugging","debugging",{"name":9,"slug":8,"type":15},{"name":4088,"slug":4089,"type":15},"Engineering","engineering",{"name":4091,"slug":4092,"type":15},"Local Development","local-development","2026-07-12T07:46:35.976807",{"slug":4095,"name":4095,"fn":4096,"description":4097,"org":4098,"tags":4099,"stars":4074,"repoUrl":4075,"updatedAt":4106},"running-benchmarks","run Rally benchmarks against Elasticsearch","Run Rally benchmarks (races) against Elasticsearch — an existing\u002Fexternal cluster or a Rally-provisioned distribution — and read the summary report. Use when running a race (any pipeline, track, challenge, target-hosts, or auth) or when interpreting throughput, latency, and service_time results.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4100,4101,4102,4103],{"name":9,"slug":8,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4072,"slug":4073,"type":15},{"name":4104,"slug":4105,"type":15},"Testing","testing","2026-07-12T07:46:37.277964",{"slug":4,"name":4,"fn":5,"description":6,"org":4108,"tags":4109,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4110,4111,4112,4113],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":109,"name":109,"fn":3983,"description":3984,"org":4115,"tags":4116,"stars":23,"repoUrl":24,"updatedAt":3994},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4117,4118,4119],{"name":21,"slug":22,"type":15},{"name":3989,"slug":3990,"type":15},{"name":3992,"slug":3993,"type":15},{"slug":116,"name":116,"fn":3996,"description":3997,"org":4121,"tags":4122,"stars":23,"repoUrl":24,"updatedAt":4003},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4123,4124,4125],{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},{"name":17,"slug":18,"type":15},{"slug":3955,"name":3955,"fn":4005,"description":4006,"org":4127,"tags":4128,"stars":23,"repoUrl":24,"updatedAt":4017},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4129,4130,4131,4132],{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4012,"slug":4013,"type":15},{"name":4015,"slug":4016,"type":15},{"slug":75,"name":75,"fn":4019,"description":4020,"org":4134,"tags":4135,"stars":23,"repoUrl":24,"updatedAt":4028},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4136,4137,4138],{"name":4024,"slug":4025,"type":15},{"name":21,"slug":22,"type":15},{"name":3992,"slug":3993,"type":15},{"slug":4030,"name":4030,"fn":4031,"description":4032,"org":4140,"tags":4141,"stars":23,"repoUrl":24,"updatedAt":4043},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4142,4143,4144,4145],{"name":4036,"slug":4037,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4040,"slug":4041,"type":15},{"name":4015,"slug":4016,"type":15},{"slug":4045,"name":4045,"fn":4046,"description":4047,"org":4147,"tags":4148,"stars":23,"repoUrl":24,"updatedAt":4054},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4149,4150,4151,4152],{"name":4024,"slug":4025,"type":15},{"name":9,"slug":8,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4015,"slug":4016,"type":15},{"slug":123,"name":123,"fn":4154,"description":4155,"org":4156,"tags":4157,"stars":23,"repoUrl":24,"updatedAt":4164},"manage Elasticsearch RBAC and security roles","Manage Elasticsearch RBAC: native users, roles, role mappings, document- and field-level security. Use when creating users or roles, assigning privileges, or mapping external realms like LDAP\u002FSAML.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4158,4159,4160,4163],{"name":9,"slug":8,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4161,"slug":4162,"type":15},"RBAC","rbac",{"name":4015,"slug":4016,"type":15},"2026-07-12T07:47:36.394177",{"slug":4166,"name":4166,"fn":4167,"description":4168,"org":4169,"tags":4170,"stars":23,"repoUrl":24,"updatedAt":4177},"elasticsearch-esql","query Elasticsearch data with ES|QL","Execute ES|QL (Elasticsearch Query Language) queries, use when the user wants to query Elasticsearch data, analyze logs, aggregate metrics, explore data, or create charts and dashboards from ES|QL results.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4171,4172,4173,4174],{"name":4065,"slug":4066,"type":15},{"name":4068,"slug":4069,"type":15},{"name":3992,"slug":3993,"type":15},{"name":4175,"slug":4176,"type":15},"SQL","sql","2026-07-12T07:47:40.249533",86]