AWS實戰 - 利用IAM對S3做訪問控制

介紹

要對S3的訪問權限做控制,既可以使用基於身份的策略(IAM用戶策略),也可以使用基於資源的策略(ACL和存儲桶策略)。

訪問一個存儲桶的權限控制流程如圖所示:
clipboard.png

訪問存儲桶中的對象的權限控制流程如圖所示:
clipboard.png

當 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中輸入該密鑰;

clipboard.png

  • 之後將Authy中連續兩個30s的MFA CODE輸入以下文本框中,並點擊分配MFA;

clipboard.png

  • 此時Harp-Admin已經開啓了MFA驗證,使用該用戶登錄控制檯時,需要在驗證密碼之後,再驗證MFA(即輸入Authy中的實時CODE);
  • 在IAM控制檯中點擊,將密碼策略修改如下,可根據需要調整;

clipboard.png

創建測試用戶和存儲桶

  • 根據AWS最佳實踐,本步驟的操作都是使用Harp-Admin來處理的;
  • 依次創建以下4個用戶,暫不賦予任何權限;

clipboard.png

  • 如下圖,創建Bucket一列對應的存儲桶,Object不爲*的需要創建對應的文件夾,權限一列是我們要實現的訪問控制權限;

clipboard.png

配置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寫入,則會被拒絕,如圖:

clipboard.png

clipboard.png

  • 修改AWS CLI的配置文件credentials,如下圖紅框,添加一個mfa-user,將上一步的結果複製到這裏;

clipboard.png

  • 利用mfa-user複製文件到mfa文件夾,提示覆製成功;

clipboard.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章