我开始使用 AWS IAM 实例角色,这对于提升我们的安全管理非常有用,但它增加了一些维护轻量级开发流程的挑战。
眼前的问题是:
-
我定义了一个 AWS 实例角色,并将安全策略附加到该角色。此策略指定为此角色启动的新 EC2 实例授予的权限,它是一个冗长而复杂的 json 文档,其中包含"允许访问 S3 存储桶 x"和"拒绝访问 SQS y"等规则。这在 EC2 上效果很好。
-
接下来,我想让开发人员在 IDE 中进行本地开发时在其本地设备上运行我们的代码,并使用与前面定义的完全相同的安全策略。当开发人员生成新代码时,这很重要 b/c 我希望他们按照与在生产中运行的完全相同的安全策略对其进行 WRT 测试。如果它们使用不同的安全策略运行,则情况可能会溜走。
-
问题是我还没有找到一种方法来做到这一点。可以定义 IAM 组,并将开发人员加入组(例如"开发人员"组)。在此组中,我可以定义一个适用于该组中的所有开发人员的 IAM 安全策略。但是(我发现)没有办法在实例角色的上下文中重用附加到组的策略。或者在组的上下文中使用附加到角色的策略。(我完全错过了这个吗?...)
-
综上所述,我想要的是:1)定义一次安全策略文档。 2)在两个地方重用此文档,一个在IAM实例角色定义中,另一个是IAM组。
-
无法做到这一点意味着我必须为每种类型的服务(我们有许多这样的服务)和每个环境(例如阶段/生产)维护一个复杂的 JSON 文档(超出版本控制)的两个副本。我可以看到这很容易成为维护噩梦。
到目前为止,我想出的最好的办法可能是将策略文档存储在版本控制下的磁盘上,并编写一个使用 aws API 将策略文档上传到实例角色和组的工具。这有点麻烦,所以我希望能有更多的敏捷性。
你对我有更好的建议吗?...谢谢!
感谢@Steffen指出 CloudFormation,但我想我找到了一个更适合我的解决方案。
AWS 提供安全令牌服务,简而言之,该服务允许您代入角色。
这正是我一直在寻找的,因为我想定义一次角色(例如一组 AWS 权限),然后让 AWS EC2 实例自动承担此角色(容易做到),以及开发人员为他们正在开发的特定服务代入角色。开发人员部分涉及更多,但我将在下面粘贴一些 Java 代码来演示如何执行此操作。
首先,在定义角色时,您必须说明允许哪些委托人承担此角色。为此,您可以编辑角色的信任关系部分(位于 AWS Web 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 在一般意义上也可能很有用,主要是为了保持我的代码库和实际 AWS 部署的一致性,但那是另一回事。
但令人讨厌的一点是:可以将主体定义为实际用户名,但不能定义为用户组,因此您实际上不能说"允许所有开发人员承担角色 x",而是必须具体列出每个开发人员。这很烦人,但我想我不是唯一一个有这种抱怨的人。
更新
AWS刚刚推出了 AWS Identity & Access Management 托管策略,它提供了一种跨 IAM 实体共享和维护 IAM 策略的新方法,专门旨在减少当前信息和工作量的重复:
随着 AWS 安装的规模和复杂性的增长,您可能会发现自己正在编辑多个权限文档,以便添加新权限或删除现有权限。审核和确认权限也比必要的更困难。
安全博客文章管理策略的更简单方法提供了更多详细信息。
- 新功能可以像往常一样通过AWS管理控制台和AWS命令行界面(AWS CLI)使用(但可能还没有通过AWS CloudFormation)。
初步答案
到目前为止,我想出的最好的办法可能是将策略文档存储在版本控制下的磁盘上,并编写一个使用 aws API 将策略文档上传到实例角色和组的工具。这有点麻烦,所以我希望能有更多的敏捷性。
像这样的工具已经存在,实际上是许多AWS自己和第三方服务的主要支持技术 - 看看AWS CloudFormation,它为开发人员和系统管理员提供了一种简单的方法来创建和管理相关AWS资源的集合,以有序和可预测的方式预置和更新它们。
更具体地说,AWS::IAM::P olicy 资源将 IAM 策略与 IAM 用户、角色或组相关联:
{
"Type": "AWS::IAM::Policy",
"Properties": {
"Groups" : [ String, ... ],
"PolicyDocument" : JSON,
"PolicyName" : String,
"Roles" : [ String, ...
"Users" : [ String, ... ],
}
}
当然,CloudFormation 还有更多功能,它是一个非常强大的工具(请参阅 AWS CloudFormation 入门)。