ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

Function App から全ての接続文字列から解放してみた (かった)

f:id:horihiro:20210529170353p:plain

Microsoft Build 2021

先週やってました。

が、App Service や Azure Functions 関連のセッションは少なかったですね。。。
アップデートとしてはこのあたりです。

  • GA
    • App Service Managed Certificates
    • Azure Static Web Apps
    • PowerShell Durable Functions
  • Preview
    • Durable Functions backend providers (Microsoft SQL server / Netherite)
    • OpenAPI extension for Azure Functions
    • Azure Application Services on Kubernetes with Azure Arc

ASE v3 あたりは GA に向けての機能整理も進んでいるようなのでセッションあるのかな、とは思っていたのですけどね。
Azure Application Services のインパクトが大きかった感じ。

本題

Build とは全く関係ありません。

Azure SDK が更新されて、Blob Storage、Queue Storage、Event Hubs、Service Bus、Event Grid への接続で、接続文字列を使用しないマネージド ID / クライアント シークレット / クライアント証明書での接続がサポートされました (ベータ版です)。

devblogs.microsoft.com

Function App でも WebJobs Extension を介してこれが使えるらいしいので、アプリケーション設定から接続文字列が一掃できるのでは、という期待を胸に試してみました。

実験

今回は Timer トリガー関数に Queue ストレージの出力バインディングを足したもので試してみます。
なので、本来は Timer トリガーで使うアプリケーション設定 AzureWebJobsStorage と、Queue ストレージの出力バインディング用アプリケーション設定、これら 2 つのアプリケーション設定で接続文字列を使っているはずです。

この関数が接続文字列無しで、マネージド ID を使って問題なく動作するかを試してみました。

デプロイする関数コードと function.json

まずは関数コード。

module.exports = async function (context, myTimer) {
    var timeStamp = new Date().toISOString();
    
    if (myTimer.isPastDue)
    {
        context.log('JavaScript is running late!');
    }
    context.bindings.outputQueueItem = {datetime: new Date()};
    context.log('JavaScript timer trigger function ran!', timeStamp);   
};

VScode拡張機能が作ってくれるテンプレートに、Queue ストレージへの出力バインディング

    context.bindings.outputQueueItem = {datetime: new Date()};

の 1 行を足しただけです。

次に function.json

{
  "bindings": [
    {
      "name": "myTimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 * * * * *"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "outputQueueItem",
      "queueName": "outqueue",
      "connection": "withoutConnectionString_STORAGE"
    }
  ]
}

上半分は Timer トリガーの設定、下半分が Queue の出力バインディングです。
本来は connection に指定した名称のアプリケーション設定に接続文字列を格納しているはずです。

ここはほぼテンプレ通りです。

ベータ版 WebJobs Extension の追加

ベータ版 WebJobs Extension を追加するため host.json にはひと手間加えます。

host.json に Extension Bundle (拡張機能一式) に関する記述があれば、それをを削除して Extension Bundle のロードをやめます。
これは、この Extension Bundle の設定があると、この後のベータ版の WebJobs Extension を追加できないためです。

f:id:horihiro:20210529141120p:plain
# 選択部分を削除。

次に、ターミナルで下記コマンドを実行して、(Blob と Queue を試したいので) Storage 用 の WebJobs Extension の最新ベータ版を改めて入れます。

func extensions install --package Microsoft.Azure.WebJobs.Extensions.Storage --version 5.0.0-beta.4

まだデプロイしません。

マネージド ID の有効化

今度はデプロイ先になる Azure 側の事前設定をします。

Function App*1Indentity ブレードでポチっとやるだけです。
f:id:horihiro:20210529155950p:plain

RBAC 設定

Storage Account (AzureWebJobsStorage と Queue バインディングでの出力先) の Access Control (IAM) ブレードに移動し、上で有効化したマネージド ID に対して、Storage Account のデータ操作に関する権限を与えます。
f:id:horihiro:20210529160212p:plain

AzureWebJobsStorage 設定については Blob ストレージを操作するので Storage Blob Data Contributor 、あと出力バインディングでの Queue ストレージに対する操作 (Queue 自体の作成とメッセージ追加) のために Storage Queue Data Contributor を与えています。

今回 AzureWebJobsStorage と Queue バインディングで使う Storage Account を同じものにしているので、一つの Storage Account に二つのロール割り当てをしました。 もしこれらが別の Storage Account だったり、バインディングやトリガーで Event Hubs や Service Bus を使う場合は、それらのリソースの Access Control (IAM) ブレードにて、マネージド ID に対する適切なロールを割り当てましょう。

アプリケーション設定の変更

アプリケーション設定の名称と値を変えます。

こちらが変更前の設定。
# フィルター初めて使った

f:id:horihiro:20210529161117p:plain
AzureWebJobsStorage と Queue バインディング用アプリケーション設定 withoutConnectionString_STORAGE ( function.jsonconnection で指定) 、それぞれに接続文字列が入っています。

これらのアプリケーション設定から変更します。
f:id:horihiro:20210529161908p:plain

AzureWebJobsStorageAzureWebJobsStorage__accountName に変更し、その値は Storage Account 名をズバリ書きます。

バインディング用の設定 withoutConnectionString_STORAGEwithoutConnectionString_STORAGE__queueServiceUri に変更し、値は https://${accountName}.queue.core.windows.net という書式で指定します。

こちらにはもっといろいろ設定名が書いてありますが、マネージド ID を使っているせいか、特に不要のようです。

最後にデプロイ

関数コードをデプロイすると、AzureWebJobsStorage や接続文字列がなくても、Timer トリガーの関数が毎分実行され、Queue にメッセージが追加されるはずです。

めでたしめでたし。

ちなみに

従量課金プランと Premium プランの Function App の場合、D:\home *2 としてマウントしているファイル/フォルダーの実態が File ストレージ内にあり、その設定には File ストレージへの接続文字列を格納した WEBSITE_CONTENTAZUREFILECONNECTIONSTRING というアプリケーション設定が必要です。

今回のベータ版は Blob と Queue に関する更新で、File ストレージについては未対応なようなので、File ストレージを使うこれらのプランでは、接続文字列を一掃することができませんでした。悔しい。
あと Application Insights への接続文字列も残ってました。

*1:個々のリソースが Function App、サービス名が Azure Functions という使い分けをしています。

*2:場合によっては C:\home