Azure SDK for Java からの Storage への接続（認証）について

# Azure SDK for Java からの Storage への接続（認証）について

Azure上にシステムを構築するにあたって、よく使われるのがAzure Storageです。知らない方に説明するとザックリ以下のようなものです。

* BLOB  : テキスト、バイナリなどの大量のオブジェクトデータを格納
* Table : スキーマレスな Key - Value ストア
* Queue : いわゆる FIFO を実現するためのキュー

ここの本題ではないので、詳しく知りたい方は、以下のドキュメントを当たってください

* [Blob (オブジェクト) Storage の概要 - Azure Storage | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-blobs-introduction?WT.mc_id=AZ-MVP-5001265)
* [Table Storage の概要 - Azure のオブジェクト ストレージ | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/tables/table-storage-overview?WT.mc_id=AZ-MVP-5001265)
* [Azure Queue Storage の概要 - Azure Storage | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/queues/storage-queues-introduction?WT.mc_id=AZ-MVP-5001265)

ここでは、Azure Storage SDK を使う前段階の認証について検証をかねて解説したいと思います。他のAzureリソースを使う場合も、同じ認証方法をサポートしているので、ここで説明したような方法が使えると思います。

# 接続文字列

サンプルなどで一般的に扱われるのが、接続文字列によるStorageへの接続です。ポータルの、アクセスキー画面から取得できます。

以下のような形式で、プロトコル、アカウント名、アカウントキー、エンドポイントのサフィックスが定義されています。現在のAzureは、リージョンによって `core.windows.net` を持たない物もあるため、このようにサフィックスを定義することになってます。

```
DefaultEndpointsProtocol=https;AccountName=qiitaazure;AccountKey=xxxxxxxxxx;EndpointSuffix=core.windows.net
```

SDKでは、以下のように `BlobServiceClientBuilder#connectionString()` に 接続文字列を渡してビルドします。

```java
        BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
            .connectionString(connectionString)
            .buildClient();
```

接続文字列をどのように管理するかはここではあまり言及しませんが、マネージドIDを使えば、接続文字列を管理する必要もなくなりますから、開発とか極小規模なアプリ向けでしょうか。KeyVault に格納という話もなくはないのでしょうが、それくらいならマネージドID使いましょう。

# StorageSharedKeyCredential

接続文字列とあまり違わないのですが、共有キーで認証する方法です。`StorageSharedCredential` を使います。実装を見ると接続文字列も内部的には`StorageSharedKeyCredential`を使っています。

```java
        StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);
        BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
            .endpoint(String.format("https://%s.blob.core.windows.net", accountName))
            .credential(credential)
            .buildClient();
```

# TokenCredential インタフェースを使う

`BlobServiceClientBuilder` には、 `public BlobServiceClientBuilder credential(TokenCredential credential)` が定義されており、 `TokenCredential` をインタフェースを実装した様々な認証方式を取ることが出来ます。

リファレンス的には以下を参照すると、色々な具象クラスが定義されいますので、少しかいつまんで説明します。

* [Overview (Azure SDK for Java Reference Documentation)](https://azuresdkdocs.blob.core.windows.net/$web/java/azure-identity/1.2.5/index.html)

## 開発環境下での Credential

開発環境下用に、

* `IntelliJCredential`
* `VisualStudioCodeCredential`
* `AzureCliCredential`

と言った物があります。特定のIDE環境下で認証済の情報を利用してくれるので、開発環境下で使うことができます。例えば、`AzureCliCredential` は、 Azure CLI いわゆる `az` コマンドでの認証に対応します。`az login` でサブスクリプションに接続すると、その認証情報は `~/.azure` に格納されるのですがそれを勝手に使ってくれます。

内部的には  `az account get-access-token --output json --resource https://storage.azure.com` なコマンドを発行してStorageへのアクセスに必要なトークンを取得しています。


コード的には以下です。

```java
AzureCliCredential azureCliCredential = new AzureCliCredentialBuilder().build();
```

## ManagedIdentityCredential

`ManagedIdentityCredential` はマネージドIDを有効にしたWebAppやVMなどで利用できる認証方法です。アカウントキーでの認証が不要になります。

マネージドID全般の話は以下を参照してください。SDKからの利用については、ほぼポータルでの設定話になってしまうので、割愛します。

[Azure リソースのマネージド ID | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/overview?WT.mc_id=AZ-MVP-5001265)

```java
  ManagedIdentityCredential managedIdentityCredential = new ManagedIdentityCredentialBuilder().build();
```

## 最終的には、DefaultAzureCredential を使えば無問題

長々と説明してきましたが、`TokenCredential` を実装したクラスは説明した以外にもいくつかあります。そして、それらの認証方式を全て試してくれるのが `DefaultAzureCredential` です。いちいちいままで紹介した個別のクラスを使う必要はありませんし、ぶっちゃけ、この `DefaultAzureCredential` だけ知っていれば良いレベルなのですが、実際の振る舞いは理解しておいて損は無いと思います（はまるので）。

リファレンスやDocsを見ると説明が書いてあります。

* https://azuresdkdocs.blob.core.windows.net/$web/java/azure-identity/1.2.5/com/azure/identity/DefaultAzureCredential.html
* [Azure でホストされる Java アプリケーションを認証する | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/developer/java/sdk/identity-azure-hosted-auth?WT.mc_id=AZ-MVP-5001265)

コード的には以下の通りです。

```java
        DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
```

JavaDocから抜粋すると、以下の順番で認証を試していってくれます。最終的にどの方法でも認証できないと、失敗となります。

1. EnvironmentCredential
2. ManagedIdentityCredential
3. SharedTokenCacheCredential
4. IntelliJCredential
5. VisualStudioCodeCredential
6. AzureCliCredential

個別の動きについては、リファレンスなりDocsを当たれば良いでしょう。ソースを追いかけるのも面白うと思います。

# まとめ

`DefaultAzureCredential` を使っとけばOKということです。