介紹
要對S3的訪問權限做控制,既可以使用基於身份的策略(IAM用戶策略),也可以使用基於資源的策略(ACL和存儲桶策略)。
訪問一個存儲桶的權限控制流程如圖所示:
訪問存儲桶中的對象的權限控制流程如圖所示:
當 Amazon S3 收到對象操作請求時,它會將基於資源的所有相關權限(對象訪問控制列表 (ACL)、存儲桶策略、存儲桶 ACL)和IAM用戶策略轉換爲將在運行時進行評估的策略集。然後它會通過一系列步驟評估生成的策略集。在每個步驟中,它會在三個特定上下文 (用戶上下文、存儲桶上下文和對象上下文) 中評估一個策略子集。
簡單來說就是先判斷用戶權限,然後判斷存儲桶權限,最後判斷對象權限。
目前我們都是通過同一個AWS賬戶下的多個IAM用戶去訪問S3的,因此可以只使用IAM用戶策略去做訪問權限控制,這也基本能滿足絕大部分常規的權限控制需求,如果無法滿足的情況再考慮使用存儲桶處理和ACL。
實戰演練
準備工作
- 使用AWS根賬號(我的賬戶名是
Harp
)登錄AWS管理控制檯,選擇IAM服務進入,創建一個名爲Administrators
的組,並向其附加AdministratorAccess
權限; - 創建一個IAM用戶(
Harp-Admin
),並將其添加到Administrators
組; - 下載Authy軟件,手機版或PC版均可,並安裝,用於爲用戶添加MFA驗證;
- 在IAM控制檯中點擊用戶,點擊
Harp-Admin
,點擊安全憑證; - 已分配 MFA 設備目前顯示未分配,點擊管理,添加虛擬 MFA 設備,繼續;
- 此時彈出如下的對話框,如果使用的Authy是手機版本的,那麼點擊顯示QR碼並掃描,如果是PC版則點擊顯示私有密鑰,並在PC版的Authy中輸入該密鑰;
- 之後將Authy中連續兩個30s的MFA CODE輸入以下文本框中,並點擊分配MFA;
- 此時
Harp-Admin
已經開啓了MFA驗證,使用該用戶登錄控制檯時,需要在驗證密碼之後,再驗證MFA(即輸入Authy中的實時CODE); - 在IAM控制檯中點擊,將密碼策略修改如下,可根據需要調整;
創建測試用戶和存儲桶
- 根據AWS最佳實踐,本步驟的操作都是使用
Harp-Admin
來處理的; - 依次創建以下4個用戶,暫不賦予任何權限;
- 如下圖,創建Bucket一列對應的存儲桶,Object不爲*的需要創建對應的文件夾,權限一列是我們要實現的訪問控制權限;
配置IAM用戶策略
s3_common_policy
- 在IAM控制檯中點擊策略,創建策略,JSON,輸入如下json,命名爲
s3_common_policy
;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::derek-public*"
]
},
{
"Sid": "AllowRootLevelListingOfTheBucket",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::derek-bucket3"
],
"Condition": {
"StringEquals": {
"s3:prefix": [
""
],
"s3:delimiter": [
"/"
]
}
}
},
{
"Sid": "AllowListBucketOfASpecificUserPrefix",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::derek-bucket3"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"public/*"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::derek-public1/*",
"arn:aws:s3:::derek-bucket3/public/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::derek-public2/*"
}
]
}
解釋一下各條statements:
statement1: 對所有的S3資源賦予s3:ListAllMyBuckets和s3:GetBucketLocation,這兩個權限是給控制檯使用的,通過控制檯訪問S3時,需要這兩個權限來正常列出所有存儲桶,如果通過CLI訪問則不需要;
statement2: 賦予所有derek-public開頭的存儲桶列出存儲桶對象的權限(s3:ListBucket);
statement3: 允許列出derek-bucket3第一層路徑下的對象,這個寫法可以在S3的官方文檔中找到;
statement4: 允許列出derek-bucket3/public下的所有對象;
statement5: 允許對derek-public1和derek-bucket3/public中的對象讀寫、複製操作;
statement6: 允許對derek-public2中的對象讀取操作;
- 創建一個用戶組
s3_common_group
,並將所有用戶添加到其中,將s3_common_policy
附加到這個組; - 此時id爲1/4/8的權限已經實現,4個用戶可以正常讀取derek-public1、derek-public2和derek-bucket3/public,其中derek-public2只有可讀權限,如果用戶嘗試寫入,例如創建一個文件夾,會顯示“無法創建名爲XXX的文件夾”;
- 如果用戶嘗試進入無權限的bucket或者文件夾,例如derek-bucket1或derek-bucket3/user1,會顯示“Access Deny”;
user1_policy
- 在IAM控制檯中點擊策略,創建策略,JSON,輸入如下json,命名爲
user1_policy
;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::derek-bucket1",
"arn:aws:s3:::derek-bucket2"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::derek-bucket1/*",
"arn:aws:s3:::derek-bucket3/user1/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::derek-bucket2"
},
{
"Sid": "AllowListBucketOfASpecificUserPrefix",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::derek-bucket3"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"user1/*"
]
}
}
}
]
}
解釋一下各條statements:
statement1: 允許列出derek-bucket1和derek-bucket2中的所有對象;
statement2: 允許對derek-bucket1和derek-bucket3/user1中的對象讀寫、複製操作;
statement3: 允許對derek-bucket2中的對象讀取操作;
statement4: 允許列出derek-bucket3/user1下的所有對象;
- 因爲該策略只有user1使用,我們可以不創建組,直接將其附加到user1上;
- 點擊用戶,user1,添加權限,直接附加現有策略,選擇
user1_policy
,審覈,添加權限; - 此時id爲3/4/6中涉及user1的權限已經配置完成;
user2_policy
- 在IAM控制檯中點擊策略,創建策略,JSON,輸入如下json,命名爲
user2_policy
;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::derek-bucket2"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::derek-bucket2/*",
"arn:aws:s3:::derek-bucket3/user2/*"
]
},
{
"Sid": "AllowListBucketOfASpecificUserPrefix",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::derek-bucket3"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"user2/*"
]
}
}
}
]
}
解釋一下各條statements:
statement1: 允許列出derek-bucket2中的所有對象;
statement2: 允許對derek-bucket2和derek-bucket3/user2中的對象讀寫、複製操作;
statement3: 允許列出derek-bucket3/user2下的所有對象;
- 將該策略附加給user2,此時id爲4/7中涉及user2的權限已經配置完成;
user3_policy
- 在IAM控制檯中點擊策略,創建策略,JSON,輸入如下json,命名爲
user3_policy
;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::derek-bucket3"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::derek-bucket3"
}
]
}
- 將該策略附加給user3,此時id爲5的權限已經配置完成;
user4_policy
- 根據之前的步驟,爲user4創建虛擬MFA;
- 在IAM控制檯中點擊策略,創建策略,JSON,輸入如下json,命名爲
user4_policy
;
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::derek-bucket4"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::derek-bucket4/*"
]
},
{
"Effect": "Deny",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::derek-bucket4/mfa/*"
],
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": false
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::derek-bucket4/mfa/*"
]
}
]
}
解釋一下各條statements:
statement1: 允許列出derek-bucket4中的所有對象;
statement2: 允許對derek-bucket4中的對象讀寫、複製操作;
statement3: 未通過MFA驗證時禁止寫derek-bucket4/mfa下的所有對象;
statement4: 允許讀取derek-bucket4/mfa下的所有對象;
- 其中涉及MFA驗證的權限控制可以參考帶MFA條件的示例策略;
- 將該策略附加給user4,此時id爲9的權限已經配置完成;
- 如果user4通過控制檯登錄,必須要使用MFA驗證,登錄之後符合statement3的條件,因此可以在mfa文件夾下寫入內容;
- 如果user4通過CLI直接向mfa寫入,則會被拒絕,如圖:
- 此時需要加上MFA驗證,輸入下圖中的命令,兩個紅框依次替換成user4的MFA ARN和MFA當前的6位token,會返回一個json格式的臨時憑證,該憑證默認有效期12h,更多關於CLI和MFA的內容可參考 如何使用 MFA 令牌對通過 AWS CLI 進行的 AWS 資源訪問執行身份驗證?:
- 修改AWS CLI的配置文件credentials,如下圖紅框,添加一個mfa-user,將上一步的結果複製到這裏;
- 利用mfa-user複製文件到mfa文件夾,提示覆製成功;