[Azure] Azure FunctionsからAzure Key Vaultの値を参照する

# 本記事のゴール

今回の記事では、Azure Functionsの構成(環境変数)にAzure Key Vaultから読み出した値を埋め込んでそれを関数内で読み出せるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/3fca6b6e-77c9-e095-0a63-9ec59ca29704.png)


Q .何が嬉しいのか？

- 複数Functionsに同じ環境変数を渡すとき、手入力の必要がなくなり、AzureKeyVaultで一括して管理できる
- DB_PASSWORDなど秘匿情報を見ることができるユーザーを絞ることができる(あまり恩恵は得られないかも)

例えば、自分の別記事である[[Azure] Azure FunctionsからVnet内のRDBを操作する](https://qiita.com/iron-samurai/items/b86777889df16829775d)では、Azure Functionsの構成(環境変数)にDB_PASSWORDをベタガキしていましたが、これでは同じDBにアクセスする別のFunctionsを作成する際に再度手入力をする必要があります。

また、Functionsの構成はFunctionsを触れる人なら誰でも閲覧できます。これをよりアクセスポリシーを細かく設定できるKeyVaultの値に置き換えれば値を知りうる人を制限できます(もっともFunctionsで環境変数をログ出力すれば見れてしまうのでそんなに恩恵はないかも？)

# 準備するもの

- Azure Functions
- Azure Key Vault

# Azure Functionsを作る

1. AzurePortal上でFunctionAppを作成する
    
    [こちら](https://qiita.com/iron-samurai/items/b86777889df16829775d)と同じ流れでコマンドを使ってテンプレートから関数を作成します
    今回はターミナルから実行できるように`HTTP trigger`とします.また、ローカルのターミナルからリクエストを送れるようにauthlevelもanonymousにしておきます
    
    ```bash
    func new --name HttpTrigger --template "HTTP trigger" --authlevel "anonymous"
    ```
    
    パッケージをインストールしておきます
    
    ```bash
    npm i
    ```
    
2. 雛形を修正
    
    まず、変更後にprocess.envを利用するので警告が出ないように以下をインストールしておきます
    
    ```bash
    npm i --save-dev @types/node
    ```
    
    次に、雛形を次のように編集し、読み出した環境変数をログ出力できるようにします
    ※今回は読み取り確認のためにログ出力しますが、実際の開発では、DBのパスワードなどその他重要な情報はログ出力しないでください。Functionsのログに記録されてしまい漏洩のリスクが高まるためです。開発の際は、実際にDBと接続できたかなどの結果を用いて検証を行ってください。
    
    ```tsx
    import { AzureFunction, Context, HttpRequest } from "@azure/functions"
    
    const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
        const valueInKeyVault = process.env.TEST_VALUE;
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: valueInKeyVault
        };
    
    };
    
    export default httpTrigger;
    ```
    
3. 関数をデプロイ
    
    ```bash
    npm run build
    
    func azure functionapp publish ${FunctionsAppの名前}
    ```
    
    以下のような表示が出ればデプロイ完了です！
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/07e0343f-0fc4-e043-49b9-33631aad6982.png)

    

# Azure Key Vaultに値を設定する

1. Azure Portal上にAzure Key Vaultをデプロイ
    
    [Azure Key Vault とは?](https://docs.microsoft.com/ja-jp/azure/key-vault/general/basic-concepts)
    
    参考までに自分の設定を載せておきます
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/dee105a4-14a1-0add-103e-5ff57a2404b1.png)

    
2. KeyVaultに値を登録する
デプロイが完了したらリソースのページに行き、サイドメニューからシークレットを選択します
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/883d8178-88b9-bb7b-b998-00c006341bcc.png)

    
    生成/インポートを押して値を登録します
    今回は、値には適当な文字列として`this_is_value_in_key_vault`を登録します
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/de43a964-42cb-3d36-fdcb-88c8c06437e5.png)



    

# FunctionsとKeyVaultを連携する

ここからFunctionsとKeyVaultを少し行ったり来たりします。

1. FunctionsでオブジェクトIDを作成
まず、サイドメニューからIDを選択し、システム割り当て済みをオンにします。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/35d9a2e0-6f78-88ad-8737-603b877c4c1a.png)

    
    すると以下のようにオブジェクトIDが発行されるのでこれを控えておきます。(KeyVault側で登録するため)
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/49a9c303-f5da-90fc-ca90-8dd88b8a53c7.png)

    
2. Key VaultのアクセスポリシーにFunctionsのオブジェクトIDを登録する
①KeyVaultに移動し、アクセスポリシーの追加をクリックします
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/18f3833e-d2ef-e1f8-7db6-9579c9bc6438.png)

    
    ②追加ページでは各項目は以下のように選択してください
    
    - テンプレートからの構成
    ”シークレットの管理”を選択します。
    - シークレットのアクセス許可
    デフォルトのままでも良いです。が、権限は最小限に絞っておいて損はないので、デフォルトのものから”取得”だけに絞ります.
    - プリンシパルの選択
    関数アプリの名前かオブジェクトIDで検索してプリンシパルを選択します
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/64914cd9-6e17-e40d-1cbc-76f0fceb952f.png)

    
    ③追加後にアクセスポリシートップページで設定を保存する
    アクセスポリシートップで関数アプリが追加されていることを確認したら、忘れずに保存をクリックします。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/ff6a76da-67b1-eba7-0a7f-032942605fb8.png)

    
    ④登録したシークレットのページにいき、シークレット識別子を控えておきます
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/1a0a77bb-dd25-9582-50e2-19a84463e600.png)

    
    1. Functionsの構成に環境変数を設定します
    次のような形式で値を設定します
        
        ```
        @Microsoft.KeyVault(SecretUri=xxxxxxxxx)
        ```
        
        [Key Vault 参照を使用する - Azure App Service](https://docs.microsoft.com/ja-jp/azure/app-service/app-service-key-vault-references)
        
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/ebb12582-88f1-1274-90bd-768d620412eb.png)

        
        追加後は忘れずに保存を行います
        
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/e320408b-eeeb-a350-745c-4d9a5244a6a1.png)

        
    
    登録した値の右側に”キーコンテナーの参照”と表示されていたら成功です！
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/63cfb43e-fb09-23bc-80b3-5397ee600731.png)

    

# 動作確認

デプロイしたFunctionsにターミナルからcurlでリクエストを叩いてみます。
responseにKeyVaultに設定した値が表示されれば成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/599e9233-b9a8-e4b9-c938-f4297d45b8b1.png)


# 終わりに

これでAzureFunctionsからKeyVaultの値を読み出せるようになりました。DBのパスワードなどセキュアな情報を利用する場合に役立ててください。