AWS一個賬號下面可以通過IAM創建多個用戶,但默認情況下,資源是沒有用戶屬性的,一個賬號下的資源,只要用戶有這種資源的操作權限,那麼不過是你自己創建的還是其他用戶創建的,你都可以操作。
但在客戶的實際使用場景中,有時需要隔離各用戶之間的資源。按照AWS的建議,那你需要創建不同的賬號,比如你有開發測試資源環境,還有生產資源環境,那麼你需要創建兩個賬號,但創建兩個賬號,在查詢費用的時候不方便,AWS提供consolidateBill的授權方案,可以合併賬單。
所以AWS官方是沒有一套簡單的方法可以實現我們想要的效果的。
具體可以參考AWS開發者論壇很stackoverflow上的一些帖子
https://forums.aws.amazon.com/message.jspa?messageID=346577
https://forums.aws.amazon.com/thread.jspa?threadID=187874
https://stackoverflow.com/questions/25909203/how-to-differentiate-between-different-aws-environments-dev-test-stage-prod
那在同一個賬號下,能不能做到不同用戶的資源隔離呢。
通過IAM策略的靈活配置和aws全局變量,可以部分滿足一些場景的需求。
在看場景之前,我們先了解一下,AWS IAM的授權機制:
AWS是通過策略來定義權限,再將這些策略授予用戶、組或者角色,使用戶、組或者角色擁有相應的權限。
IAM 策略是包含一個或多個語句的JSON 文檔。每個語句的結構如下:
{
"Statement":[{
"Effect":"effect",
"Action":"action",
"Resource":"arn",
"Condition":{
"condition":{
"key":"value"
}
}
}
]
}
組成語句的各個元素如下:
Effect:此 effect 可以是 Allow 或 Deny。默認情況下 IAM 用戶沒有使用資源和 API 操作的權限,因此,所有請求均會被拒絕。顯式允許將覆蓋默認規則。顯式拒絕將覆蓋任何允許。
Action:action 是對其授予或拒絕權限的特定 API 操作。
Resource:操作影響的資源。有些 Amazon EC2 API 操作允許您在策略中包括該操作可以創建或修改的特定資源。要在語句中指定資源,您需要使用其 Amazon 資源名稱 (ARN)。如果 API 操作不支持 ARN,請使用 * 通配符指定操作可以影響所有資源。
Condition:條件是可選的。它們可以用於控制策略生效的條件。
由此可以看出,
第一、要想進行資源隔離,resource是關鍵。但問題來了,就如上面所說,並不是所有操作都支持資源級權限。
第二、即使有些操作是支持資源級權限的,那麼怎麼唯一標示一個資源或一批資源呢?AWS使用Amazon 資源名稱 (ARN)來標示資源。
Amazon Elastic Compute Cloud (Amazon EC2) 的ARN 樣例
arn:aws:ec2:region:account-id:customer-gateway/cgw-id
arn:aws:ec2:region:account_id:dedicated-host/host_id
arn:aws:ec2:region:account-id:dhcp-options/dhcp-options-id
arn:aws:ec2:region::image/image-id
arn:aws:ec2:region:account-id:instance/instance-id
arn:aws:iam::account:instance-profile/instance-profile-name
arn:aws:ec2:region:account-id:internet-gateway/igw-id
arn:aws:ec2:region:account-id:key-pair/key-pair-name
arn:aws:ec2:region:account-id:network-acl/nacl-id
arn:aws:ec2:region:account-id:network-interface/eni-id
arn:aws:ec2:region:account-id:placement-group/placement-group-name
arn:aws:ec2:region:account-id:route-table/route-table-id
arn:aws:ec2:region:account-id:security-group/security-group-id
arn:aws:ec2:region:account-id:snapshot/snapshot-id
arn:aws:ec2:region:account-id:subnet/subnet-id
arn:aws:ec2:region:account-id:volume/volume-id
arn:aws:ec2:region:account-id:vpc/vpc-id
arn:aws:ec2:region:account-id:vpc-peering-connection/vpc-peering-connection-id
arn:aws:ec2:region:account-id:***-connection/***-id
arn:aws:ec2:region:account-id:***-gateway/vgw-id
這裏我們看到,大部分資源是使用ID來唯一標示的,但是ID是創建資源時,由AWS自動生成的,沒什麼可以利用的規律。這個問題就有點棘手了。
下面我們針對幾種場景來試着解決一下上面提出的問題。
VPC隔離
目標:每個用戶創建、管理並控制自己的VPC。
我們先看一下VPC的操作(僅限VPC,暫不包括VPC下的組件):
DescribeVpcs、CreateVpc、DeleteVpc、ModifyVpcAttribute
首先所有describe操作都不支持資源級權限,所以想要互相看不見暫時辦不到。
很不幸,上面所有這些操作都不支持資源級權限。
所以,我建議,VPC由管理員(有權限的用戶)統一管理,其他用戶只讀。
VPC中大部分組件的刪除操作可以支持資源級權限。但如上面所說,大部分資源都是以ID來唯一標示的,VPC下面的組件有很多,而且是動態的,隨時增加,那有沒有辦法可以標示出這些組件是屬於我的呢。
答案是肯定的,AWS提供Tag來給資源打標籤,我們可以規定大家按一定的規則來給資源加上Tag,比如加上(creator:username)。那麼在進行VPC組件刪除操作的時候就可以通過condition條件ec2:ResourceTag/tag-key進行控制。但這方案也有一定缺陷,因爲Tag是會被任何有權限的用戶修改的,別的用戶改了這個資源的Tag,或者你自己改了這個Tag,那麼你就不能繼續限制對它的操作了。
subnet子網的刪除操作是不支持資源級權限的。同樣建議子網定義由專門的網絡管理員操作。
只允許客戶在指定的VPC中創建和管理虛機
還是一樣,先來看一下有關虛機的操作:
RunInstances、StartInstances、RebootInstances、StopInstances、TerminateInstances
1)創建虛機:
RunInstances 是支持資源級權限的,它支持:
Image:使用什麼樣的鏡像
Key pair:使用哪個key pair
Security group:使用哪個安全組
Subnet:使用哪個子網
這裏沒有VPC,但是有subnet,我們再看一下subnet支持的condition。
ec2:AvailabilityZone
ec2:Region
ec2:ResourceTag/tag-key
ec2:Vpc
這裏是有VPC的。所以在指定的VPC中創建虛機是可以的。
2)管理虛機
StartInstances、RebootInstances、StopInstances、TerminateInstances
這些操作是不能限定VPC的,可以限定單臺虛機資源,但這樣就達不到我們想要的效果。還好這些操作的condition條件都有ec2:ResourceTag/tag-key。同樣使用和上面相同的方法,對我們自己的虛機打上我們的Tag,我們就可以限定只有我自己才能操作這些我打了tag的虛機。
一個大問題
雖然我們可以給資源打tag,但是正如上面所說,有一個大問題,我們怎麼阻止其他用戶修改我的tag呢?
我們先來看一下ec2裏Tag的相關操作:
CreateTags、DeleteTags。這兩個操作都是支持資源級權限的。我們是否也可以使用ec2:ResourceTag/tag-key來隔離各個用戶的操作呢。看上去好像可以。但這裏有一個前提,是你先要有一個tag-key,例如creator:username。那麼創建這個tag的時候你是不能用conditionec2:ResourceTag/creator :username的,因爲初始情況,是一個tag都沒有的,所以加了這個condition,你就無法創建tag。那麼只能不加,不加的話,你就無法限制其他用戶對tag的修改。但DeleteTags你可以使用這種方法,來限制其他用戶的刪除。
看到這裏其實感覺有點悖論,是先有雞還是先有蛋的問題。或者把create 和 modify操作分開的話,也可以部分解決這個問題,但不幸的是這兩個操作也不是分開的。
但我們還是找到了一種稍微折中一點的辦法。放棄一些tag使用的功能,換來這個問題的解決。思路就是做到只能創建,不能修改。AWS CreateTags 創建Tag是支持一種condition ec2:CreateAction,可以限定只有在虛機創建的時候可以創建tag,創建完以後,你就不能修改和新增其他tag了。這樣通過控制tag的使用,達到了管理tag的效果。
寫到這裏,主要場景和解題思路已經講完了。
下面我們來實操一下。
創建兩個用戶,不要分配權限。
用戶管理員創建兩個VPC,在每個VPC裏創建一個子網。
下面來創建策略
{
"Version":"2012-10-17",
"Statement": [
{
//基本ec2查詢操作和一些創建虛機必要的,但不涉及資源權限的操作
"Effect":"Allow",
"Action": [
"ec2:Describe*",
"ec2:AttachVolume",
"ec2:CreateVolume",
"ec2:AttachNetworkInterface",
"ec2:DetachVolume",
"ec2:DeleteVolume"
],
"Resource": "*"
},
{
//限定只能在虛機創建時,創建tag
"Effect":"Allow",
"Action": [
"ec2:CreateTags"
],
"Resource":"arn:aws:ec2: region:account:*/*",
"Condition": {
"StringEquals": {
"ec2:CreateAction": [
"RunInstances",
"CreateVolume"
]
}
}
},
{
//限定當該虛機的creator標籤等於當前用戶時,才能進行該虛機的操作。
"Effect":"Allow",
"Action": [
"ec2:RebootInstances",
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:TerminateInstances"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/creator": "${aws:username}"
}
},
"Resource": "*"
},
{
//限定當前用戶只能在指定的vpc中啓動虛機
"Effect":"Allow",
"Action":"ec2:RunInstances",
"Resource":"arn:aws:ec2: region:account:subnet/*",
"Condition": {
"StringEquals": {
"ec2:Vpc":"arn:aws:ec2: region:account:vpc/vpc-id"
}
}
},
{
//其他必要的虛機啓動資源授權
"Effect":"Allow",
"Action":"ec2:RunInstances",
"Resource": [
"arn:aws:ec2:eu-central-1::image/ami-*",
"arn:aws:ec2:eu-central-1:286883986851:volume/*",
"arn:aws:ec2:eu-central-1:286883986851:network-interface/*",
"arn:aws:ec2:eu-central-1:286883986851:key-pair/*",
"arn:aws:ec2:eu-central-1:286883986851:security-group/*"
]
}
]
}
更換vpc-id,創建另一個策略。
將兩個策略分別分配給兩個用戶。
然後就可以測試效果了。大家自己動動手吧。