EC2 IAM Role環境でSSE-KMS暗号化を使ってS3バケットにアクセスする（AWS SDK for Java）

先日、とあるイベントに参加して、

**「そういえば、暗号化してS3バケットにアップロードする記事を書いたのに、認証にアクセスキーを使ってた！」**（セキュリティ・ベストプラクティスに沿ってない）

ということに気づいたので、補足することにしました。

**[AWS SDK for Javaを使ってS3にアップロードするデータを暗号化／SSE-KMS編](http://qiita.com/hmatsu47/items/37308f6938c6fe351d38)** の続きです。

※手順は全然難しくないのですが、私はCMKのキーユーザーにIAM Roleを割り当てるのを忘れて、小一時間悩みました。その場合でも、返ってくるHTTPレスポンスコードが「403」（Access Denied）なので、単純にS3の認証／認可が通らないケースと区別が付きません…。

# 1. EC2用のIAM Roleを設定する

・IAMで**[新しいロールの作成]**をクリックします。
![01_iam1.png](https://qiita-image-store.s3.amazonaws.com/0/123899/11a86815-070e-5e80-b7f2-8675ad647eb2.png)

・**「Amazon EC2」**を選択します。
![02_iam2.png](https://qiita-image-store.s3.amazonaws.com/0/123899/c4d3262f-1886-84f0-7c31-5b06faae5b7b.png)

・**「AmazonS3FullAccess」**にチェックを入れて**[次のステップ]**をクリックします。
![03_iam3.png](https://qiita-image-store.s3.amazonaws.com/0/123899/b85b20fd-f7aa-a1c7-e8a2-cb123eb8c9dd.png)

・**ロール名**を入れて**[ロールの作成]**をクリックします。
![04_iam4.png](https://qiita-image-store.s3.amazonaws.com/0/123899/664d3473-3af3-60cb-176e-d3e19c61366a.png)

・S3暗号化に使う**暗号化キー**を選択します。
![05_kms1.png](https://qiita-image-store.s3.amazonaws.com/0/123899/9e446d95-57f3-be8c-73a8-b3585ba96101.png)

・**キーユーザー**の**[追加]**をクリックします。
![06_kms2.png](https://qiita-image-store.s3.amazonaws.com/0/123899/d1c93999-f7b8-6666-214c-0a5dd71dc959.png)

・**作成したIAMロール**を選択して**[アタッチ]**をクリックします。
![07_kms3.png](https://qiita-image-store.s3.amazonaws.com/0/123899/a80381b7-b61a-1acd-51a8-3f16795eaa26.png)

・作成したIAMロールを、**対象のEC2インスタンス**に割り当てます。
![08_ec2_1.png](https://qiita-image-store.s3.amazonaws.com/0/123899/94e6607e-9715-989c-3bc2-4ddde722e4b3.png)

・**IAMロール名**を入力／選択して**[適用]**をクリックします。
![09_ec2_2.png](https://qiita-image-store.s3.amazonaws.com/0/123899/adf5d6ca-3f5f-d559-6145-78d9533f6765.png)

・処理が成功したら、対象のEC2インスタンスを開始（起動）し、IAM Roleが適用されていることを確認します。
![11_ec2_4.png](https://qiita-image-store.s3.amazonaws.com/0/123899/64c5823e-edb4-ea98-8d96-5ffafffbcd87.png)

# 2. Javaコードの変更

Javaコードについては、単純にcredentialsの指定を外すだけでOKです。

```Java:変更点
public class S3Access {

    private static final String ENDPOINT_URL = "https://s3-ap-northeast-1.amazonaws.com";
    private static final String REGION       = "ap-northeast-1";
//  private static final String ACCESS_KEY   = "【アクセスキー】";
//  private static final String SECRET_KEY   = "【シークレットキー】";
    private static final String KMS_KEY_ID   = "【KMSキーID】";

(中略)

    //--------------------------------------------------
    // クライアント生成
    //--------------------------------------------------
    private AmazonS3 getClient(String bucketName) throws Exception {

//      // 認証情報
//      AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);

        // クライアント設定
        ClientConfiguration clientConfig = new ClientConfiguration();
        clientConfig.setProtocol(Protocol.HTTPS);  // プロトコル
        clientConfig.setConnectionTimeout(10000);   // 接続タイムアウト(ms) 

        // エンドポイント設定
        EndpointConfiguration endpointConfiguration = new EndpointConfiguration(ENDPOINT_URL, REGION);

        // クライアント生成
        AmazonS3 client = AmazonS3ClientBuilder.standard()
//                      .withCredentials(new AWSStaticCredentialsProvider(credentials))
                        .withClientConfiguration(clientConfig)
                        .withEndpointConfiguration(endpointConfiguration).build();

(後略)
```

**行頭の「//」でコメントアウトしている行を削除**します。

※すでにコード内に認証情報を記述しない形にしていて、環境変数や実行ユーザのホームディレクトリ（Amazon Linuxにyumでtomcat8をパッケージインストールした場合は /usr/share/tomcat8/）直下に「.aws」ディレクトリを作成し、「credentials」ファイルにアクセスキーを記述して使用していた場合は、それらを削除すると、IAM Roleの認証／資格情報を使用することが可能です。