AWS IAM
首先要知道, AWS 提供了许许多多种类的服务或者说资源供我们使用, 这些资源挂在我们的 AWS 账户下, 这个账户就是我们第一次用 AWS 时用邮箱和密码申请的, 以后我们所有的资源申请, 账单费用都会挂到这个户头.
那么 IAM 算什么呢? IAM 不是 AWS 的专有名词, 它是一个通用概念, 全称是 Identity and Access Management, 其要解决的两个问题就是身份认证 (Authtication) 和授权 (Authorization). 为此 AWS IAM 设计了用户, 角色, 用户组, 权限策略等概念和机制
IAM (Identity Access Management) 由这些东西组成:
- Users
- Groups 用户组
- Roles 角色可以分配给AWS服务,让AWS服务有访问其他AWS资源的权限。 举个例子,我们可以赋予EC2实例一个角色,让其有访问S3的读写权限(后面课程会有关于这一点的实操)
- Policy Documents 策略。 策略具体定义了能访问哪些AWS资源,并且能执行哪些操作(比如List, Read, Write等) 策略的文档以JSON的格式展现
// An example policy: allowing any access to any resource
{
"Version": "2012-10-17"
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
IAM 是 Global的,不属于任何一个 region
IAM Entities
首先 IAM 为了能够同时照顾到 “人” 和 “非人“ 这两类资源访问者, 使用了一个概念叫做 Entity(实体), 目前 IAM 里有两种 Entity: IAM User 和 IAM Role. 一般来说公司可以为每个程序员创建一个 IAM User 的实体, 让他们能够访问 AWS Console做一些权限之内的事情; 而对于非人的程序, 一般的实践则是创建 IAM Role, 然后令这程序 “假装”(Assume) 这个角色, 这样它就有了这个角色的权限, 一个 IAM Role 可以让很多程序一起假装, 不过要想假装 Role 的话, 必须得是 AWS 里的资源才行, 这是当然的, 像上面第三个例子, 公网的设备想访问我们的存储资源, 首先要通过 API Gateway, 由 API Gateway 来完成这个假装动作.
Users
在 AWS 里,一个 IAM user 和 unix 下的一个用户几乎等价。你可以创建任意数量的用户,为其分配登录 AWS management console 所需要的密码,以及使用 AWS CLI(或其他使用 AWS SDK 的应用)所需要的密钥。你可以赋予用户管理员的权限,使其能够任意操作 AWS 的所有服务,也可以依照 Principle of least privilege,只授权合适的权限。下面是使用 AWS CLI 创建一个用户的示例:
saws> aws iam create-user --user-name tyrchen
{
"User": {
"CreateDate": "2015-11-03T23:05:05.353Z",
"Arn": "arn:aws:iam::<ACCOUNT-ID>:user/tyrchen",
"UserName": "tyrchen",
"UserId": "AIDAISBVIGXYRRQLDDC3A",
"Path": "/"
}
}
当然,这样创建的用户是没有任何权限的,甚至无法登录,你可以用下面的命令进一步为用户关联群组,设置密码和密钥:
saws> aws iam add-user-to-group --user-name --group-name
saws> aws iam create-login-profile --user-name --password
saws> aws iam create-access-key --user-name
IAM User 创建了之后, 就可以将这个实体给到某个员工让他使用, 第一次给员工时可能是将用户名和初始密码告知他, 员工登陆后可以自行修改密码. 这里用户名 + 密码就是这个 IAM User 的认证信息 (Credentials), 不过 Credentials 可不光是只有用户名 + 密码这一种形式, 还可以是 Access Key ID + Secret Acces Key 的形式, 更进一步的, 还可以是 MFA 的形式. 用户名 + 密码一般用于员工认为登陆 AWS Console 界面, Access Key 则一般用于 AWS CLI, 用户脚本这种程序访问方式. 用户或者程序通过提供 Credentials 来向 AWS IAM 证明自己, 获得合法身份 (Identity), IAM 根据这个身份来做进一步的权限审查.
Groups
群组(groups)也等同于常见的 unix group。将一个用户添加到一个群组里,可以自动获得这个群组所具有的权限。在一家小的创业公司里,其 AWS 账号下可能会建立这些群组:
- Admins:拥有全部资源的访问权限
- Devs:拥有大部分资源的访问权限,但可能不具备一些关键性的权限,如创建用户
- Ops:拥有部署的权限
- Stakeholders:拥有只读权限,一般给 manager 查看信息之用
还需要为其添加 policy:
saws> aws iam attach-group-policy --group-name --policy-arn
在前面的例子和这个例子里,我们都看到了 ARN 这个关键字。ARN 是 Amazon Resource Names 的缩写,在 AWS 里,创建的任何资源有其全局唯一的 ARN。ARN 是一个很重要的概念,它是访问控制可以到达的最小粒度。在使用 AWS SDK 时,我们也需要 ARN 来操作对应的资源。
群组中授权增加、删除或者修改时,这些变更都会适用于所有用户。有些时候最好不要将授权直接分配给用户。
Roles
角色(roles)类似于用户,但没有任何访问凭证(密码或者密钥),它一般被赋予某个资源(包括用户)
role都是短期凭证。
对于非人的程序, 一般的实践则是创建 IAM Role, 然后令这程序 “假装”(Assume) 这个角色, 这样它就有了这个角色的权限, 一个 IAM Role 可以让很多程序一起假装, 不过要想假装 Role 的话, 必须得是 AWS 里的资源才行
Credentials 就是认证信息,比如用户名+密码 或者AccessID + Secret Access Key等。
在 Credentials 这一点上, IAM Role 和 IAM User 不同, 因为 IAM Role 没有 Credentials, 或者准确地说是没有固定的 Credentials, 实际上当假装一个角色来获得对某资源的访问权时, 临时的 Credentials 会被生成, 但这是 AWS IAM 底层的实现机理, 从用户这一面上从来不需要操心配置角色的 Credentials, 所以我们就可以按照角色没有 Credentials 来理解. 至于为什么角色没有 Credentials, 那是因为角色只能由 AWS 自身的其他资源所假装, 比如由 EC2, Lambda 来假装, 而当你已经取得了这些资源的操作权限时, 你实际上已经通过 IAM User 的用户名密码或者 Access Key 证明了自己的身份, 所以再假装某个角色的时候, 就不需要再证明身份了.
虽然说我们部署在 EC2 里的程序, 一般是通过假装角色来获得对某资源的访问权限, 但是 AWS IAM 并不关心你创建的 IAM User 是给人用还是给程序用, 我们给程序创建一个 IAM User, 然后将其 Access Key 嵌到程序代码中令其获得对资源的访问权限也是可以的. 我们可以根据自己的场景灵活决定.
场景
- 自己公司的员工想访问 AWS Console 查看所在项目组的基础设施
- AWS User. 可以通过Group管理。
- AWS 账户里的 EC2/Lambda 实例想访问同账户下的一台 RDS
- 给EC2添加Role。User也行,但要AK,SK啥的不方便
- 公网里用户的手机想要访问我们的后端存储(借助 API Gateway)
- 借助API Gateway, 给它加Role
AWS IAM 并不关心你创建的 IAM User 是给人用还是给程序用。
另外 角色也可以给User, 但基本都是使用角色进行跨账户访问。 系统管理员可以创建角色,在一个账户中授权给用户,可以在另一个账户中访问资源。
那权限挂在User上还是角色上?可以看下面这个例子。角色不该轻易给User。
一个用户可能在应用中将数据存储到AWS S3 bucket中。为了保护应用数据的完整性,用户并没有被给予授权来直接对bucket进行编写。在这样的例子中,在运行应用的AWS EC2实例中使用角色将有助于分配授权。
一个lambda or 一个ecs只能有一个执行角色。可以lambda里的configration里看到。除了这个执行角色添加policy,也可以assume成其它role,但一次只能assume成一个。可以通过API手动切换。
Root User
Root 账号是你第一次配置账号的时候创建的,它拥有完全的 Admin aceess
新 User 刚创建时是没有权限的。
AWS 官方建议 root 用户的唯一用途, 就是用来创建你的第一个 IAM 用户, 把这第一个 IAM 用户设置为管理员, 然后以后的工作都用这个管理员用户来进行.
策略 policy document
AWS 下的权限都通过 policy document 描述
IAM 策略可以直接附加到用户、组或角色上。
policy 是用 JSON 来描述的,主要包含 Statement,也就是这个 policy 拥有的权限的陈述,一言以蔽之,即:谁在什么条件下能对哪些资源的哪些操作进行处理。也就是所谓的撰写 policy 的PARCE原则:
- Principal:谁 主体指代一个用户、角色或 AWS 服务,这些主体可以请求访问 AWS 资源。
- Action:哪些操作
- Resource:哪些资源
- Condition:什么条件
- Effect:怎么处理(Allow/Deny)
一个 IAM policy 包含一个或多个 JSON 对象,每个对象都包含一个 policy 的名称和一个 policy 的定义。这个定义通常包含了一个或多个 Statement 对象,每个 Statement 定义了一组操作、资源和条件,以及授予或拒绝这些操作的效果。看起来,其实就是一个策略是多个json文件,每个json文件就下面有一个Version这样的json。
下面讲讲 policy 的执行规则,它也是几乎所有访问控制方案的通用规则:
- 默认情况下,一切资源的一切行为的访问都是 Deny
- 如果在 policy 里显式 Deny,则最终的结果是 Deny
- 否则,如果在 policy 里是 Allow,则最终结果是 Allow
- 否则,最终结果是 Deny
我们看一个允许对 S3 进行只读操作的 policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "*"
}
]
}
其中,Effect 是 Allow,允许 policy 中所有列出的权限,Resource 是*,代表任意 S3 的资源,Action 有两个:s3:Get*和s3:List*,允许列出 S3 下的资源目录,及获取某个具体的 S3 Object。
在这个 policy 里,Principal 和 Condition 都没有出现。如果对资源的访问没有任何附加条件,是不需要 Condition 的;而这条 policy 的使用者是用户相关的 principal(users, groups, roles),当其被添加到某个用户身上时,自然获得了 principal 的属性,所以这里不必指明,也不能指明。
policy支持variable. 允许用户在 policy 里使用 AWS 预置的一些变量,比如${aws:username}。 可以实现用户只能访问S3自己文件夹这样的能力。
一个角色可以attach多个policy。
信任策略
A want to assume as B. 信任策略加在B上。
在AWS中,当实体A需要访问某些资源,但没有直接访问这些资源的权限时,可以通过Assume Role操作来获取一个临时凭证,该凭证赋予实体A访问资源的权限。在这种情况下,实体A必须信任另一个实体B,以便它可以Assume Role操作,并且只有在实体B的策略允许时,才能访问资源。
信任关系决定了谁可以assume成它。
总之,IAM的信任关系是AWS中的一种授权机制,用于允许一个实体代表另一个实体访问资源,并确保只有授权的实体可以访问这些资源。
AssumeRole policy配置
A want to assume as B. assume policy加在A上。
所以实际上,A和B都需要加,一个是policy,一个是信任策略的policy. refer: https://nelson.cloud/aws-iam-allowing-a-role-to-assume-another-role/
AssumeRole 权限是一种 IAM 权限,用于授予 IAM 实体(如 IAM 用户或角色)调用 AssumeRole API 的权限。通过调用 AssumeRole API,实体可以获取其他 IAM 角色的权限并扮演该角色,从而访问该角色可访问的 AWS 资源。
使用场景
- 跨账户访问资源:AssumeRole 可以用于授予一个 AWS 账户中的 IAM 实体(如 IAM 用户或角色)访问另一个 AWS 账户中的资源的权限。
- 使用跨服务角色:如果您在一个服务中运行了一个应用程序,该应用程序需要访问另一个 AWS 服务中的资源,但是您不想直接授予该应用程序访问该服务的权限,可以使用 AssumeRole 为应用程序创建一个跨服务角色。该角色可以通过 AssumeRole API 访问该服务,并且您可以在角色策略中限制访问该服务的权限。
同账号
- B增加trust relationship即可
不同账号
- B增加trust relationship
- A增加policy。
一次至多只能assume成一个角色,只能调用api来assume。
Best Practices
每年的 AWS re:invent 大会,都会有一个 session:Top 10 AWS IAM Best Practices,感兴趣的读者可以去 YouTube 搜索。 2015 年的 top 10(top 11)如下:
- users: create individual users
- permissions: Grant least priviledge
- groups: manage permissions with groups
- conditions: restrict priviledged access further with conditions
- auditing: enable cloudTrail to get logs of API calls
- password: configure a strong password policy
- rotate: rotate security credentials regularly.
- MFA: enable MFA (Multi-Factor Authentication) for priviledged users
- sharing: use IAM roles to share access
- roles: use IAM roles for EC2 instances
- root: reduce or remove use of root
这 11 条 best practices 很清晰,我就不详细解释了。
按照上面的原则,如果一个用户只需要访问 AWS management console,那么不要为其创建密钥;反之,如果一个用户只使用 AWS CLI,则不要为其创建密码。一切不必要的,都是多余的——这就是安全之道。
一个由来已久的信息安全原则就是用户应该且只能拥有他们执行的职责的授权。这也就是最小授权原则,旨在最小化可信用户对于信息系统产生的不利影响。
在授权给群组时,也应该使用最小授权。只授权给有需要的群组的成员。如果一些群组成员需要额外的授权,然后创建额外的群组,并为他们分配额外的授权。需要额外授权的用户可以分配到这两个群组中。IAM群组和角色可以让系统管理员按需为用户和应用授权。
总结
定义群组管理类似的用户。用户都是需要密码等认证的。
用户上没有policy,都通过群组管理
定义角色保护应用,比如只想某EC2访问,就给EC2加角色,而不是加User上。
角色比User的一个好处就是不需要认证信息,因为本身就是AWS自带认证信息。所以给非人的资源一般都是角色。当然EC2也可以是User,访问时需要AK,SK啥的,不如角色方便。
角色分给User目的就是使用角色进行跨账户访问。
User的credential 两种: 用户名+密码, ak+sk。角色不需要这类东西,自己天然就带了,像psm一样。
IAM策略可以分配给AWS账号、IAM用户、IAM组、IAM角色等AWS资源。
cdk里ecs要发sns,需要给ecs授权。cdk里可以把sns topic传入ecs,然后把ecs service那个role(只有1个),grant相应权限即可。一个EC2只能有一个执行角色。
让另一个aws账号的sqs订阅当前账号的sns加权限时,可以直接给另一个aws account加权限。sns有access policy
账号A的ddb暴露给账号b的服务c,可以账号A里创建一个角色,然后创建一个Policy, grant c the role.即principle是c。
一个lambda只能有一个执行角色,不能同时有多个。但可以通过assumeAPI手动切换,意味着每次都切换因此不合理。所以直接操作执行角色授予权限就行,可以IAM里配置执行角色assume成其他。
一个 IAM 角色可以通过 AssumeRole API 来同时 assume 多个角色,从而获取这些角色的权限。这种做法称为角色链 (Role chaining)。直接看上面AssumeRole部分。
SQS access policy如果只有一个Id,那就是defaultPolicy。Amazon SQS 默认的访问策略(access policy)不包含任何明确的权限规则,它允许任何 AWS 账户中的任何用户对队列进行读写操作。但注意,lambda执行角色还需要添加消费的权限,例如,为 Lambda 函数执行角色添加
AmazonSQSFullAccess策略。相当于权限都是两方的,两个都需要愿意才行。
许多 AWS 服务都支持单独的执行角色,这些角色允许服务执行操作而不需要使用您的 AWS 凭证。以下是一些支持单独执行角色的常见 AWS 服务:
- Amazon EC2:实例角色
- AWS Lambda:执行角色
- Amazon ECS:任务角色
- Amazon EKS:服务角色
- Amazon S3:存储桶策略
- Amazon SQS:队列策略
- Amazon SNS:主题策略
- Amazon Kinesis Data Streams:流策略
- Amazon RDS:实例角色
- Amazon Redshift:集群 IAM 角色
这些执行角色通常是与 AWS Identity and Access Management (IAM) 配合使用的,它们允许您授予 AWS 服务和资源执行所需操作的最小权限,从而提高安全性和可管理性。此外,许多服务还提供了自定义权限策略,以便您更精细地控制执行角色的权限。