Concept
IAM是AWS云平臺(tái)中負(fù)責(zé)身份認(rèn)證,和權(quán)限控制的服務(wù)。AWS云雖然分了很多個(gè)區(qū)(Region),但I(xiàn)AM是Global,全局的。所以,它的數(shù)據(jù)和配置的更改,也是Eventually Consistent的。
Best Practices
在講IAM的權(quán)限控制是怎么工作之前,先強(qiáng)調(diào)兩個(gè)最重要的安全理念。
Grant Least Privilege
在AWS里面,每一個(gè)用戶默認(rèn)都是沒(méi)有任何權(quán)限的。他甚至不能查看自己的密碼或access key,丟失了也只能重新生成。
Lock Away Your AWS Account Root User
AWS賬戶開(kāi)通的時(shí)候,你的登錄郵箱和密碼,就成為了這個(gè)賬戶下的超級(jí)管理員,它默認(rèn)是什么都可以干的。所以,和在Linux下不要濫用root一樣,不要用這個(gè)超級(jí)帳號(hào)做日常操作,而是創(chuàng)建一個(gè)有Full Administrator權(quán)限的用戶。
How It Works?
權(quán)限控制有兩個(gè)基本概念:
1.Authentication-確認(rèn)是否為有效用戶,是否允許登錄/接入
2.Authorization-確認(rèn)用戶當(dāng)前請(qǐng)求的操作(讀寫(xiě)資源),是否合法
所以,IAM最重要就是管理Identity,和控制Resource的操作。
Identity/Principal
從資源訪問(wèn)的角度來(lái)看,使用AWS資源的其實(shí)不單單是具體的人,還可能是Application。所以,AWS里面的身份,分幾種:
·User
·Application
·Federated User
·Role
能在AWS IAM控制臺(tái)里創(chuàng)建的,只有User和Role。而User在創(chuàng)建的時(shí)候,可以指定它的訪問(wèn)類(lèi)型。是憑借用戶名密碼在Console登錄,還是使用Access Key ID及Secret通過(guò)API來(lái)訪問(wèn),還是兩者皆可。
要特別注意的是,User是直接操作AWS資源的用戶,而不是你自己開(kāi)發(fā)并部署在AWS的系統(tǒng)里面的用戶。IAM的User是有數(shù)量限制的,最多5000個(gè)。
如果你開(kāi)發(fā)的系統(tǒng)需要操作AWS資源,比如說(shuō)上傳文件到S3,那你需要用的是Federated User。通過(guò)OpenID Connect(如Google/Facebook)或者SAML 2.0(如Microsoft AD),你的系統(tǒng)用戶可以在登錄后換取代表某個(gè)AWS Role的臨時(shí)token來(lái)訪問(wèn)AWS資源。
Authentication
訪問(wèn)和使用AWS資源有兩種方式,一種是通過(guò)頁(yè)面登錄,也就是Console。一種是通過(guò)AWS API,也就是接口,包括CLI,SDK或HTTPS請(qǐng)求。
IAM User在Console頁(yè)面登錄需要提供AWS帳號(hào)名,IAM User名和密碼。AWS帳號(hào)名是AWS云服務(wù)開(kāi)通時(shí),系統(tǒng)生成的一串?dāng)?shù)字,或者是你賦予的別名。它其實(shí)就是一個(gè)多租戶系統(tǒng)里面的租戶帳號(hào)。AWS還會(huì)為每個(gè)帳號(hào)提供一個(gè)獨(dú)特的登錄鏈接,比如我的測(cè)試帳號(hào):https://kcawsfree.signin.aws.amazon.com/console。kcawsfree就是我?guī)ぬ?hào)的別名。
而如果是使用API訪問(wèn)AWS,我們是需要用IAM User的Access Key ID及Secret來(lái)為這個(gè)HTTP請(qǐng)求生成簽名的。為請(qǐng)求簽名,是大多數(shù)的API集成的一種安全性考量。微信,支付寶等平臺(tái)都這么做。為什么呢?
1.確認(rèn)請(qǐng)求發(fā)起方是合法的,就是確保你就是你。
2.保護(hù)數(shù)據(jù)傳輸過(guò)程的安全,就是確保數(shù)據(jù)沒(méi)被篡改。
3.防止重放攻擊,就是確保一個(gè)請(qǐng)求不被多次使用,濫用或者冒用。
簽名需要根據(jù)什么信息生成呢?可以說(shuō)是包含了請(qǐng)求唯一性的所有信息:
請(qǐng)求的接口版本號(hào)請(qǐng)求的操作是什么(Action)請(qǐng)求的日期所有請(qǐng)求的參數(shù)等
AWS的請(qǐng)求樣例:
https://iam.amazonaws.com/?Action=AddUserToGroup
&GroupName=Managers
&UserName=Bob
&Version=2010-05-08
&AUTHPARAMS
其實(shí),如果你是使用AWS SDK或者CLI,它會(huì)根據(jù)你配置的Access Key自動(dòng)簽名。只有當(dāng)你自己發(fā)起一個(gè)HTTP請(qǐng)求的時(shí)候,才需要自己實(shí)現(xiàn)簽名的邏輯。
Authorization
所謂是否有足夠的權(quán)限,就是驗(yàn)證以下三者在一個(gè)請(qǐng)求的場(chǎng)景下,是否被允許:
1.主體(Identity)
2.操作(Action)
3.資源(Resource)
AWS是通過(guò)策略(Policy)來(lái)定義權(quán)限(Permissions)的。最基本的策略有兩大類(lèi)。一種是Identity-based policy,另一種是Resource-based policy。前一種掛在User/Role/Group上面,用以定義這些被掛載的主體,能對(duì)什么資源進(jìn)行怎樣的操作。而后一種直接掛載在AWS資源上面,用以定義哪些主體可以對(duì)這個(gè)資源做什么樣的操作。
AWS Policy的Permissions定義,在內(nèi)部是通過(guò)一個(gè)JSON格式來(lái)表示的。我們來(lái)看一個(gè)樣例:
{
"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
}
}
}
]
}
這個(gè)策略控制了DynamoDB和EC2的訪問(wèn)權(quán)限。它看起來(lái)很復(fù)雜,但其實(shí)結(jié)構(gòu)很清晰。這里面最主要的元素就是Effect,Action和Resource。它們確定了什么資源上的哪些操作,是被允許,還是禁止的。它們是AND的邏輯組合。
Statement里前兩個(gè)Permission,允許用戶獲取DynamoDB里面的資源信息,但是只有MyTable這個(gè)表能做寫(xiě)操作。而后兩部分允許用戶對(duì)EC2做任何操作,但是停止和結(jié)束Instance則必須通過(guò)了MFA登錄認(rèn)證后才可以。
Policy Evaluation Logic
一個(gè)用戶或者角色主體上,可以擁有多個(gè)不同的Policy。所以,Policy的權(quán)限驗(yàn)證邏輯,可謂相當(dāng)復(fù)雜。在講驗(yàn)證流程前,我再重復(fù)一次AWS權(quán)限的設(shè)計(jì)原則,這對(duì)流程的理解很重要。
·如果有顯式的Deny,就禁止。
·Grant Least Privilege原則。如果沒(méi)有顯式賦予權(quán)限,也就是沒(méi)有任何Policy為請(qǐng)求的資源和操作定義了Allow權(quán)限,那這個(gè)主體就沒(méi)有權(quán)限(Implicit Deny)。
AWS對(duì)收到的操作請(qǐng)求,會(huì)根據(jù)以下的流程來(lái)判斷這個(gè)請(qǐng)求的主體是否有操作權(quán)限:
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拿出來(lái)。如果當(dāng)前的請(qǐng)求屬于Deny的范圍,直接禁止操作。這個(gè)就是第一個(gè)原則。
第二步到第六步,是具體的policy。如果該主體有這個(gè)類(lèi)型的policy存在,就按照第二個(gè)原則處理。如果沒(méi)有,跳到下一個(gè)policy類(lèi)別的檢查。
那么多種的Policy類(lèi)別,為什么是這個(gè)排列順序呢?我是這么理解的:
1.Organization SCP作為組織級(jí)別策略,優(yōu)先級(jí)最高。
2.Resource-based policy可以跨帳號(hào)賦予權(quán)限,級(jí)別比后面的高一些。
3.Permission Boundary的作用是提前為用戶定義一個(gè)最大的權(quán)限范圍,避免意外打開(kāi)了權(quán)限的情況,所以比后面的級(jí)別要高。
4.Session policies是會(huì)話級(jí)別,允許臨時(shí)賦予權(quán)限,所以比Identity-based policies高。
5.Identity-based policies是最穩(wěn)定的,所以檢查放在最后。
不過(guò),這里有一個(gè)特例,就是Resource-based policy。如果它是Implicit Deny的情況,還是會(huì)繼續(xù)后面的檢查,不會(huì)阻止。還有一個(gè)復(fù)雜的情況是關(guān)于Session policy的,這個(gè)就不在本文解釋了。
其實(shí),即便邏輯復(fù)雜,判斷是否有權(quán)限還是可以簡(jiǎn)單地總結(jié)為一句話:
只有具備顯式的Allow,并且沒(méi)有顯式的Deny,才有權(quán)限。
或者
如果沒(méi)有顯式的Allow,或者有顯式的Deny,就沒(méi)有權(quán)限。