Java on Azure におけるアプリケーション設定の保存方法について

# Java on Azure におけるアプリケーションの設定について

クラウドでアプリケーションの構成設定（いわゆる、コンフィグレーション）をどこに保持しておくのかというのは、以外と悩ましい問題です。アプリケーションに埋め込むと、変更があったときに再デプロイを余儀なくされたり、パスワードを含む接続文字列などをどう管理すればよいのかだったり。

このあたりの構成をAzureではどのように設定できるのか、Spring Bootアプリケーション + WebApps にデプロイする前提で考えていきたいと思います。

# どこに保存するか?

アプリケーションの構成設定を保存する方法として、いくつか上げると、以下のような感じになると思います。

* ハードコーディング
* コンフィグレーションファイルに設定
* WebApps の構成に設定
* App Configration に設定
* Key Vault に設定

ハードコーディングは論外として、それ以外について見ていきたいと思います。

# コンフィグレーションファイルに設定

Spring boot ですと、 `application.properties` だったり、 `application.yml` などに構成を設定できます。ただし、jarに含まれてしまうので、なにか変更したい場合は再デプロイになってしまうでしょう。また、開発環境と運用環境の切り替えなどは、プロファイル機能があるので、`application-dev.yml` だったり、`application-prod.yml` だったりとファイルを切り替えることができます。

とはいえ、パスワードやキーなど秘匿すべき情報などをファイルにべた書するのは、秘密保持の観点からあまりよろしくないでしょう。

## WebApps の構成に設定

WebApps には「設定」という項目があり、Key Value の形式でアプリケーションの設定をすることができます。ここで、設定した値は、最終的に環境変数に設定されます。したがって、環境変数から値を読み出すことが出来れば、WebApp で設定した値を利用するとができるわけです。

Spring Bootですと、 [Externalized Configuraiton](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#boot-features-external-config) で（優先順位の問題はありますが）環境変数から読み出してくれます。ちなみに、プロパティファイル ＜ 環境変数なので、環境変数に設定しあ値が上書きされて読み込まれます。

以下のようなConfigとAPIを用意した上で試してみしょう。


```java
@Configuration
@ConfigurationProperties(prefix = "myapp")
public class MyConfig {

    private String message;

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
```

```java
@RestController
public class ApiController {

    private MyConfig config;

    public ApiController(MyConfig config) {
        this.config = config;
    }

    @GetMapping("/hello")
    public String hello() {
        return config.getMessage();
    }
}
```

WebAppsに設定をしてみます。

![2021-05-03 13_08_00-config-sample-1620013095057 - Microsoft Azure および他 5 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/3f3b5046-d113-a01c-e5bb-d5bd9e29012b.png)


curl で叩けば、設定されあ値が表示されていることが確認できるでしょう。

```sh
$ curl https://config-sample-1620013095057.azurewebsites.net/hello
webapps configuration
```

まとめますと、

+ WebApps で構成設定ができ、それらは環境変数に設定される
+ 環境変数から読み出して構成設定してくれるフレームワークがあれば、透過的に利用可能
+ Azureポータルにアクセス出来るひとには、情報を読み取られる可能性がある

あたりを考慮してください。

ちなみに、WebAppsでは、接続文字列だけ特別扱いして構成できるようになっています。これは、環境変数に特殊なプレフィックスが付加されるので、読み取るときは注意が必要です。 SQL Azure ですと `SQLAZURECONNSTR_` になります。フレームワークによっては相性が悪いかもしれません。

## App Configuration に設定

Azure には、アプリケーション設定を行う専用のサービスとしてApp Configrationがあります。

[Azure App Configuration とは | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-app-configuration/overview?WT.mc_id=AZ-MVP-5001265)

先ほどの WebApps の構成では、WebApps 単体からしか参照できません。複数のアプリケーションから設定を一元管理したい場合などに有効でしょう。

App Configuration には、 Spring Cloud 用 ライブラリが用意されているので、それを使うと簡単でしょう。

最新版は、以下にあります。

https://mvnrepository.com/artifact/com.microsoft.azure/spring-cloud-azure-appconfiguration-config/1.3.0

使い方としては、`pom.xml` に以下の設定をしておくと、特になにもしなくても、外部構成先とアクセスしてくれます。とはいえ、App Configration 自身への接続情報が必要なのですが、そこは Managed ID（※） を利用すれば、それさえ不要となります。

```xml
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>spring-cloud-azure-appconfiguration-config</artifactId>
    <version>1.3.0</version>
</dependency>
```

（※） Managed ID は別途記事化したいと思います。

同じようにクラスを定義します。

```java
@ConfigurationProperties(prefix = "appconfig")
public class AppConfig {

    private String message;

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
```

App Configuration に設定するにはキー値を `/application/appconfig.messsge` と プレフィックスを付ける必要があります。同じようにAPIを定義して呼び出せば値が取得できることを確認できるでしょう。

![2021-05-03 16_39_43-sampleconfig - Microsoft Azure および他 6 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/f405d3ab-ab95-cc13-23f5-585e6be35568.png)


```sh
$ curl http://localhost:8080/hello2
App configuration message.
```

簡単にまとめますと、

+ App Configurtion は、アプリケーション構成設定専用のサービス
+ 複数のアプリケーションから共有できる
+ これ以外にも、機能フラグを管理する機能があったり、ラベルをつけて、開発・運用などを分けて定義できる

などがあります。フレームワークレベルでどの程度の機能まで対応しているかは未検証ですのでありからず。

## Key Vault に設定

Key Vault とは、アプリケーションが使用する証明書や暗号化キー、パスワード証明書などを安全に管理するためのサービスです。App Configuration と同じように Spring Boot 用スターターが用意されており、簡単にアクセス可能です。

https://mvnrepository.com/artifact/com.microsoft.azure/azure-keyvault-secrets-spring-boot-starter/2.3.5


```xml
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-keyvault-secrets-spring-boot-starter</artifactId>
    <version>2.3.5</version>
    <scope>runtime</scope>
</dependency>
```

App Configuration と同じく依存関係を設定しておきさえすれば（接続文字列の問題はありますが）、外部ストアとして透過的にアクセスできます。より厳密に管理したいときは、Key Vault をお勧めします。

Key Vault に設定できるキー名はには、ドットを含めることはできないので、ダッシュあたりで代替する必要が合ったと思います。

# まとめ

アプリケーションの構成設定をどこに保存するかは、ケースによると思ってます。小規模なアプリなら、構成設定ファイルでもか特に問題ないでしょうが、中規模、大規模になるにしたがい、厳密に管理する必要が出てくると思いますので、要件と相談しながら、なにをどこで管理するか設計しておきましょう。ライブラリが対応していますので、どこに格納されていても、ちゃんとアクセス出来ると思います。そういうところは、自分で実装するのではなくフレームワークにお任せしたい部分ではありますが、直接アクセスする場合にはSDKが使えます。

さて結局、今回 App Configuration にアクセスするにしても、Key Vault にアクセスするにしても、そもそもそのサービスにアクセスするためのキーをどうするのか？と言った問題は残ったままです。そのあたりは、Azure のManaged ID を使うとスッキリ解決できるのですが、そのあたりは次回以降に試してみたいと思います。