他のアカウントへS3バケットへのアクセスを許可する
クロスアカウントと外部ID
このあたりに書いてあることを実践してみます。
外部 ID について - AWS Security Token Service
一時的なセキュリティ認証情報を使用して AWS リソースをリクエストする - AWS Security Token Service
準備
アクセス元のアカウントIDを調べます。
ここではアクセス元を999999999999
としS3バケットがある方を111111111111
とします。
S3バケットを持つアカウントの方にIAMにロールを作成
- ロール名を入力
ここではcross-account
としました。
- アクセス元のアカウントIDを入力
- ポリシーを選択
ここではSelectPolicyTemplateからAmazon S3 Read Only Access
を選択し、
そのまま進んでロールを作成しました。
アクセス元のアカウントからアクセスしてみる
- アクセス元のアカウントにEC2を立ててそこからアクセスしてみます。
sshログインしたら試しにS3のバケット一覧を取得してみます。
$ ssh ec2-user@ec2-54-65-xxx-xxx.ap-northeast-1.compute.amazonaws.com -i key.pem [ec2-user@ip-172-31-24-163 ~]$ aws s3 ls 2014-12-23 07:25:37 cf-templates-xxxxxxxxxxxxx-ap-northeast-1 2015-01-11 03:32:18 elasticbeanstalk-ap-northeast-1-999999999999 2015-01-05 14:42:54 yustam-artifact-repository 2014-11-07 15:21:07 yustam-docker-registry 2014-12-11 09:52:14 yustam-lambda-sample 2014-11-14 12:26:45 yustam-private
ロールを付与しておくとここではアクセス元アカウントのバケットが確認できます。
- STSのAssumeRoleでセッションを作成
ここではaws-cli
を使用してクロスアカウントアクセスを利用します。
sts assume-role
を使用してS3バケットアクセス用のセッションを作成します。
[ec2-user@ip-172-31-24-163 ~]$ aws sts assume-role --role-arn arn:aws:iam::111111111111:role/cross-account --role-session-name hoge { "AssumedRoleUser": { "AssumedRoleId": "AROAJWSTZ4KKB2EXAMPLE:hoge", "Arn": "arn:aws:sts::111111111111:assumed-role/cross-account/hoge" }, "Credentials": { "SecretAccessKey": "EmlBUyGcOKPI/Sdsf4RCE56sHnbo6XfJkEXAMPLE", "SessionToken": "AQoDYXdzECUagAKpFP2OknLKXsPLl/801n...(省略)", "Expiration": "2015-02-07T05:19:53Z", "AccessKeyId": "ASIAJ2GNOUN4ZEXAMPLE" } }
- 作成したセッションを利用してS3バケットにアクセスしてみる
先ほどのレスポンスに記載されたアクセスキー/シークレットキー/トークンを使用します。
[ec2-user@ip-172-31-24-163 ~]$ export AWS_ACCESS_KEY_ID=ASIAJ2GNOUN4ZEXAMPLE [ec2-user@ip-172-31-24-163 ~]$ export AWS_SECRET_ACCESS_KEY=EmlBUyGcOKPI/Sdsf4RCE56sHnbo6XfJkEXAMPLE [ec2-user@ip-172-31-24-163 ~]$ export AWS_SECURITY_TOKEN=AQoDYXdzECUagAKpFP2OknLKXsPLl/801n...(省略) [ec2-user@ip-172-31-24-163 ~]$ aws s3 ls 2013-02-15 08:04:27 private.yustam.jp 2013-01-21 05:53:07 www.robotjohn.jp 2013-07-10 01:08:47 www.yustam.jp 2013-10-27 02:28:07 yustam.convert
S3バケットの一覧を取得するとアクセス先アカウントのバケット一覧が取得できます。
Javaから利用する場合は以下のようにAssumeRoleしてcom.amazonaws.auth.BasicSessionCredentials
を作成すればいいみたいです。
package jp.yustam.s3.ca; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicSessionCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.Bucket; import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient; import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; import com.amazonaws.services.securitytoken.model.AssumeRoleResult; import com.amazonaws.services.securitytoken.model.Credentials; import org.junit.Test; public class CrossAccountTest { static final String ROLE_ARN = "arn:aws:iam::111111111111:role/cross-account"; static final String ROLE_SESSION_NAME = "hoge"; @Test public void testAccessS3BucketOnAnotherAccount() { AWSSecurityTokenService sts = new AWSSecurityTokenServiceClient(); AssumeRoleResult result = sts.assumeRole(new AssumeRoleRequest() .withRoleArn(ROLE_ARN) .withRoleSessionName(ROLE_SESSION_NAME)); Credentials credentials = result.getCredentials(); AWSCredentials sessionCredentials = new BasicSessionCredentials(credentials.getAccessKeyId(), credentials.getSecretAccessKey(), credentials.getSessionToken()); AmazonS3 s3 = new AmazonS3Client(sessionCredentials); for (Bucket bucket : s3.listBuckets()) { System.out.println(bucket); } } }
Javaからもっと簡単に使う(3/5更新)
Credentialsを毎回生成するのもイケてないし有効期限があるから管理めんどうだなと
思ってたらSTSAssumeRoleSessionCredentialsProvider
という便利なものが既に用意されていた。
AWSCredentialsProvider cp = new STSAssumeRoleSessionCredentialsProvider(ROLE_ARN, ROLE_SESSION_NAME); AmazonS3 s3 = new AmazonS3Client(cp);