AWSs
AWS 机密引擎根据 IAM 策略动态生成 AWS 访问凭据。这通常简化了 AWS IAM 的使用,因为它不需要在 Web 界面中点击。此外,该过程可以被编码并映射到内部身份验证方法(例如 LDAP)。基于 AWS IAM 生成凭据具有有效期,会在 Vault 租约到期时自动撤销。
Vault 支持从 AWS 获取三种不同类型的凭据:
iam_user
: Vault 将为每个租约创建一个 IAM 用户,将角色中指定的托管和内联 IAM 策略附加到用户,如果在角色上指定了权限边界,那么这个权限边界也会被附加。然后 Vault 将为 IAM 用户生成 access key 和 secret key,并将它们返回给调用者。 IAM 用户没有会话令牌,所以不会返回会话令牌。 Vault 将在 TTL 到期时删除 IAM 用户。assumed_role
: Vault 会调用 sts:AssumeRole 并返回 access key、secret key 和会话令牌给调用者federation_token
: Vault 会调用 sts:GetFederationToken 传入配置的 AWS 策略文档并将 access key、secret key 和会话令牌返回给调用者。
配置
大部分机密引擎在工作之前必须要先进行配置。这些步骤通常是由系统管理员来完成。
- 启用 AWS 机密引擎:
$ vault secrets enable aws
Success! Enabled the aws secrets engine at: aws/
默认情况下,机密引擎会挂载到名字对应的路径上。要在不同路径上启用机密引擎,请使用 -path
参数。
- 配置 Vault 用来与 AWS 通信生成 IAM 凭据的凭据:
$ vault write aws/config/root \
access_key=AKIAJWVN5Z4FOFT7NLNA \
secret_key=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 \
region=us-east-1
Vault 使用这里配置的凭据连接到 AWS。因此,这些凭据本身拥有的策略必须是要生成的 IAM 凭据所拥有策略的超集。由于 Vault 使用官方 AWS SDK,因此它将使用 SDK 指定使用的凭据,也可以使用标准 AWS 环境变量、共享文件凭据或 IAM 角色/ECS 任务凭据作为凭据。 (请注意,如果想要使用 STS 联合令牌,Vault 就不能使用 IAM 角色凭据,因为与角色关联的临时安全凭据无权使用 GetFederationToken。)
注意:虽然上面配置的 Vault 的路径是 aws/config/root
,也不要使用 AWS 根账户凭据,而是生成专用用户或角色。
- 配置一个映射到 AWS 中的一组权限以及 AWS 凭据类型的 Vault 角色。当用户生成凭据时,该凭据会根据使用的 Vault 角色生成。一个例子:
$ vault write aws/roles/my-role \
credential_type=iam_user \
policy_document=-<<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
}
]
}
EOF
上面的例子会创建一个名为“my-role”的角色。当用户使用这个角色生成凭据时,Vault 将创建一个 IAM 用户并将指定的策略文档附加到 IAM 用户。然后 Vault 将为 IAM 用户创建访问密钥和秘密密钥并返回这些凭据。也可以指定用户内联策略,外加可选的对现有 AWS 策略的完整 ARN 或一组 IAM 组的引用:
$ vault write aws/roles/my-other-role \
policy_arns=arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess,arn:aws:iam::aws:policy/IAMReadOnlyAccess \
iam_groups=group1,group2 \
credential_type=iam_user \
policy_document=-<<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
}
]
}
EOF
可以阅读 AWS IAM 策略文档获取更多有关 IAM 策略的信息。
可用标志
配置完机密引擎后拥有合适权限的 Vault 令牌的用户或者机器就可以用它来生成凭据了。
- 通过读取
/creds
端点加上角色名的路径来生成一个新的凭据:
$ vault read aws/creds/my-role
Key Value
--- -----
lease_id aws/creds/my-role/f3e92392-7d9c-09c8-c921-575d62fe80d8
lease_duration 768h
lease_renewable true
access_key AKIAIOWQXTLW36DV7IEA
secret_key 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
security_token <nil>
每次执行该命令都会生成一个新的凭据。
遗憾的是,与 AWS 其他服务一样,IAM 凭据创建后需要等待 5-10 秒(有时更长)才能正常使用,如果是在自动化流程中使用该命令需要注意这一点。
想要立即可用的凭据,请考虑使用 STS 获取密钥的方法。 STS 令牌支持的 IAM 凭据在生成后立即可用。
- 轮替 Vault 用来与 AWS 通信使用的凭据:
$ vault write -f aws/config/rotate-root
Key Value
--- -----
access_key AKIA3ALIVABCDG5XC8H4
注意:由于 AWS 的最终一致的特点,调用此端点后,从 Vault 到 AWS 的后续调用可能会失败几秒钟,直到 AWS 再次变得一致。
为 Vault 设置 IAM 策略的例子
配置在 aws/config/root
的凭据需要管理动态 IAM 用户的权限。这里有一份 AWS IAM 策略的例子,该策略授予了大多数 Vault 所需要的权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachUserPolicy",
"iam:CreateAccessKey",
"iam:CreateUser",
"iam:DeleteAccessKey",
"iam:DeleteUser",
"iam:DeleteUserPolicy",
"iam:DetachUserPolicy",
"iam:ListAccessKeys",
"iam:ListAttachedUserPolicies",
"iam:ListGroupsForUser",
"iam:ListUserPolicies",
"iam:PutUserPolicy",
"iam:AddUserToGroup",
"iam:RemoveUserFromGroup"
],
"Resource": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/vault-*"]
}
]
}
Vault 也支持在创建 IAM 用户时应用权限边界。如果希望强制 Vault 始终将权限边界附加到 IAM 用户,可以使用如下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:DeleteUser",
"iam:ListAccessKeys",
"iam:ListAttachedUserPolicies",
"iam:ListGroupsForUser",
"iam:ListUserPolicies",
"iam:AddUserToGroup",
"iam:RemoveUserFromGroup"
],
"Resource": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/vault-*"]
},
{
"Effect": "Allow",
"Action": [
"iam:AttachUserPolicy",
"iam:CreateUser",
"iam:DeleteUserPolicy",
"iam:DetachUserPolicy",
"iam:PutUserPolicy"
],
"Resource": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/vault-*"],
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": [
"arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:policy/PolicyName"
]
}
}
}
]
}
这里的“iam:PermissionsBoundary”条件包含希望确保 Vault 使用的权限边界策略列表。此策略将确保 Vault 使用给定的权限边界中的一个(不是全部)。
STS 凭据
上面我们演示了如何使用 iam_user
凭据。如前所述,Vault 也支持 assumed_role
和 federation_token
凭据。
STS 联合(Federation)令牌
注意:由于 AWS 中的限制,为了使用 federation_token
凭据,Vault 必须配置为使用 IAM 用户凭据。 AWS 不允许使用临时凭据(例如那些来自 IAM 实例配置文件的凭据)。
STS 联合令牌继承了一组权限,他们是四组权限的组合(交集):
- 配置在
aws/config/root
的凭据所拥有的权限 - 配置在 Vault 的角色中的内联策略
- 配置在 Vault 的角色的托管策略的 ARN
- 一个 IAM 或是 STS 操作上的隐式的拒绝策略
credential_type
为 federation_token
的角色可以在 Vault 角色中指定一个或多个 policy_document
、policy_arns
和 iam_groups
参数。
配置在 aws/config/root
的凭据需要有 sts:GetFederationToken
的 IAM 权限以及委托给 STS 联合令牌的权限。例如,aws/config/root
凭据上的策略将允许创建具有委托给 ec2:*
的权限(或任意 ec2:*
权限的子集)的 STS 联合令牌:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": [
"ec2:*",
"sts:GetFederationToken"
],
"Resource": "*"
}
}
然后 ec2_admin
角色将分配一个具有相同的 ec2:*
权限的内联策略。
$ vault write aws/roles/ec2_admin \
credential_type=federation_token \
policy_document=@policy.json
这里的 policy.json 文件将包含具有类似权限的内联策略,但没有 sts:GetFederationToken
权限。 (我们可以授予 sts:GetFederationToken
权限,但 STS 附加了一个隐式拒绝,覆盖了我们授予的权限。)
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
}
}
要生成一组新的 STS 联合令牌凭据,我们只需向 aws/sts
路径写入:
$ vault write aws/sts/ec2_admin ttl=60m
Key Value
lease_id aws/sts/ec2_admin/31d771a6-fb39-f46b-fdc5-945109106422
lease_duration 60m0s
lease_renewable false
access_key ASIAJYYYY2AA5K4WIXXX
secret_key HSs0DYYYYYY9W81DXtI0K7X84H+OVZXK5BXXXX
security_token AQoDYXdzEEwasAKwQyZUtZaCjVNDiXXXXXXXXgUgBBVUUbSyujLjsw6jYzboOQ89vUVIehUw/9MreAifXFmfdbjTr3g6zc0me9M+dB95DyhetFItX5QThw0lEsVQWSiIeIotGmg7mjT1//e7CJc4LpxbW707loFX1TYD1ilNnblEsIBKGlRNXZ+QJdguY4VkzXxv2urxIH0Sl14xtqsRPboV7eYruSEZlAuP3FLmqFbmA0AFPCT37cLf/vUHinSbvw49C4c9WQLH7CeFPhDub7/rub/QU/lCjjJ43IqIRo9jYgcEvvdRkQSt70zO8moGCc7pFvmL7XGhISegQpEzudErTE/PdhjlGpAKGR3d5qKrHpPYK/k480wk1Ai/t1dTa/8/3jUYTUeIkaJpNBnupQt7qoaXXXXXXXXXX
STS AssumeRole
assumed_role
凭据通常用于跨账户身份验证或单点登录 (SSO) 场景。为了使用 assumed_role
凭据,必须在 Vault 之外进行配置:
- 一个 IAM 角色
- IAM 内联策略以及可选的附加到 IAM 角色的托管策略
- IAM 信任策略附加到 IAM 角色以授予 Vault 代入角色的权限
与使用 federation_token
凭据相比,使用 assumed_role
凭据有如下的优势:
- 如果角色的 IAM 策略允许的话,
assumed_role
凭据可以调用 IAM 和 STS 操作。 assumed_role
支持跨账户身份验证- 临时凭据(例如在使用了 IAM 实例配置文件的 EC2 实例上运行 Vault 使用的凭据)可以读取
assumed_role
凭据(但不能检索federation_token
凭据)。
配置在 aws/config/root
的凭据必须有一个允许指定角色执行 sts:AssumeRole
的 IAM 策略:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:role/RoleNameToAssume"
}
}
我们必须为要代入的 IAM 角色附加一个信任策略,从而允许配置在 aws/root/config
凭据代入该角色。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/VAULT-AWS-ROOT-CONFIG-USER-NAME"
},
"Action": "sts:AssumeRole"
}
]
}
在设置一个 Vault 角色的 credential_type
为 assumed_role
的时候,可以设置不止一个 IAM 角色 ARN。这样做的话,Vault 客户端可以在从该角色检索凭据时选择他们想要代入的角色 ARN。
此外,我们可以同时设定 policy_document
和 policy_arns
参数;如果这样设定的话,这两个参数同时对要授予代入角色的 IAM 权限进行过滤。如果设置了 iam_groups
,则在调用 sts:AssumeRole
时,每个 IAM 组的内联和附加策略都会被添加到 policy_document
和 policy_arns
参数中。对于要放行的操作,它必须得到要代入的 AWS 角色上的 IAM 策略,以及 Vault 角色上指定的 policy_document
(如果设置了的话)以及 policy_arns
参数指定的托管策略的许可。 (policy_document
参数被作为 Policy
参数传入 sts:AssumeRole
API 调用,而 policy_arns
参数被作为 PolicyArns
参数传入同一调用。)
注意:当设置了多个 role_arns
时,请求凭据的客户端可以指定在 Vault 角色上定义的某个角色 ARN 以获得凭据。但是,当指定了 policy_document
、policy_arns
或 iam_groups
时,这将适用于从 AWS 检索的所有角色凭据。
让我们使用我们要代入的角色的 ARN 来创建一个“deploy”策略:
$ vault write aws/roles/deploy \
role_arns=arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:role/RoleNameToAssume \
credential_type=assumed_role
为了生成一组新的代入角色 STS 凭据,我们再次对 aws/sts
路径进行写操作:
$ vault write aws/sts/deploy ttl=60m
Key Value
lease_id aws/sts/deploy/31d771a6-fb39-f46b-fdc5-945109106422
lease_duration 60m0s
lease_renewable false
access_key ASIAJYYYY2AA5K4WIXXX
secret_key HSs0DYYYYYY9W81DXtI0K7X84H+OVZXK5BXXXX
security_token AQoDYXdzEEwasAKwQyZUtZaCjVNDiXXXXXXXXgUgBBVUUbSyujLjsw6jYzboOQ89vUVIehUw/9MreAifXFmfdbjTr3g6zc0me9M+dB95DyhetFItX5QThw0lEsVQWSiIeIotGmg7mjT1//e7CJc4LpxbW707loFX1TYD1ilNnblEsIBKGlRNXZ+QJdguY4VkzXxv2urxIH0Sl14xtqsRPboV7eYruSEZlAuP3FLmqFbmA0AFPCT37cLf/vUHinSbvw49C4c9WQLH7CeFPhDub7/rub/QU/lCjjJ43IqIRo9jYgcEvvdRkQSt70zO8moGCc7pFvmL7XGhISegQpEzudErTE/PdhjlGpAKGR3d5qKrHpPYK/k480wk1Ai/t1dTa/8/3jUYTUeIkaJpNBnupQt7qoaXXXXXXXXXX
故障排查
动态 IAM 用户错误
如果看到类似于以下任一内容的错误消息,则写入 aws/config/root
的根凭据权限不足:
$ vault read aws/creds/deploy
* Error creating IAM user: User: arn:aws:iam::000000000000:user/hashicorp is not authorized to perform: iam:CreateUser on resource: arn:aws:iam::000000000000:user/vault-root-1432735386-4059
$ vault revoke aws/creds/deploy/774cfb27-c22d-6e78-0077-254879d1af3c
Revoke error: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/sys/revoke/aws/creds/deploy/774cfb27-c22d-6e78-0077-254879d1af3c
Code: 400. Errors:
* invalid request
任何时候如果遇到问题,都可以运行 vault path-help aws
或是使用子路径来获取交互式帮助信息。
STS 联合令牌错误
Vault 使用配置在 aws/config
的 IAM 凭据生成 STS 令牌。
这些凭据必须具有两个属性:
- 他们必须有权限调用
sts:GetFederationToken
- 他们所拥有的权限必须至少与要附加到待生成的 STS 凭据的权限相等
如果上述任一一个条件得不到满足,就会返回 "403 not-authorized"。
查阅 http://docs.aws.amazon.com/STS/latest/APIReference/API_GetFederationToken.html 获取更多信息。
使用 STS 令牌时,建议使用 Vault 0.5.1 或更高版本,以避免超过 AWS 对 STS 令牌名称的 32 个字符的限制而导致验证错误。
AWS 读取实例元数据超时
影响 Vault 1.4 及以后的版本
Vault 在 EC2 实例上使用实例元数据服务的时候,例如从实例配置文件中获取凭据,使用到实例元数据服务 (IMDSv2) 的 v2 版本时可能会出现延迟。 Vault 使用的 AWS SDK 首先尝试连接到 IMDSv2,如果超时,则回退到 v1。在 Vault 1.4 中,此超时最多可能需要 2 分钟。在 Vault 1.5.5 及更高版本中最多可能需要 2 秒钟。
超时会发生在 Vault 和 IMDSv2 之间存在代理,并且实例 hop 限制设置为小于 Vault 和 IMDSv2 之间的“hop”数的时候。例如,如果 Vault 在 EC2 实例上的 docker 中运行,并且实例 hop 限制设置为 1,AWS SDK 客户端将尝试连接到 IMDSv2,超时并回退到 IMDSv1,因为 docker 和 IMDS 之间存在额外的网络 hop.
为避免超时行为,可以在底层 EC2 实例上调整 hop 限制。对于 docker 示例,将 hop 限制设置为 2 就可以让 Vault 中的 AWS SDK 无延迟地连接到 IMDSv2。