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

介紹

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

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

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

當 Amazon S3 收到對象操做請求時,它會將基於資源的全部相關權限(對象訪問控制列表 (ACL)、存儲桶策略、存儲桶 ACL)和IAM用戶策略轉換爲將在運行時進行評估的策略集。而後它會經過一系列步驟評估生成的策略集。在每一個步驟中,它會在三個特定上下文 (用戶上下文、存儲桶上下文和對象上下文) 中評估一個策略子集。

簡單來講就是先判斷用戶權限,而後判斷存儲桶權限,最後判斷對象權限。安全

目前咱們都是經過同一個AWS帳戶下的多個IAM用戶去訪問S3的,所以能夠只使用IAM用戶策略去作訪問權限控制,這也基本能知足絕大部分常規的權限控制需求,若是沒法知足的狀況再考慮使用存儲桶處理和ACL。ide


實戰演練

準備工做

  • 使用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-public1derek-public2derek-bucket3/public,其中derek-public2只有可讀權限,若是用戶嘗試寫入,例如建立一個文件夾,會顯示「沒法使用名稱XXX建立文件夾」;

clipboard.png

  • 若是用戶嘗試進入無權限的bucket或者文件夾,例如derek-bucket1derek-bucket3/user1,會顯示「Access Denied」;

clipboard.png

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下的全部對象;ui

  • 由於該策略只有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-bucket2derek-bucket3/user2中的對象讀寫、複製操做;
statement3: 容許列出derek-bucket3/user2下的全部對象;spa

  • 將該策略附加給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
  • 根據以前的步驟,使用Harp-Admin爲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


一些坑

在使用user1時,在derek-bucket1中創建文件夾沒有問題,可是上傳文件卻失敗,提示OptionsRequestDenied,經谷歌查詢猜想可能和瀏覽器的AdBlock相關插件有關,因而換火狐瀏覽器、或者使用CLI上傳,都沒有問題。code

相關文章
相關標籤/搜索