关于 cloud-access-management
cloud-access-management 是用于管理 Elastic Cloud 组织及 Serverless 项目身份与访问权限的技能,面向组织成员和项目访问管理。它涵盖成员邀请、角色分配、自定义角色及 Cloud API 密钥,并要求先由 cloud-setup 配置环境。
主要功能
- 01邀请、列出和移除组织成员
- 02分配组织级与项目级角色
- 03创建和管理 Cloud API 密钥
- 04创建并分配 Serverless 自定义角色
适用场景
- 01为新成员授予 Serverless 项目访问权限
- 02调整现有成员的项目角色
- 03为程序化访问创建或撤销 API 密钥
- 04按索引和集群权限创建自定义角色
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elastic/ agent-skills --skill cloud-access-management安装后在 Claude Code 中输入/cloud-access-management确认已加载。
附带文件references/api-reference.mdscripts/cloud_access.py
详细介绍
Cloud Access Management
管理 Elastic Cloud 组织及其 Serverless 项目的身份与访问权限:邀请用户、分配预定义或自定义角色,以及管理 Cloud API 密钥。
**前提条件:**此技能假设 cloud-setup 技能已运行——
EC_API_KEY已在环境中设置,且组织上下文已建立。如果缺少EC_API_KEY,请指示 Agent 先调用 cloud-setup。不要直接向用户索要 API 密钥。
如需创建项目,请参阅 cloud-create-project 技能。如需执行第 2 天项目操作(列出、更新、删除),请参阅 cloud-manage-project。如需管理 Elasticsearch 级别的角色(原生用户、角色映射、DLS/FLS),请参阅 elasticsearch-authz 技能。
有关详细的 API 端点和请求架构,请参阅 references/api-reference.md。
待办事项
- 邀请用户加入组织,并为其分配 Serverless 项目角色
- 列出组织成员及其当前角色分配
- 更新用户的角色(组织级或项目级)
- 将用户从组织中移除
- 创建具有指定角色和有效期的额外 Cloud API 密钥
- 创建也可在 Serverless 项目上调用 Elasticsearch 和 Kibana API 的 Cloud API 密钥
- 列出并撤销 Cloud API 密钥
- 在 Serverless 项目中创建具有 ES 集群、索引和 Kibana 权限的自定义角色
- 使用 Cloud API 的
application_roles为用户分配或移除其在 Serverless 项目上的自定义角色 - 将自然语言访问请求转换为邀请、角色和 API 密钥相关任务
前提条件和权限
| 项目 | 描述 |
|---|---|
| EC_API_KEY | Cloud API 密钥(由 cloud-setup 设置)。所有操作都需要此密钥。 |
| 组织 ID | 使用 GET /organizations 自动发现。不要向用户索取。 |
| 项目端点 | Serverless 项目的 Elasticsearch 端点。仅自定义角色操作需要。 |
| ES 凭据 | 在项目上具有 manage_security 权限的 API 密钥或凭据。仅自定义角色操作需要。 |
| 组织所有者角色 | 只有组织所有者才能创建和管理 Cloud API 密钥。API 密钥操作需要此角色。 |
在执行任何操作前,运行 python3 skills/cloud/access-management/scripts/cloud_access.py list-members,以验证 EC_API_KEY 有效并自动发现组织 ID。
操作级权限
Elastic Cloud Serverless 中常见访问管理操作需要以下权限。
| 操作 | 所需权限 |
|---|---|
| 邀请或移除成员 | 组织所有者(organization-admin) |
| 分配或移除角色 | 组织所有者(organization-admin) |
| 创建或撤销 Cloud API 密钥 | 组织所有者(organization-admin) |
| 列出成员、邀请或密钥 | 任意组织成员 |
| 创建或删除自定义角色 | 项目 ES 端点上的 manage_security 集群权限 |
此技能不会单独预先检查角色。请尝试执行所请求的操作,并由 API 强制执行授权。如果 API 返回授权错误(例如 403 Forbidden),请停止操作,并要求用户确认所提供的 API 密钥权限。
手动设置备用方案(cloud-setup 不可用时)
如果此技能是独立安装的,且 cloud-setup 不可用,请告知用户在运行命令前手动配置 Cloud 环境变量。切勿要求用户在聊天中粘贴 API 密钥。
| 变量 | 必需性 | 描述 |
|---|---|---|
EC_API_KEY | 是 | 具有 Organization owner 角色的 Elastic Cloud API 密钥。 |
EC_BASE_URL | 否 | Cloud API 基础 URL(默认值:https://api.elastic-cloud.com)。 |
ELASTICSEARCH_URL | 有条件 | Elasticsearch URL。仅自定义角色操作需要。 |
ELASTICSEARCH_API_KEY | 有条件 | 具有 manage_security 权限的 Elasticsearch API 密钥。仅自定义角色操作需要。 |
注意: 如果缺少
EC_API_KEY,或用户还没有 Cloud API 密钥,请引导用户前往 Elastic Cloud API keys 生成密钥,然后按照以下步骤在本地配置。
首选方法(适合 Agent):在项目根目录创建 .env 文件:
EC_API_KEY=your-api-key
EC_BASE_URL=https://api.elastic-cloud.com
# Only needed for custom role operations against the project Elasticsearch endpoint:
# ELASTICSEARCH_URL=https://<project-id>.es.<region>.elastic-cloud.com
# ELASTICSEARCH_API_KEY=<your-es-manage-security-api-key>
所有 cloud/* 脚本都会自动从工作目录加载 .env。
替代方法:直接在终端中导出:
export EC_API_KEY="<your-cloud-api-key>"
export EC_BASE_URL="https://api.elastic-cloud.com"
# Only needed for custom role operations against the project Elasticsearch endpoint:
# export ELASTICSEARCH_URL="https://<project-id>.es.<region>.elastic-cloud.com"
# export ELASTICSEARCH_API_KEY="<your-es-manage-security-api-key>"
终端中的导出变量可能无法被运行在独立 Shell 会话中的沙盒 Agent 访问,因此使用 Agent 时优先选择 .env。
拆解访问权限请求
当用户用自然语言描述访问权限需求时(例如,“将 Alice 添加为我的搜索项目的开发者”),请在执行前将请求拆分为具体任务。
步骤 1 — 确认各项要素
| 要素 | 需要回答的问题 |
|---|---|
| 对象 | 新的组织成员(邀请),还是现有成员(更新角色)? |
| 范围 | 哪些 Serverless 项目,或组织级访问权限? |
| 访问级别 | 预定义角色(Admin/Developer/Viewer/Editor),还是自定义角色? |
| API 密钥? | 请求是否还需要用于编程访问的 Cloud API 密钥? |
步骤 2 — 检查预定义角色是否合适
查阅下方的预定义角色表。优先使用预定义角色 — 仅当预定义角色无法提供所需的粒度时,才创建自定义角色。
步骤 3 — 检查现有状态
在创建或邀请之前,先检查现有内容:
python3 skills/cloud/access-management/scripts/cloud_access.py list-members
python3 skills/cloud/access-management/scripts/cloud_access.py list-api-keys
如果用户已经是成员,则跳过邀请,改为更新其角色。
对于 API 密钥请求,只有 Organization owners 才能创建和管理 Cloud API 密钥。如果已通过身份验证的用户没有 organization-admin 角色,API 密钥操作将因 403 错误而失败。查看 list-api-keys 返回的现有密钥。如果已有一个用于相同目的或任务的活动密钥,且具备所需角色并有足够的剩余有效期,请重复使用,而不是创建新密钥。如果两个密钥权限相同,但用途不同(例如,用于不同的 CI 管道),则可以同时存在;但为同一任务创建第二个密钥没有必要,还会增加管理负担。
步骤 4 — 执行
运行 skills/cloud/access-management/scripts/cloud_access.py 中相应的命令。执行破坏性操作(移除成员、撤销密钥)前,请先与用户确认。
步骤 5 — 验证
执行后,再次列出成员或密钥,以确认更改已生效。
预定义角色
组织级角色
| 角色 | Cloud API role_id | 描述 |
|---|---|---|
| 组织所有者 | organization-admin | 对组织、部署和项目拥有完整的管理权限 |
| 账单管理员 | billing-admin | 仅管理账单详情 |
无服务器项目级角色
| 角色 | Cloud API role_id | 适用范围 | 描述 |
|---|---|---|---|
| 管理员 | admin | Search、Obs、Security | 完整的项目管理权限,登录后拥有超级用户权限 |
| 开发者 | developer | 仅限 Search | 创建索引、API 密钥、连接器和可视化 |
| 查看者 | viewer | Search、Obs、Security | 对项目数据和功能拥有只读访问权限 |
| 编辑者 | editor | Obs、Security | 配置项目功能,对数据索引拥有只读访问权限 |
| 一级分析师 | t1_analyst | 仅限 Security | 告警分流、常规读取、创建仪表板 |
| 二级分析师 | t2_analyst | 仅限 Security | 告警分流、启动调查、创建案例 |
| 三级分析师 | t3_analyst | 仅限 Security | 深入调查、规则、列表、响应操作 |
| SOC 经理 | soc_manager | 仅限 Security | 告警、案例、端点策略、响应操作 |
| 规则作者 | rule_author | 仅限 Security | 检测工程、规则创建 |
项目级角色会在邀请时(POST /organizations/{org_id}/invitations)分配,也可以通过角色分配更新接口(POST /users/{user_id}/role_assignments)进行分配。有关包含 project 范围的 role_assignments JSON 架构,请参阅
references/api-reference.md。
自定义角色(无服务器)
如果预定义角色无法满足所需的细化程度,可以在无服务器项目中使用 Elasticsearch 安全 API 创建自定义角色,并通过 Cloud API 的 application_roles 字段将其分配给用户。
安全提示:使用自定义角色时,不要另外分配预定义的 Cloud 角色。 自定义角色会隐式授予项目范围内的查看者级 Cloud 访问权限。如果还将
viewer(或任何其他预定义角色)作为单独的 Cloud 角色分配给同一项目,用户通过 SSO 登录项目时会获得两种角色权限的并集——查看者栈角色的权限范围比大多数自定义角色更广,会覆盖你原本想要设置的限制。
自定义角色分配的工作方式
- 预定义角色(
viewer、developer、admin等)通过 Cloud API(invite-user、assign-role)分配。当用户通过 SSO 登录项目时,会获得映射到其 Cloud 角色的堆栈角色(例如,Cloudviewer映射到viewer堆栈角色)。 - 自定义角色通过 Elasticsearch 安全 API(
create-custom-role)在项目中创建,并通过 Cloud API 的application_roles字段(assign-custom-role)分配。设置application_roles后,用户通过 SSO 登录时只会获得指定的自定义角色,而不会获得其 Cloud 角色对应的默认堆栈角色。 assign-custom-role命令会将role_id设为项目类型对应的 Viewer 角色(elasticsearch-viewer、observability-viewer或security-viewer),并将application_roles设为自定义角色名称。这样可确保用户能在 Cloud 控制台中查看和访问项目,但在项目内只获得自定义角色所限制的权限。- Cloud API 密钥也可以使用
application_roles,以在 Serverless 项目上获得 ES/Kibana API 访问权限。详情请参阅下文的 Cloud API 密钥 — ES 和 Kibana API 访问权限。
自定义角色的标准引导流程
- 在项目中创建自定义角色(
create-custom-role)。 - 如果用户尚未加入组织,则邀请其加入(
invite-user)。邀请中不要包含项目角色分配——下一步的自定义角色分配会处理项目访问权限。 - 将自定义角色分配给用户(
assign-custom-role --user-id ... --project-id ... --custom-role-name ...)。 - 使用
list-members和list-roles进行验证。
创建自定义角色
python3 skills/cloud/access-management/scripts/cloud_access.py create-custom-role \
--role-name marketing-analyst \
--body '{"cluster":[],"indices":[{"names":["marketing-*"],"privileges":["read","view_index_metadata"]}]}'
这会在项目的 Elasticsearch 端点上调用 PUT /_security/role/{name}。
命名限制
角色名称必须以字母或数字开头,且只能包含字母、数字、_、- 和 .。Serverless 中不提供 Run-as 权限。
何时使用自定义角色而非预定义角色
| 场景 | 使用 |
|---|---|
| 标准管理员/开发者/查看者访问权限 | 预定义角色 |
| 对特定索引模式的只读访问权限 | 自定义角色 |
| DLS 或 FLS 限制 | 自定义角色 |
| Kibana 功能级访问控制 | 自定义角色 |
有关高级 DLS/FLS 模式(模板化查询、ABAC),请参阅 elasticsearch-authz 技能。
Cloud API 密钥 — ES 和 Kibana API 访问权限
Cloud API 密钥现在也可以选择在 Serverless 项目上访问 Elasticsearch 和 Kibana API,而不仅限于 Cloud API。这样,单个凭据即可同时用于控制平面(Cloud API)和数据平面(ES/Kibana API)操作——例如,CI 管道通过 Cloud API 创建项目后,再通过 ES API 索引数据。
工作方式
创建密钥时,将 application_roles 添加到密钥的 role_assignments 中。此字段接受预定义角色名称数组(admin、developer、viewer 以及解决方案专属角色,例如 t1_analyst、editor),也接受通过 PUT /_security/role/{name} 在项目中创建的自定义角色名称。每个项目默认都提供预定义角色。必须在密钥需要访问的每个项目中单独创建自定义角色——如果某个项目中不存在所引用的自定义角色,密钥在该项目中将不会获得任何访问权限,且不会显示提示。
关键规则:不会隐式继承
与用户不同,API 密钥绝不会从其 role_id 继承堆栈角色。如果省略 application_roles 或将其留空,密钥将仅能访问 Cloud API。使用此类密钥调用 ES 或 Kibana 端点会返回 403 Forbidden。这是为了向后兼容而设计的——现有未设置 application_roles 的密钥会继续作为仅限 Cloud 的密钥使用。
作用域模式
-
项目作用域(首选)——授予对特定项目或指定类型的所有项目的访问权限。在
role_assignments中使用project键,并在每个条目中设置application_roles。除非用户明确需要跨项目访问权限,否则默认使用此模式。 -
组织作用域——授予对组织中所有现有和未来项目的访问权限。在
role_assignments中使用organization键,并设置application_roles。**这是数据平面的最大作用域。**仅当密钥确实需要访问每个项目时才使用此模式(例如,平台自动化,或在整个组织范围内进行跨项目搜索)。使用application_roles创建组织作用域密钥前,务必先与用户确认,因为它会授予对可能尚不存在的项目的 ES/Kibana 访问权限。
**自定义角色和组织作用域访问:**在组织作用域分配中使用
application_roles指定自定义角色名称时,必须在需要授予密钥访问权限的每个项目中都创建该自定义角色。如果某个项目未定义该自定义角色(通过PUT /_security/role/{name}),密钥将静默地无法访问该项目——不会报错。对于组织范围的访问,建议使用预定义角色(admin、developer、viewer),这些角色默认在每个项目中都可用。如果必须在多个项目中使用自定义角色,请先确保已在每个目标项目中创建该角色。
**Agent 指南:**用户请求具有 ES/Kibana 访问权限的 API 密钥时,默认使用项目作用域分配。只有当用户明确需要访问所有项目时,才建议使用组织作用域
application_roles。继续操作前,请确认用户意图——组织作用域访问也适用于未来的项目。如果用户指定了组织作用域访问的自定义角色名称,请提醒他们必须在每个项目中分别定义该角色。
示例
具有 developer ES 访问权限的项目作用域密钥(使用 --stack-access 便捷标志):
python3 skills/cloud/access-management/scripts/cloud_access.py create-api-key \
--description "CI pipeline - ES ingest" \
--expiration 30d \
--roles '{"project":{"elasticsearch":[{"role_id":"developer","organization_id":"$ORG_ID","all":true}]}}' \
--stack-access developer
具有 admin ES 访问权限的组织作用域密钥(可访问所有项目——请谨慎使用):
python3 skills/cloud/access-management/scripts/cloud_access.py create-api-key \
--description "Platform automation" \
--expiration 7d \
--roles '{"organization":[{"role_id":"organization-admin","organization_id":"$ORG_ID"}]}' \
--stack-access admin
使用自定义角色的项目作用域密钥(原始 JSON):
python3 skills/cloud/access-management/scripts/cloud_access.py create-api-key \
--description "Marketing ETL" \
--expiration 14d \
--roles '{"project":{"elasticsearch":[{"role_id":"elasticsearch-viewer","organization_id":"$ORG_ID","all":false,"project_ids":["$PROJECT_ID"],"application_roles":["marketing-writer"]}]}}'
将 $ORG_ID 和 $PROJECT_ID 替换为实际的组织 ID 和项目 ID。使用 list-members 查找组织 ID。
**常见错误:**如果 API 密钥在调用 ES 或 Kibana 端点时返回 403,最可能的原因是缺少
application_roles。与用户不同,API 密钥必须显式设置application_roles才能访问堆栈——仅设置role_id并不足够。
示例
邀请用户以 Viewer 身份加入搜索项目
提示词:“将 [email protected] 添加到我的搜索项目,并授予只读访问权限。”
python3 skills/cloud/access-management/scripts/cloud_access.py invite-user \
--emails [email protected] \
--roles '{"project":{"elasticsearch":[{"role_id":"viewer","organization_id":"$ORG_ID","all":false,"project_ids":["$PROJECT_ID"]}]}}'
将 $ORG_ID 和 $PROJECT_ID 替换为实际的 ID。接受邀请后,将为用户分配 Viewer 角色。若要授予自定义角色访问权限,请在用户接受邀请后使用 assign-custom-role——不要为同一项目同时分配预定义角色和自定义角色。
创建 CI/CD API 密钥
提示词:“为我们的 CI 流水线创建一个 API 密钥,30 天后过期,并可编辑所有部署。”
python3 skills/cloud/access-management/scripts/cloud_access.py create-api-key \
--description "CI/CD pipeline" \
--expiration "30d" \
--roles '{"deployment":[{"role_id":"deployment-editor","all":true}]}'
实际密钥值会写入权限为 0600 的安全临时文件。stdout JSON 中包含 _secret_file 路径,而不是原始密钥。请告知用户从该文件中获取密钥——密钥仅显示一次。当 CI 流水线不再需要此密钥时,请使用 delete-api-key 撤销它,以免未使用的密钥不断累积。
创建具有 ES 访问权限的 CI/CD API 密钥
提示词:“为我们的 CI 流水线创建一个 API 密钥,以便将数据编入搜索项目。”
python3 skills/cloud/access-management/scripts/cloud_access.py create-api-key \
--description "CI pipeline - ES ingest" \
--expiration 30d \
--roles '{"project":{"elasticsearch":[{"role_id":"developer","organization_id":"$ORG_ID","all":true}]}}' \
--stack-access developer
将 $ORG_ID 替换为实际的组织 ID。--stack-access 标志会在角色分配中注入 application_roles: ["developer"],授予该密钥对所有 Elasticsearch 项目的开发者级 ES/Kibana API 访问权限。如果不使用 --stack-access(也未在 JSON 中显式指定 application_roles),该密钥将只能访问 Cloud API,调用 ES/Kibana 时会收到 403 错误。
为营销数据创建自定义角色
提示词:“创建一个角色,使其对我的搜索项目中的 marketing-* 索引具有只读访问权限。”
python3 skills/cloud/access-management/scripts/cloud_access.py create-custom-role \
--role-name marketing-reader \
--body '{"cluster":[],"indices":[{"names":["marketing-*"],"privileges":["read","view_index_metadata"]}]}'
然后使用 assign-custom-role 命令将自定义角色分配给用户,该命令会在 Cloud API 角色分配中设置 application_roles。
用于只读仪表板的完整自定义角色流程
提示词:“将 [email protected] 添加到我的搜索项目,并授予只读仪表板访问权限。”
# 1) Create custom role in the project
python3 skills/cloud/access-management/scripts/cloud_access.py create-custom-role \
--role-name dashboard-reader \
--body '{"cluster":[],"indices":[],"applications":[{"application":"kibana-.kibana","privileges":["feature_dashboard.read"],"resources":["*"]}]}'
# 2) Invite user to the organization (no project roles — custom role handles access)
python3 skills/cloud/access-management/scripts/cloud_access.py invite-user \
--emails [email protected]
# 3) After invitation is accepted, assign the custom role via application_roles
python3 skills/cloud/access-management/scripts/cloud_access.py assign-custom-role \
--user-id "$USER_ID" \
--project-id "$PROJECT_ID" \
--project-type elasticsearch \
--custom-role-name dashboard-reader
用户将获得 Viewer 级别的 Cloud 访问权限(可在控制台中查看项目),并且在通过 SSO 登录项目时仅拥有 dashboard-reader 权限。不要同时为该项目单独分配 viewer Cloud 角色,否则将授予范围更广的 Viewer Stack 角色,并覆盖自定义角色的限制。
更新用户的项目角色
提示词:“将 Bob 在我们的可观测性项目中的角色提升为管理员。”
python3 skills/cloud/access-management/scripts/cloud_access.py assign-role \
--user-id "$USER_ID" \
--roles '{"project":{"observability":[{"role_id":"admin","organization_id":"$ORG_ID","all":false,"project_ids":["$PROJECT_ID"]}]}}'
将 $USER_ID、$ORG_ID 和 $PROJECT_ID 替换为实际值。使用 list-members 查找用户 ID。要移除角色分配,请使用 remove-role-assignment,并采用相同的 --roles 架构。
列出所有成员及其角色
提示词:“告诉我谁有权访问我的组织。”
python3 skills/cloud/access-management/scripts/cloud_access.py list-members
输出包含每位成员的用户 ID、电子邮件地址和已分配的角色。
指南
- 如果未设置
EC_API_KEY,不要提示用户输入;应指示 Agent 先调用 cloud-setup。 - 执行破坏性操作(移除成员、撤销密钥)前,始终先向用户确认。
- 如果预定义角色能够满足访问要求,优先使用预定义角色,而不是自定义角色。
- 在此处创建的 API 密钥是额外密钥,用于 CI/CD、限定访问权限或团队成员。初始密钥由 cloud-setup 管理。
- 绝不将机密信息输出到 stdout 或 stderr。 脚本会在 stdout 中将敏感字段(
key、token、invitation_token)替换为REDACTED占位符,并将完整的未脱敏响应写入权限为 0600(仅所有者可读)的临时文件。stdout 中的 JSON 包含指向该文件的_secret_file路径。绝不要尝试读取、提取或概述机密文件的内容。 如果用户索要密钥,告知他们打开_secret_file路径所指向的文件。用户获取机密信息后,提醒他们删除该文件。 - Cloud API 密钥在创建时继承角色,之后无法更新;如需更改角色,请先撤销密钥,再重新创建。
- API 密钥卫生——尽量减少数量、限定权限并设置有效期:
- 创建密钥前,始终先运行
list-api-keys,并检查是否已有用途或任务相同的密钥,且该密钥具有所需角色并有足够的剩余有效期。权限相同但用途不同的密钥(例如,供两个独立 CI 流水线使用的密钥)是合理的;目标是避免为同一任务创建多余密钥。 - 始终设置与任务预期时长相符的
--expiration。短期任务(CI 运行、一次性迁移)应使用短期密钥(例如1d、7d)。 - 任务完成后,提示用户使用
delete-api-key撤销不再需要的密钥。短期和长期密钥均适用。 - 长期密钥(例如,用于监控流水线的密钥)也应设置明确的有效期,并定期轮换,而不是设为永不过期。
- 创建密钥前,始终先运行
- 每个组织最多支持 500 个有效 API 密钥。默认有效期为 3 个月。
- 邀请默认在 72 小时后过期。如果用户尚未接受,请重新发送邀请。
- 有关 SAML SSO 配置,请参阅 Elastic Cloud SAML docs。
- 自定义角色安全——不要过度授权: 使用
assign-custom-role为某个项目分配自定义角色时,绝不要为同一项目分配预定义 Cloud 角色(例如viewer)。自定义角色分配会隐式授予 Viewer 级别的 Cloud 访问权限。在此基础上再添加预定义角色,会扩大用户在项目中的权限,超出自定义角色预期的范围。 - 如果自定义角色已存在,但用户无法访问项目,请确认是否已通过
assign-custom-role分配该角色(该命令会在 Cloud API 中使用application_roles)。仅创建自定义角色不会授予项目访问权限——必须通过 Cloud API 进行分配。 - 有关网络级安全(流量筛选器、专用链接),请参阅 cloud-network-security 技能。
- 有关超出 Cloud 角色范围的 ES 级角色管理(原生用户、DLS/FLS),请参阅 elasticsearch-authz。