簡體   English   中英

在AWS S3中為權限指定IAM角色

[英]Specifying IAM roles for permissions in AWS S3

我試圖將我的所有AWS Cognito用戶限制為他們在S3存儲桶中自己的子目錄。

我不希望它們在我的較大存儲桶中列出,讀取或寫入其他人的子目錄/文件,而我只希望它們在自己的目錄中讀取和寫入對象。

從這個AWS文檔片段中汲取了靈感。

這是我的政策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket"
            ],
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "subfolder/"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}",
                "arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}/*"
            ]
        }
    ]
}

我的代碼使用user_id = test@test.com來檢索某個用戶的文件,但實際上允許我檢索受限制的文件:

import boto

# These keys are *not* hardcoded, I'm just leaving out
# the auth flow to get them from Cognito/STS as described 
# here: https://mobile.awsblog.com/post/Tx2FL1QAPDE0UAH/Understanding-Amazon-Cognito-Authentication-Part-2-Developer-Authenticated-Ident
conn = boto.s3.connect_to_region('us-east-1',
    aws_access_key_id=ACCESS_KEY_FROM_COGNITO,
    aws_secret_access_key=SECRET_KEY_FROM_COGNITO,
    security_token=SECURITY_KEY_FROM_COGNITO)

# get the bucket
b = conn.get_bucket('my-bucket', validate=False)

# try to get an object we SHOULD be able to get
k = Key(b)
k.key = 'subfolder/us-east-1:xxxx-xxxx-xxxx-xxxxxxxxx/foobar'
print "Contents:", k.get_contents_as_string()  # success!

# try to get and object we SHOUDN'T be able to get
k2 = Key(b)
k2.key = 'subfolder/BLAH_BLAH/restricted'
print "Contents:", k2.get_contents_as_string()  # should fail, but doesn't

不幸的是,我可以訪問和讀取兩個文件的內容,但是我遵循的是AWS博客文檔中的完全相同的模式。 我也不確定為什么在boto連接中需要validate=False ,但它似乎工作得很好。

我想念什么?


編輯:為響應下面的答案,我嘗試將我的角色更新為以下內容,但沒有任何區別:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket"
            ],
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "subfolder/${cognito-identity.amazonaws.com:sub}/*"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket/subfolder/${cognito-identity.amazonaws.com:sub}/*"
            ]
        }
    ]
}

我還通過使用通過Cognito令牌從STS檢索的訪問/秘密/安全令牌三重創建了boto IAMConnection對象,並查詢了我的角色名稱,以確認我正在使用的訪問憑據來自Cognito。為我的身份池識別用戶。 這樣做時,嘗試讀取此角色時遇到了以下異常(這正是我沒有授予訪問權限而應該發生的情況):

BotoServerError: BotoServerError: 403 Forbidden
<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
  <Error>
    <Type>Sender</Type>
    <Code>AccessDenied</Code>
    <Message>User: arn:aws:sts::MY_AWS_ACCT_ID:assumed-role/my_policy_role_name/session_name_here is not authorized to perform: iam:GetRole on resource: role awsNameFor_Role_Given_123012313</Message>
  </Error>
  <RequestId>xxx-xxxx-xxxx-xxxx-xxxxx</RequestId>
</ErrorResponse>

因此,仍然不清楚為什么它不起作用。

5件事:

  1. 確保您使用的是Amazon Cognito身份服務發布的憑證,否則$ {cognito-identity.amazonaws.com:sub}將為空,並授予您訪問所有內容的權限
  2. 確保在更新策略后發布了您正在使用的Amazon Cognito Identity憑證,該策略嵌入在憑證的會話部分中,因此,如果您使用的是舊憑證,則它們可能未附加當前策略。
  3. 您無法使用用戶名,而必須使用Amazon Cognito身份ID。 因此,代替的是test@test.com,它將是身份ID:us-east-1:beef-beef-beef-xxxxxxxxx
  4. 您的池具有2個與之關聯的角色,一個未經身份驗證的角色和一個經過身份驗證的角色。 確保將策略設置為正確的角色,在這種情況下,您似乎正在使用開發人員身份驗證的身份,因此應在身份驗證角色上修改策略。
  5. 檢查您的S3存儲桶策略,如果您允許匿名訪問存儲桶,則Cognito角色策略將不會覆蓋它。 在這種情況下,請關閉匿名訪問。 http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-2

看來您的代碼正在使用硬編碼的訪問密鑰和秘密密鑰,而不是在使用Cognito來檢索憑據。 要為所有用戶嵌入相同的訪問密鑰和秘密密鑰,您需要遵循身份驗證流程並使用GetId( boto參考AWS參考 )來獲取身份ID,然后使用GetCredentialsForIdentity( boto參考 AWS參考 )來使用Cognito。獲取由Cognito頒發的當前ID的憑據。 然后將這些憑據與boto S3連接一起使用。

另外,請確保為每個用戶緩存ID,並在對Cognito進行其他調用時重新使用它。

答案很愚蠢。 顯然,S3中的存儲桶本身具有自己的策略(它們相當隱蔽),但是我有以下指令:

Principal: "*"

這使得存儲桶在世界范圍內都可以讀取。

第二個啟示是,如果使用帶有Conditions3:ListBucket限制存儲桶,這並不意味着如果您列出存儲桶,則只會得到那些結果-必須按名稱調用它。 boto為例:

wrong = bucket.list()  # will simply 403
right = bucket.list(prefix="base/subdir/<cognito-id>/")  # will succeed

換句話說,S3的設計使您必須知道所需文件夾的前綴鍵,無論如何這都是一種好習慣。

我必須說,AWS的人員在這里和在他們的論壇上診斷此問題的幫助給我留下了深刻的印象。 無論如何,現在對S3有了更好的了解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM