11

一文读懂 AWS IAM

 3 years ago
source link: http://www.thinkingincrowd.me/2020/02/16/aws-iam/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Concept

IAM 是 AWS 云平台中负责身份认证,和权限控制的服务。AWS 云虽然分了很多个区(Region),但 IAM 是 Global,全局的。
所以,它的数据和配置的更改,也是 Eventually Consistent 的。

Best Practices

在讲 IAM 的权限控制是怎么工作之前,先强调两个最重要的安全理念。

Grant Least Privilege

在 AWS 里面,每一个用户默认都是没有任何权限的。他甚至不能查看自己的密码或 access key,丢失了也只能重新生成。

Lock Away Your AWS Account Root User

AWS 账户开通的时候,你的登录邮箱和密码,就成为了这个账户下的超级管理员,它默认是什么都可以干的。
所以,和在 Linux 下不要滥用 root 一样,不要用这个超级帐号做日常操作,而是创建一个有 Full Administrator 权限的用户。

How It Works?

权限控制有两个基本概念:

  1. Authentication - 确认是否为有效用户,是否允许登录/接入
  2. Authorization - 确认用户当前请求的操作(读写资源),是否合法

所以,IAM 最重要就是管理 Identity,和控制 Resource 的操作。

Identity/Principal

从资源访问的角度来看,使用 AWS 资源的其实不单单是具体的人,还可能是 Application。所以,AWS 里面的身份,分几种:

  • Application
  • Federated User

能在 AWS IAM 控制台里创建的,只有 User 和 Role。而 User 在创建的时候,可以指定它的访问类型。是凭借用户名密码在 Console 登录,还是使用 Access Key ID 及 Secret 通过 API 来访问,还是两者皆可。

要特别注意的是,User 是直接操作 AWS 资源的用户,而不是你自己开发并部署在 AWS 的系统里面的用户。IAM 的 User 是有数量限制的,最多 5000 个。

如果你开发的系统需要操作 AWS 资源,比如说上传文件到 S3,那你需要用的是 Federated User。通过 OpenID Connect(如 Google/Facebook)或者 SAML 2.0(如 Microsoft AD),你的系统用户可以在登录后换取代表某个 AWS Role 的临时 token 来访问 AWS 资源。

Authentication

访问和使用 AWS 资源有两种方式,一种是通过页面登录,也就是 Console。一种是通过 AWS API,也就是接口,包括 CLI, SDK 或 HTTPS 请求。

IAM User 在 Console 页面登录需要提供 AWS 帐号名,IAM User 名和密码。AWS 帐号名是 AWS 云服务开通时,系统生成的一串数字,或者是你赋予的别名。它其实就是一个多租户系统里面的租户帐号。
AWS 还会为每个帐号提供一个独特的登录链接,比如我的测试帐号: https://kcawsfree.signin.aws.amazon.com/consolekcawsfree 就是我帐号的别名。

而如果是使用 API 访问 AWS,我们是需要用 IAM User 的 Access Key ID 及 Secret 来为这个 HTTP 请求生成签名的。为请求签名,是大多数的 API 集成的一种安全性考量。微信,支付宝等平台都这么做。为什么呢?

  1. 确认请求发起方是合法的,就是确保你就是你。
  2. 保护数据传输过程的安全,就是确保数据没被篡改。
  3. 防止重放攻击,就是确保一个请求不被多次使用,滥用或者冒用。

签名需要根据什么信息生成呢?可以说是包含了请求唯一性的所有信息:

请求的接口版本号
请求的操作是什么(Action)
请求的日期
所有请求的参数等

AWS 的请求样例:

1
2
3
4
5
https://iam.amazonaws.com/?Action=AddUserToGroup
&GroupName=Managers
&UserName=Bob
&Version=2010-05-08
&AUTHPARAMS

其实,如果你是使用 AWS SDK 或者 CLI,它会根据你配置的 Access Key 自动签名。只有当你自己发起一个 HTTP 请求的时候,才需要自己实现签名的逻辑。

Authorization

所谓是否有足够的权限,就是验证以下三者在一个请求的场景下,是否被允许:

  1. 主体(Identity)
  2. 操作(Action)
  3. 资源(Resource)

AWS 是通过策略(Policy)来定义权限(Permissions)的。最基本的策略有两大类。一种是 Identity-based policy,另一种是 Resource-based policy。前一种挂在 User/Role/Group 上面,用以定义这些被挂载的主体,能对什么资源进行怎样的操作。而后一种直接挂载在 AWS 资源上面,用以定义哪些主体可以对这个资源做什么样的操作。

AWS Policy 的 Permissions 定义,在内部是通过一个 JSON 格式来表示的。我们来看一个样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListAndDescribe",
"Effect": "Allow",
"Action": [
"dynamodb:List*",
"dynamodb:Describe*"
],
"Resource": "*"
},
{
"Sid": "SpecificTable",
"Effect": "Allow",
"Action": [
"dynamodb:BatchGet*",
"dynamodb:Get*",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchWrite*",
"dynamodb:Delete*",
"dynamodb:Update*",
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/MyTable"
},
{
"Sid": "AllowAllActionsForEC2",
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
},
{
"Sid": "DenyStopAndTerminateWhenMFAIsNotPresent",
"Effect": "Deny",
"Action": [
"ec2:StopInstances",
"ec2:TerminateInstances"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": false
}
}
}
]
}

这个策略控制了 DynamoDB 和 EC2 的访问权限。它看起来很复杂,但其实结构很清晰。这里面最主要的元素就是 Effect, Action, 和 Resource。它们确定了什么资源上的哪些操作,是被允许,还是禁止的。它们是 AND 的逻辑组合。

Statement 里前两个 Permission,允许用户获取 DynamoDB 里面的资源信息,但是只有 MyTable 这个表能做写操作。而后两部分允许用户对 EC2 做任何操作,但是停止和结束 Instance 则必须通过了 MFA 登录认证后才可以。

Policy Evaluation Logic

一个用户或者角色主体上,可以拥有多个不同的 Policy。所以,Policy 的权限验证逻辑,可谓相当复杂。
在讲验证流程前,我再重复一次 AWS 权限的设计原则,这对流程的理解很重要。

  • 如果有显式的 Deny,就禁止
  • Grant Least Privilege 原则。如果没有显式赋予权限,也就是没有任何 Policy 为请求的资源和操作定义了 Allow 权限,那这个主体就没有权限(Implicit Deny)。

AWS 对收到的操作请求,会根据以下的流程来判断这个请求的主体是否有操作权限:

  1. Deny evaluation
  2. AWS Organizations service control policies (SCP)
  3. Resource-based policies
  4. IAM permissions boundaries
  5. Session policies
  6. Identity-based policies

第一步,首先把 2 至 6 里面的所有 policy 的显式 Deny 拿出来。如果当前的请求属于 Deny 的范围,直接禁止操作。这个就是第一个原则。

第二步到第六步,是具体的 policy。如果该主体有这个类型的 policy 存在,就按照第二个原则处理。如果没有,跳到下一个 policy 类别的检查。

那么多种的 Policy 类别,为什么是这个排列顺序呢?我是这么理解的:

  1. Organization SCP 作为组织级别策略,优先级最高。
  2. Resource-based policy 可以跨帐号赋予权限,级别比后面的高一些。
  3. Permission Boundary 的作用是提前为用户定义一个最大的权限范围,避免意外打开了权限的情况,所以比后面的级别要高。
  4. Session policies 是会话级别,允许临时赋予权限,所以比 Identity-based policies 高。
  5. Identity-based policies 是最稳定的,所以检查放在最后。

不过,这里有一个特例,就是 Resource-based policy。如果它是 Implicit Deny 的情况,还是会继续后面的检查,不会阻止。
还有一个复杂的情况是关于 Session policy 的,这个就不在本文解释了,具体可看文档

其实,即便逻辑复杂,判断是否有权限还是可以简单地总结为一句话:

只有具备显式的 Allow,并且没有显式的 Deny,才有权限。

如果没有显式的 Allow,或者有显式的 Deny,就没有权限。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK