本文为 SPIRE 官方文档 plugin_server_nodeattestor_aws_iid.md 的中文译本,以英文原文为准。 🔗 穿越源码分析:Server 详解 · NodeAttestor
Server 插件:NodeAttestor "aws_iid"
必须与 Agent 侧 aws_iid 插件配合使用
aws_iid 插件使用 AWS 实例元数据 API(Instance Metadata API)和 AWS 实例身份文档(Instance Identity document)自动对实例进行认证。它还允许运维人员在定义 SPIFFE ID 认证策略时使用 AWS 实例 ID(Instance ID)。由 aws_iid 认证器认证的 agent 会被签发形如 spiffe://example.org/spire/agent/aws_iid/ACCOUNT_ID/REGION/INSTANCE_ID 的 SPIFFE ID。此外,本插件还会将 agent 基于 AWS IID 的 SPIFFE ID 解析为一组 selector。
Configuration(配置)
| Configuration | Description | Default |
|---|---|---|
access_key_id | AWS access key id | AWS_ACCESS_KEY_ID 环境变量的值 |
secret_access_key | AWS secret access key | AWS_SECRET_ACCESS_KEY 环境变量的值 |
skip_block_device | 跳过防篡改机制,该机制会检查以确保底层根卷(root volume)在认证前未被分离(detached)。 | false |
disable_instance_profile_selectors | 禁用获取用于 selector 的、被认证实例的 instance profile 信息。适用于 server 无法访问 iam.amazonaws.com 的场景。 | false |
assume_role | 要担任(assume)的角色 | 空字符串,可选参数。 |
partition | SPIRE server 所运行的 AWS 分区(partition)<aws|aws-cn|aws-us-gov> | aws |
verify_organization | 验证节点属于指定的 AWS 组织(Organization)见下文 | |
validate_eks_cluster_membership | 验证节点属于指定的 EKS 集群 见下文 |
示例配置:
NodeAttestor "aws_iid" {
plugin_data {
access_key_id = "ACCESS_KEY_ID"
secret_access_key = "SECRET_ACCESS_KEY"
}
}如果设置了 assume_role,SPIRE server 会担任由模板 arn:{{Partition}}:iam::{{AccountID}}:role/{{AssumeRole}} 指定的角色,其中 Partition 来自 AWS NodeAttestor 插件配置(若指定),否则设为 'aws';AccountID 取自 SPIRE agent 发送给 SPIRE server 的 AWS IID 文档;AssumeRole 来自 AWS NodeAttestor 插件配置。关于模板引擎的详情,见模板引擎文档。
在以下配置中,
NodeAttestor "aws_iid" {
plugin_data {
assume_role = "spire-server-delegate"
}
}假设 spire agent 发送的 AWS IID 文档包含 accountId : 12345678,则 spire server 在为节点认证发起任何 AWS 调用之前,会先担任 "arn:aws:iam::12345678:role/spire-server-delegate" 角色。如果配置了 assume_role,即使 spire-server 和 spire agent 部署在同一账户中,spire server 也总是会担任该角色。
启用 AWS 节点认证的组织(Organization)校验
要为 AWS 节点认证方法配置组织校验,可使用以下配置:
| Field Name | Description | Constraints |
|---|---|---|
| management_account_id | 组织的账户 id(Account id) | 必填 |
| management_account_region | 管理账户 id 所在的区域(Region) | 可选 |
| assume_org_role | 具备列出账户(list accounts)能力的 IAM 角色名 | 必填 |
| org_account_map_ttl | 将账户列表缓存指定时长。应 >= 1 分钟。默认 3 分钟。 | 可选 |
使用 verify_organization 块将启用组织校验的节点认证方法。采用上述配置时,spire server 会构造并尝试担任如下角色:arn:aws:iam::management_account_id:role/assume_org_role。若不使用该功能,则该块(例如 verify_organization = {})不应为空——由于它是可选的,应将其完全移除,否则就应填入全部必填参数,即 management_account_id、assume_org_role。
assume_role 所指的角色必须创建在管理账户 management_account_id 中,并且它应当与 spire server 所担任的角色之间存在信任关系(trust relationship)。下面是一份示例策略,展示了所需的权限以及需要在管理账户中创建的信任关系。
策略(Policy):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "organizations:ListAccounts",
"Effect": "Allow",
"Resource": "*",
"Sid": "SpireOrganizationListAccountRole"
}
]
}信任关系(Trust Relationship):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CrossAccountAssumeRolePolicy",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::account-id-where-spire-is-running:role/spire-control-plane-root-server",
"arn:aws:iam::account-id-where-spire-is-running:role/spire-control-plane-regional-server"
]
},
"Action": "sts:AssumeRole"
}
]
}启用 AWS 节点认证的 EKS 集群校验
要为 AWS 节点认证方法配置 EKS 集群校验,可使用以下配置:
| Field Name | Description | Constraints |
|---|---|---|
| eks_cluster_names | 允许节点所属的 EKS 集群名称列表 | 必填 |
使用 validate_eks_cluster_membership 块将启用 EKS 集群校验的节点认证方法。采用上述配置时,SPIRE server 会验证被认证节点属于所指定的 EKS 集群之一。若不使用该功能,则该块(例如 validate_eks_cluster_membership = {})不应为空——由于它是可选的,应将其完全移除,否则就应填入全部必填参数,即 eks_cluster_names。
示例配置:
NodeAttestor "aws_iid" {
plugin_data {
validate_eks_cluster_membership = {
eks_cluster_names = ["production-cluster", "staging-cluster"]
}
}
}SPIRE server 会验证被认证的 EC2 实例属于某个自动伸缩组(Auto Scaling Group),而该伸缩组隶属于所指定的 EKS 集群之一。校验过程如下:
- 获取每个指定 EKS 集群的节点组(node group)列表
- 对每个节点组,获取其关联的自动伸缩组(Auto Scaling Group)
- 检查被认证的实例 ID 是否存在于这些自动伸缩组中的任意一个内
EKS 校验所需的 AWS IAM 权限
由所配置凭据标识的用户或角色,必须具备用于 EKS 集群校验的额外权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EKSClusterValidation",
"Effect": "Allow",
"Action": [
"eks:ListNodegroups",
"eks:DescribeNodegroup",
"autoscaling:DescribeAutoScalingGroups"
],
"Resource": "*"
}
]
}禁用 Instance Profile 选择器
如果 spire-server 运行在没有公网访问的环境中,设置 disable_instance_profile_selectors = true 可阻止 server 向 iam.amazonaws.com 发起请求。这是必要的,因为此时 spire-server 无法获取元数据信息,从而会导致节点认证失败。
启用此项后,IAM Role selector 信息将不再可用。
AWS IAM 权限
由所配置凭据标识的用户或角色,必须具备 ec2:DescribeInstances 权限。
以下是从 AWS 获取实例信息所需的 IAM 策略示例。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"iam:GetInstanceProfile"
],
"Resource": "*"
}
]
}注意: 使用可选的校验特性时,还需要额外的权限:
- 组织校验(
verify_organization):organizations:ListAccounts - EKS 集群校验(
validate_eks_cluster_membership):eks:ListNodegroups、eks:DescribeNodegroup、autoscaling:DescribeAutoScalingGroups
有关安全凭据的更多信息,见 https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html。
支持的选择器(Supported Selectors)
本插件生成以下与 agent 运行所在实例相关的 selector:
| Selector | Example | Description |
|---|---|---|
| Account ID | aws_iid:account_id:123456789012 | 实例所属 AWS 账户的 ID。 |
| Availability Zone | aws_iid:az:us-west-2b | 实例运行所在的可用区(Availability Zone)。 |
| IAM role | aws_iid:iamrole:arn:aws:iam::123456789012:role/Blog | 实例的 instance profile 中的某个 IAM 角色 |
| Image ID | aws_iid:image:id:ami-5fb8c835 | 用于启动该实例的 AMI 的 ID。 |
| Instance ID | aws_iid:instance:id:i-0b22a22eec53b9321 | 实例的 ID。 |
| Instance Tag | aws_iid:tag:name:blog | 实例标签的键(例如 name)与值(例如 blog) |
| Region | aws_iid:region:us-west-2 | 实例运行所在的区域(Region)。 |
| Security Group ID | aws_iid:sg:id:sg-01234567 | 实例所属安全组的 id |
| Security Group Name | aws_iid:sg:name:blog | 实例所属安全组的名称 |
所有 selector 的类型均为 aws_iid。
只有当实例关联了 IAM Instance Profile 且 disable_instance_profile_selectors = false 时,生成的 selector 集合中才会包含 IAM role selector。
Security Considerations(安全考量)
AWS 实例身份文档(Instance Identity Document)是本认证器用于证明节点身份的凭据,默认情况下节点上运行的任何进程都可访问它。因此,节点上的非 agent 代码有可能向 SPIRE Server 完成认证,从而获取该节点被授权运行的任意工作负载身份(workload identity)。
尽管许多运维人员会选择配置系统以阻止对实例身份文档的访问,但 SPIRE 项目无法保证这一安全态势。为缓解相关风险,aws_iid 节点认证器实现了首次使用即信任(Trust On First Use,简称 TOFU)语义。对于任意给定节点,认证只能发生一次,后续的认证尝试都将被拒绝。
非 agent 代码仍有可能先于 SPIRE Agent 完成节点认证;不过这种情况很容易被迅速发现,因为此时 SPIRE Agent 将无法启动,并且 SPIRE Agent 和 SPIRE Server 都会记录该事件。此类情况应作为可能的安全事件加以调查。