如何使用 IAM Role 進行跨帳號的資源存取

程式技術

如果你想要讓別人能夠存取你 AWS 帳號上的資源,最安全的做法,就是新增一個 IAM Role,並透過 Assume Role 的方式,將這個 Role 賦予給對方。對方可以透過 STS (Security Token Service) 來取得這個 Role 的暫時性憑證,並使用這個憑證來存取你的資源。

舉個例子,假設你想讓 Development 帳號可以讀取 Production 帳號底下的的 S3 資源,可以怎麼做?

首先在 Production 帳號中新增一個讀取 S3 Bucket 的 Policy,並命名為 read_my_bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-bucket"
    },
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

然後一樣在 Production 帳號新增一個 Role,並命名為 delegate_read_my_bucket,並且在 Trust Relationship 設定讓該 Role 能被 Development 帳號使用:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<DEVELOPMENT_ACCOUNT_ID>:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

設定完成之後,將剛剛新增的 Policy 附加到 Role 上。此時帳號 Development 就可以透過 AssumeRole API 來取得一個暫時性的 Credential,並且使用該 Credential 來讀取 S3 Bucket。

--role-session-name 參數取一個你喜歡的名字即可。

aws sts assume-role --role-arn arn:aws:iam::<PRODUCTION_ACCOUNT_ID>:role/delegate_s3_bucket_role --role-session-name "my-s3-session"

指令的結果如下:

{
  "Credentials": {
    "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    "SessionToken": "AQoDYXdzEGcaEXAMPLE2gsYULo+Im5ZEXAMPLEe...",
    "Expiration": "2014-12-11T23:08:07Z",
    "AccessKeyId": "AKIAIOSFODNN7EXAMPLE"
  }
}

將上述資訊設成環境變數,就可以在 Development 帳號中讀取 Production 的 S3 Bucket 了:

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_SESSION_TOKEN="AQoDYXdzEGcaEXAMPLE2gsYULo+Im5ZEXAMPLEe..."

嘗試用 Python SDK 來印出 Bucket 底下所有的物件。

import os

import boto3

session = boto3.Session(
    aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
    aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
    aws_session_token=os.environ["AWS_SESSION_TOKEN"],
)

s3 = session.resource("s3")

my_bucket = s3.Bucket("my-bucket")

for my_bucket_object in my_bucket.objects.all():
    print(my_bucket_object.key)

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

0 則留言