Azure SDK for Javaを使ってAzure Storage Blobにアクセスする(3)Java SDK v12を使ったクライアント暗号化

はじめに

先日から書いているAzure SDK for Javaを使ってAzure Storage Blobにアクセスする方法の続きです。今回は、Azure Storage Blobに保存するデータのクライアント暗号化を試したいと思います。

これまでの記事はこちらを。

Azure Storageでの暗号化

以下のドキュメントにあるように、デフォルトではAzure Storageに対してデータを保存するときに暗号化されるとのこと。これは無効化できないようです。

docs.microsoft.com

今回試したいのは、クライアント暗号化というもの。詳細は以下のドキュメントに記載があります。

docs.microsoft.com

Java SDK v12を使ったサンプルは、記事執筆時点でドキュメント内には書かれていませんでしたので、試してみることにしました。

Azure Key Vaultにおけるキーの作成と権限付与

まずはAzure Key Vaultにてキーを作成します。あまり難しいことはなく、ポータルで簡単に作成します。

docs.microsoft.com

作成したら、前回の記事で作成したエンタープライズアプリケーションに対してアクセス制御(IAM)とアクセスポリシーを設定します。

docs.microsoft.com

アクセスポリシーの権限はとりあえず暗号化操作に関するものに対して全てチェックを入れました。

f:id:miyohide:20220410162618j:plain

Javaを使った実装

実装はAzure Storage Blobs Cryptography client library for Javaを使って行います。

azuresdkdocs.blob.core.windows.net

build.gradleに対して関連ライブラリを追記します。Azure Key Vaultでのキー用のcom.azure:azure-security-keyvault-keysのほかcom.azure:azure-storage-blob-cryptographyを追記します。

dependencies {
    implementation platform('com.azure:azure-sdk-bom:1.2.0')
    implementation 'com.azure:azure-storage-blob'
    implementation 'com.azure:azure-security-keyvault-keys'
    implementation 'com.azure:azure-identity'
    implementation 'com.azure:azure-storage-blob-cryptography'
    implementation 'ch.qos.logback:logback-classic:1.2.11'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}

具体的な実装方法については、Azure Storage Blobs Cryptography client library for JavaのREADMEを参考にします。まずAsyncKeyEncryptionKeyを返すメソッドを作成します。

public KeyVaultKey getKeyVaultKey(String keyName) {
    return (new KeyClient()).getKey(keyName);
}

public AsyncKeyEncryptionKey createAsyncKeyEncryptionKey(String keyName) {
    KeyVaultKey key = this.getKeyVaultKey(keyName);
    AsyncKeyEncryptionKey asyncKeyEncryptionKey = new KeyEncryptionKeyClientBuilder()
            .credential(new DefaultAzureCredentialBuilder().build())
            .buildAsyncKeyEncryptionKey(key.getId())
            .block();
    return asyncKeyEncryptionKey;
}

これを使ってEncryptedBlobClientを作成します。

EncryptedBlobClient encryptedBlobClient = new EncryptedBlobClientBuilder()
                .key(this.keyVaultHelper.createAsyncKeyEncryptionKey("Azure Key Vaultのキーの名前"), KeyWrapAlgorithm.RSA_OAEP.toString())
                .credential(new DefaultAzureCredentialBuilder().build())
                .endpoint("Azure Storageのエンドポイント")
                .containerName("コンテナ名")
                .blobName("Blob名")
                .buildEncryptedBlobClient();

keyメソッドのアルゴリズムについてJava Docには書かれていなかったので何を指定すれば分からなかったのですが、今回はKeyWrapAlgorithm.RSA_OAEP.toString()を指定することでうまく動きました。他にもKeyWrapAlgorithm.RSA_OAEP_256.toString()KeyWrapAlgorithm.RSA1_5.toString()を指定してもうまく動きました。以下のドキュメントをみると良いのかもしれません。

docs.microsoft.com

作成したEncryptedBlobClientupdateStringDataメソッドを使ってデータをBlobとして保存します。

encryptedBlobHelper.updateStringData("This is a sample string2");

この状態でAzure Storage Blobを確認します。

f:id:miyohide:20220410170040j:plain

メタデータencryptiondataというのが書かれています。ドキュメントを見るとこれらのメタデータは削除してはいけないようです。

このデータをダウンロードして中身をみてみると、暗号化されているようです。

f:id:miyohide:20220410170840j:plain

EncryptedBlobClientdownloadBlobDataメソッドを使って復号化された状態でファイルがダウンロードできます。

encryptedBlobHelper.downloadBlobData("ファイル名");

ダウンロードしたファイルを見てみると、復号化できているようです。

f:id:miyohide:20220410171306j:plain