これさえ見れば大丈夫! Javaで別アカウントのS3を利用する方法

こんにちは。都築です。
 
今回はJavaで別アカウントのS3をクロスアカウントで利用する方法についてご紹介したいと思います。S3への接続方法は色々なサイトで紹介されていますが、非推奨のメソッドが利用されているなど適切でないものも多いです。
 
ぜひご参考にしていただければと思います。

環境

今回ご紹介する方法は下記環境で実際に動作しています。

OS
Windows8.1
Java
Java8
Amazon SDK
1.11.681

 

概要

イメージとしては下記の様なイメージです。

 
S3はアカウントAにあるが、利用するシステムはアカウントBなどの場合を想定しています。本来S3を利用するにはそのアカウントのアクセスキーIDやシークレットアクセスキーなどが必要となります。
 
しかしセキュリティの観点で、利用する権限のみ渡したい場合などがあります。そういった場合に自身のアカウントBに、アカウントAのS3への権限を付与してもらいます。そして一時クレデンシャルを介することで、アカウントBとしてアカウントAのS3を利用することができる仕組みとなっています。

準備

まず、JavaでS3を利用するためにSDKが用意されていますので、これをプロジェクトに設定します。SDKは下記公式サイトからダウンロードしてきます。
https://aws.amazon.com/jp/sdk-for-java/
 
ダウンロードし、展開すると下記の様なjarが入っています。

内容 詳細
/lib/aws-java-sdk-1.11.681.jar SDK本体
/third-party/lib/…… SDKで利用するサードパーティのjar

それぞれのjarについてJavaで使用するためにプロジェクトのビルドパスを通します。

通常の場合

ビルドパスを通しましたら、まずはS3クライアントを生成します。クロスアカウントでない場合は下記の通り、簡単です。

AmazonS3 s3Cliet = AmazonS3ClientBuilder.defaultClient();

サーバーに設定されたAWS接続のデフォルトクライアントを生成するのみです。

クロスアカウントの場合

クロスアカウントの場合は一時クレデンシャルを利用するため、多少複雑になります。

//クレデンシャルプロバイダの生成
AWSCredentialsProvider cp = new InstanceProfileCredentialsProvider(true);

//セキュリティトークンサービスの生成(一時クレデンシャルを生成するためのサービス)
AWSSecurityTokenService sts = AWSSecurityTokenServiceClientBuilder
					.standard()
					.withCredentials(cp)
					.withRegion(Regions.AP_NORTHEAST_1)
					.build();

//アカウントBのアカウントIDなどのロールARNを設定し、一時クレデンシャルを取得
String ROLE_B_ARN = "arn:aws:iam::12345789:role/IAM-ROLEB";
String ROLE_SESSION_NAME = "sample";
AssumeRoleRequest roleRequest = new AssumeRoleRequest()
					.withRoleArn(ROLE_B_ARN)
					.withRoleSessionName(ROLE_SESSION_NAME);
AssumeRoleResult result = sts.assumeRole(roleRequest);
Credentials credentials = result.getCredentials();

//一時クレデンシャルのアクセスキーIDやシークレットアクセスキーでクレデンシャルを生成
BasicSessionCredentials sessionCredentials = 
					new BasicSessionCredentials(
					credentials.getAccessKeyId(),
					credentials.getSecretAccessKey(),
					credentials.getSessionToken());

// S3クライアントの生成
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
					.withCredentials(
					new AWSStaticCredentialsProvider(sessionCredentials))
					.withRegion(Regions.AP_NORTHEAST_1)
					.build();

上記の様にアカウントBのロールを利用し、一時クレデンシャルを生成します。その後、一時クレデンシャルに含まれるアクセスキーIDやシークレットアクセスキーを使用して接続することで、アカウントAのS3に接続ができます。
 
一時クレデンシャルに含まれるアクセスキーIDやシークレットアクセスキーはあくまで一時的なものの為、アカウントAのアクセスキーIDやシークレットアクセスキーを知らなくてもアカウントAのS3を接続できるようになっています。

S3クライアントを生成後

S3クライアントを生成した後は通常の場合でもクロスアカウントの場合でも同様です。
 
例えばS3にあるファイルをローカルにコピーする場合など、下記のように生成したS3クライアントに対し処理を行う事でファイル名取得やファイル取得などが行えます。

//S3のバケット名、ディレクトリ名を指定してオブジェクトに対するリクエストを生成
String bucketName = "バケット名";
String dirName = "ディレクトリ名";
String localPath = "ローカルディレクトリへのパス";
ListObjectsRequest request = 
	new ListObjectsRequest(bucketName, dirName, null, "/", null);
ObjectListing objList = s3Client.listObjects(request);

//ディレクトリ下にあるすべてのファイルをローカルにコピー
for (S3ObjectSummary obj : objList.getObjectSummaries()) {
	//ファイルの場合のみ実施
	if (obj.getSize() > 0) {
		String fileName = obj.getKey().replace(dirName, "");
		GetObjectRequest reqFile = new GetObjectRequest(bucketName, obj.getKey());
		File file = new File(localPath);
		s3Client.getObject(reqFile, file);
	}
}

まとめ

S3は顧客の持ち物だったりセキュリティの関係など、色々な都合で別アカウントのS3を利用する場面もあるかと思います。
 
今回はS3クライアントの生成についてのみですが、S3の扱い方などについてもご紹介していければと思います。

記事をシェア
MOST VIEWED ARTICLES