LoginSignup
2
3

More than 5 years have passed since last update.

AWS SDK for Javaを使ってS3にアップロードするデータを暗号化/SSE-KMS編

Last updated at Posted at 2017-04-06

AWS SDK for JavaでAmazonS3ClientBuilderを使ってS3にデータをアップロード/ダウンロード/一括削除する のアップロードを、サーバーサイド暗号化に対応させる方法です。
結論を先に書くと、AmazonS3ClientBuilderを使う場合もAmazonS3Clientのときと同じ記述でOKです。

なお、S3のデータ暗号化の方法には色々な種類がありますが、ここでは「SSE-KMS」を取り上げます。

0. S3のデータ暗号化の種類について

大きく分けて、サーバー側の暗号化(SSE)とクライアント側の暗号化(CSE)があります。

前者は、クライアントから送信したデータをサーバ側で受け取ってから暗号化してストレージに保存する方法、後者はクライアントから送信する前にデータを暗号化してサーバ側に送信する方法です。
但し、サーバ側の暗号化を使う際にはエンドポイントへの接続にHTTPSを使って通信経路をSSL/TLSで暗号化する必要があるため、いずれにせよ生データがインターネット上を流れるわけではありません。

それぞれ、さらにいくつかの方法に分かれますが、CSEについてはここでは取り上げません。

  • S3で管理された暗号化キーを使うサーバ側暗号化(SSE-S3)
  • AWS KMSで管理された暗号化キーを使うサーバ側暗号化(SSE-KMS)
  • ユーザが用意した暗号化キーを使うサーバ側暗号化(SSE-C)

これらのうち、今回使うSSE-KMSでは、さらに、

  • デフォルトの暗号化キー(無料で自動発行されるキー)を使う方法
  • ユーザが明示的に発行したカスタマーマスターキー(CMK)を使う方法

があります。

1. 準備/CMK(キー)の発行とS3バケットへのポリシー設定(必要な場合のみ)

CMKを明示的に発行する場合は、IAMの「暗号化キー」のメニューを使います。
s3_enc_1.jpg
上の画面で、①(ARN)はバケットポリシー設定の際に、②(キーID)はJavaのコードで暗号化キーIDを指定する際に使います。

なお、S3のアクセスに使うユーザがこのキーを使用できるよう、権限を付与しておくのを忘れないようにしてください。
s3_enc_2.jpg

CMKを明示的に発行せず、デフォルトの暗号化キーを使う場合は、これらの作業は不要です。

続いて、アップロード時に暗号化を強制したい場合は、バケットポリシーを設定します。
s3_enc_3.jpg
使用する暗号化キーを限定する場合は、13行目末尾の「,」および14行目を記述します。限定しない(暗号化のみ強制する)場合や、デフォルトの暗号化キーを使う場合は、この記述は不要です。

2. Javaのコードを変更する

先の記事のサンプルコードを修正します。
なお、「ダウンロード」以降に変更はありません(ダウンロード時には暗号化の指定は不要です)。

S3Access.java(前半部分のみ)
package s3test;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.DeleteObjectsResult;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;

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】※②の部分を入れる";

    //--------------------------------------------------
    // アップロード
    //--------------------------------------------------
    public void putObject(String bucketName, String objectKey, int objectSize, InputStream is) throws Exception {

        // クライアント生成
        AmazonS3 client = getClient(bucketName);

        ObjectMetadata metadata = new ObjectMetadata();
        // 念のためサイズだけセットしておく(不整合ならException)
        metadata.setContentLength(objectSize);

        // アップロード
        PutObjectRequest putRequest = new PutObjectRequest(bucketName, objectKey, is, metadata)
                                    .withSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(KMS_KEY_ID));
        client.putObject(putRequest);
        client.putObject(bucketName, objectKey, is, metadata);
    }

デフォルトの暗号化キーを使う場合は、PutObjectRequest のところで引数のない .withSSEAwsKeyManagementParams() を記述します。

3. 注意点

先に軽く説明した暗号化の種類(方法)ごとに、アップロード時リクエストヘッダに記述される内容が異なります。
そのため、バケットポリシーで暗号化を強制する場合、暗号化の種類に合った記述をする必要があります。

SSE-S3を使う場合は、以下を参考にしてください。

Amazon S3 で管理された暗号化キーによるサーバー側の暗号化 (SSE-S3) を使用したデータの保護
AWS SDK for Java を使用したサーバー側の暗号化の指定

バケットポリシーとJavaコードの対応を間違えると、アップロード時エラーになります。

SSE-S3を使う方法とSSE-KMSでデフォルトの暗号化キーを使う方法は別物ですので、混同しないよう注意してください。

【2017.7.6追記】
認証にアクセスキーを使うのはセキュアではないので、以下の記事でEC2 IAM Roleを使う形への変更方法を示しています。

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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3