有没有办法跨用户和 EC2 实例角色重用 AWS IAM 权限策略?
Is there a way to reuse AWS IAM permissions policy across users and EC2 instance roles?
我开始使用 AWS IAM instance roles,这对于提升我们的安全管理水平非常有用,但它增加了维护轻量级开发流程的一些挑战。
手头的问题是:
我定义了一个 AWS 实例角色 并将 安全策略 附加到该角色。此策略指定授予在此角色下启动的新 EC2 实例的权限,它是一个冗长而复杂的 json 文档,包含 "allow access to S3 bucket x" 和 "deny access to SQS y" 等规则。这在 EC2 上运行良好。
接下来,我想让开发者运行把我们的代码放在他们本地的盒子上,在IDE本地开发的时候,使用的与之前定义的完全相同的安全策略。当开发人员生成新代码时,这很重要 b/c 我希望他们根据与生产中 运行 完全相同的安全策略对其进行 WRT 测试。如果他们 运行 使用不同的安全策略,那么事情就有可能会出错。
问题是我还没有找到办法做到这一点。可以定义 IAM 组,并将开发人员加入组(例如 "developers" 组)。在这个组中,我可以定义适用于该组中所有开发人员的 IAM 安全策略。但是(我发现)无法在实例角色的上下文中重用附加到组的策略。或者在组的上下文中使用附加到角色的策略。 (我完全错过了吗?...)
所以总结一下,我想要的是:1)定义一个安全策略文档一次。 2)在两个地方重用这个文档,一个是在IAM实例角色定义中,另一个是IAM组。
无法这样做意味着我将不得不为每种类型的服务维护一份复杂的 JSON 文档(不受版本控制)的两份副本(而且我们有很多这样的服务)和每个环境(例如 stage/prod)。我可以很容易地看出这是如何成为维护噩梦的。
到目前为止,我想出的最好的办法可能是将政策文件存储在磁盘上,在版本控制下,并编写一个使用 aws api 的工具将政策文件上传到两者实例角色和组。这有点麻烦,所以我希望能更灵活一点。
你有更好的建议给我吗?...谢谢!
更新
AWS 刚刚推出 Managed Policies for AWS Identity & Access Management,它提供了一种跨 IAM 实体共享和维护 IAM 策略的全新方法,专门用于减少当前的信息和工作重复:
As the size and complexity of your AWS installation grows, you might find yourself editing multiple permission documents in order to add a new permission or to remove an existing one. Auditing and confirming permissions was also more difficult than necessary.
安全博客 post An Easier Way to Manage Your Policies 提供了更多详细信息。
- 新功能可以通过 AWS Management Console and the AWS Command Line Interface (AWS CLI) as usual (but presumably not via AWS CloudFormation 使用。
初始答案
So far the best thing I came up with is perhaps to store the policy documents on disk, under version control, and write a tool that uses the aws api to upload the policy document to the both the instance role and the group. It's somewhat cumbersome so I was hoping for a little more agility.
这样的工具已经存在,实际上是许多 AWS 自己和第三方服务的主要支持技术 - 看看 AWS CloudFormation,它 为开发人员和系统提供管理员可以轻松创建和管理相关 AWS 资源的集合,以有序且可预测的方式配置和更新它们。
更具体地说,AWS::IAM::Policy 资源 将 IAM 策略与 IAM 用户、角色或组相关联:
{
"Type": "AWS::IAM::Policy",
"Properties": {
"Groups" : [ String, ... ],
"PolicyDocument" : JSON,
"PolicyName" : String,
"Roles" : [ String, ...
"Users" : [ String, ... ],
}
}
CloudFormation 当然还有更多功能,它是一个非常强大的工具(参见 Getting Started with AWS CloudFormation)。
感谢@Steffen 指出 CloudFormation,但我想我找到了一个更适合我的解决方案。
AWS 提供 Security Token Service,简而言之,它允许您 担任角色 。
这正是我一直在寻找的,因为我想定义一个角色一次(例如一组 AWS 权限),然后让 AWS EC2 实例自动承担这个角色(很容易做到)以及开发人员承担特定服务的角色他们正在发展。开发人员部分涉及更多,但我将在下面粘贴一些 Java 代码来说明如何执行此操作。
首先,在定义角色时,您必须说明允许哪些 负责人 担任此角色。为此,您可以编辑角色的 Trust Relationships 部分(位于 AWS 网站上角色定义页面的底部 UI)
例如,这里有一个信任关系文档,它允许 EC2 实例以及我域中的一些用户(替换 your-service-id-number
和 your-user@example.com
)承担这个角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::your-service-id-number:user/your-user@example.com",
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
然后 Java 在本地开发中 运行 承担此角色的代码:
此代码检查我是否在 EC2 实例上 运行,如果是,将承担实例的角色(否则,DefaultAWSCredentialsProviderChain
定义的任何内容,但在我的情况下,最佳实践是 - EC2 实例角色)。如果 运行 在开发环境中,例如在 EC2 之外然后它承担由 roleName
提供的角色
AWSCredentialsProvider getCredentialsProvider(String roleName) {
if (isRunningOnEc2()) {
return new DefaultAWSCredentialsProviderChain();
}
// If not running on EC2, then assume the role provided
final AWSCredentials longLivedCredentialsProvider = new DefaultAWSCredentialsProviderChain().getCredentials(); // user credentials provided by env variables for ex.
// The String roleArn is defined at the top of the Role page titled "Role ARN" ;-)
final String roleArn = String.format("arn:aws:iam::your-service-id-number:role/%s", roleName);
final String roleSessionName = "session" + Math.random(); // not sure it's really needed but what the heck..
final STSAssumeRoleSessionCredentialsProvider credentialsProvider =
new STSAssumeRoleSessionCredentialsProvider(longLivedCredentialsProvider, roleArn, roleSessionName);
return credentialsProvider;
}
实用程序 isRunningOnEc2()
已提供:
public static boolean isRunningOnEc2() {
try {
final InetAddress byName = InetAddress.getByName("instance-data");
return byName != null;
} catch (final UnknownHostException e) {
return false;
}
}
按照 Steffen 的建议使用 CloudFormation,在一般意义上也可能有用,主要是为了保持一致性 b/w 我的代码库和实际的 AWS 部署,但那是另外一回事。
但有一个烦人的地方:可以将主体定义为实际用户名而不是用户组,因此您实际上不能这么说 "all developers are allowed to assume role x",而是必须具体列出每个开发人员。这很烦人,但我猜 I'm not the only one with this complaint。
我开始使用 AWS IAM instance roles,这对于提升我们的安全管理水平非常有用,但它增加了维护轻量级开发流程的一些挑战。
手头的问题是:
我定义了一个 AWS 实例角色 并将 安全策略 附加到该角色。此策略指定授予在此角色下启动的新 EC2 实例的权限,它是一个冗长而复杂的 json 文档,包含 "allow access to S3 bucket x" 和 "deny access to SQS y" 等规则。这在 EC2 上运行良好。
接下来,我想让开发者运行把我们的代码放在他们本地的盒子上,在IDE本地开发的时候,使用的与之前定义的完全相同的安全策略。当开发人员生成新代码时,这很重要 b/c 我希望他们根据与生产中 运行 完全相同的安全策略对其进行 WRT 测试。如果他们 运行 使用不同的安全策略,那么事情就有可能会出错。
问题是我还没有找到办法做到这一点。可以定义 IAM 组,并将开发人员加入组(例如 "developers" 组)。在这个组中,我可以定义适用于该组中所有开发人员的 IAM 安全策略。但是(我发现)无法在实例角色的上下文中重用附加到组的策略。或者在组的上下文中使用附加到角色的策略。 (我完全错过了吗?...)
所以总结一下,我想要的是:1)定义一个安全策略文档一次。 2)在两个地方重用这个文档,一个是在IAM实例角色定义中,另一个是IAM组。
无法这样做意味着我将不得不为每种类型的服务维护一份复杂的 JSON 文档(不受版本控制)的两份副本(而且我们有很多这样的服务)和每个环境(例如 stage/prod)。我可以很容易地看出这是如何成为维护噩梦的。
到目前为止,我想出的最好的办法可能是将政策文件存储在磁盘上,在版本控制下,并编写一个使用 aws api 的工具将政策文件上传到两者实例角色和组。这有点麻烦,所以我希望能更灵活一点。
你有更好的建议给我吗?...谢谢!
更新
AWS 刚刚推出 Managed Policies for AWS Identity & Access Management,它提供了一种跨 IAM 实体共享和维护 IAM 策略的全新方法,专门用于减少当前的信息和工作重复:
As the size and complexity of your AWS installation grows, you might find yourself editing multiple permission documents in order to add a new permission or to remove an existing one. Auditing and confirming permissions was also more difficult than necessary.
安全博客 post An Easier Way to Manage Your Policies 提供了更多详细信息。
- 新功能可以通过 AWS Management Console and the AWS Command Line Interface (AWS CLI) as usual (but presumably not via AWS CloudFormation 使用。
初始答案
So far the best thing I came up with is perhaps to store the policy documents on disk, under version control, and write a tool that uses the aws api to upload the policy document to the both the instance role and the group. It's somewhat cumbersome so I was hoping for a little more agility.
这样的工具已经存在,实际上是许多 AWS 自己和第三方服务的主要支持技术 - 看看 AWS CloudFormation,它 为开发人员和系统提供管理员可以轻松创建和管理相关 AWS 资源的集合,以有序且可预测的方式配置和更新它们。
更具体地说,AWS::IAM::Policy 资源 将 IAM 策略与 IAM 用户、角色或组相关联:
{
"Type": "AWS::IAM::Policy",
"Properties": {
"Groups" : [ String, ... ],
"PolicyDocument" : JSON,
"PolicyName" : String,
"Roles" : [ String, ...
"Users" : [ String, ... ],
}
}
CloudFormation 当然还有更多功能,它是一个非常强大的工具(参见 Getting Started with AWS CloudFormation)。
感谢@Steffen 指出 CloudFormation,但我想我找到了一个更适合我的解决方案。
AWS 提供 Security Token Service,简而言之,它允许您 担任角色 。
这正是我一直在寻找的,因为我想定义一个角色一次(例如一组 AWS 权限),然后让 AWS EC2 实例自动承担这个角色(很容易做到)以及开发人员承担特定服务的角色他们正在发展。开发人员部分涉及更多,但我将在下面粘贴一些 Java 代码来说明如何执行此操作。
首先,在定义角色时,您必须说明允许哪些 负责人 担任此角色。为此,您可以编辑角色的 Trust Relationships 部分(位于 AWS 网站上角色定义页面的底部 UI)
例如,这里有一个信任关系文档,它允许 EC2 实例以及我域中的一些用户(替换 your-service-id-number
和 your-user@example.com
)承担这个角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::your-service-id-number:user/your-user@example.com",
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
然后 Java 在本地开发中 运行 承担此角色的代码:
此代码检查我是否在 EC2 实例上 运行,如果是,将承担实例的角色(否则,DefaultAWSCredentialsProviderChain
定义的任何内容,但在我的情况下,最佳实践是 - EC2 实例角色)。如果 运行 在开发环境中,例如在 EC2 之外然后它承担由 roleName
AWSCredentialsProvider getCredentialsProvider(String roleName) {
if (isRunningOnEc2()) {
return new DefaultAWSCredentialsProviderChain();
}
// If not running on EC2, then assume the role provided
final AWSCredentials longLivedCredentialsProvider = new DefaultAWSCredentialsProviderChain().getCredentials(); // user credentials provided by env variables for ex.
// The String roleArn is defined at the top of the Role page titled "Role ARN" ;-)
final String roleArn = String.format("arn:aws:iam::your-service-id-number:role/%s", roleName);
final String roleSessionName = "session" + Math.random(); // not sure it's really needed but what the heck..
final STSAssumeRoleSessionCredentialsProvider credentialsProvider =
new STSAssumeRoleSessionCredentialsProvider(longLivedCredentialsProvider, roleArn, roleSessionName);
return credentialsProvider;
}
实用程序 isRunningOnEc2()
已提供:
public static boolean isRunningOnEc2() {
try {
final InetAddress byName = InetAddress.getByName("instance-data");
return byName != null;
} catch (final UnknownHostException e) {
return false;
}
}
按照 Steffen 的建议使用 CloudFormation,在一般意义上也可能有用,主要是为了保持一致性 b/w 我的代码库和实际的 AWS 部署,但那是另外一回事。
但有一个烦人的地方:可以将主体定义为实际用户名而不是用户组,因此您实际上不能这么说 "all developers are allowed to assume role x",而是必须具体列出每个开发人员。这很烦人,但我猜 I'm not the only one with this complaint。