チュートリアル: シークレットではなく ID を使用して Azure サービスに接続する関数アプリを作成する
このチュートリアルでは、可能な限り、シークレットや接続文字列ではなく Microsoft Entra の ID を使用する関数アプリを構成する方法について説明します。 ID を使用すると、機密シークレットが誤って漏えいするのを防ぐのに役立ち、データへのアクセス方法をより詳細に可視化できます。 ID ベースの接続の詳細については、「ID ベースの接続を構成する」を参照してください。
ここで示す手順は一般にすべての言語で動作しますが、このチュートリアルで現在サポートされているのは特に Windows 上の C# クラス ライブラリ関数です。
このチュートリアルでは、以下の内容を学習します。
- ARM テンプレートを使用して Azure で関数アプリを作成する
- 関数アプリでシステム割り当てとユーザー割り当ての両方のマネージド ID を有効にする
- 他のリソースへのアクセス許可を付与するロールの割り当てを作成する
- ID に置き換えることができないシークレットを Azure Key Vault に移動する
- マネージド ID を使用して既定のホスト ストレージに接続するようにアプリを構成する
このチュートリアルを完了した後は、[トリガーとバインドでシークレットではなく ID ベースの接続を使用する]方法が示されている、後続のチュートリアルを行う必要があります。
前提条件
アクティブなサブスクリプションが含まれる Azure アカウント。 無料でアカウントを作成できます。
Azure Functions Core Tools バージョン 4.x。
ID を使用する理由
シークレットと資格情報の管理は、あらゆる規模のチームに共通する課題です。 シークレットは、盗難や偶発的な露見から保護する必要があり、定期的にローテーションすることが必要な場合があります。 多くの Azure サービスでは、代わりに Microsoft Entra ID の ID を使用してクライアントの認証を行い、アクセス許可を調べて迅速に変更したり取り消したりすることができます。 これにより、より少ない運用オーバーヘッドで、アプリケーションのセキュリティの制御を強化できます。 ID は、アプリケーションの開発者などの人間のユーザーの場合も、マネージド ID が設定された Azure で実行されるアプリケーションの場合もあります。
一部のサービスでは Microsoft Entra 認証がサポートされていないため、アプリケーションでは特定のケースでいまだにシークレットが必要になる場合があります。 ただし、これらのシークレットは Azure Key Vault に格納できます。これにより、シークレットの管理ライフサイクルを簡素化できます。 キー コンテナーへのアクセスも、ID で制御されます。
可能な場合はシークレットではなく ID を使い、それができないときは Key Vault を使う方法を理解すると、リスクを軽減し、運用のオーバーヘッドを減らし、一般にアプリケーションのセキュリティ態勢を向上させることができます。
必要なシークレットに Key Vault を使用する関数アプリを作成する
Azure Files は、サーバー メッセージ ブロック (SMB) ファイル共有用の Microsoft Entra 認証がまだサポートされていないサービスの例です。 Azure Files は、Premium プランと従量課金プランでの Windows のデプロイに対する既定のファイル システムです。 Azure Files を完全に削除することはできますが、それによって望ましくない制限が発生する場合があります。 代わりに、Azure Files の接続文字列を Azure Key Vault に移動します。 そうすることで、ID によって制御されるアクセスを使用して一元的に管理されます。
Azure Key Vault を作成する
まず、シークレットを格納するキー コンテナーが必要になります。 コンテナーからシークレットを読み取ることができるユーザーを決定するために、Azure ロールベースのアクセス制御 (RBAC) を使用するように、それを構成します。
Azure portal で、 [リソースの作成] (+) を選びます。
[リソースの作成] ページで、[セキュリティ]>[Key Vault] を選びます。
[基本] ページで、下の表を使用してキー コンテナーを構成します。
オプション 推奨値 説明 サブスクリプション 該当するサブスクリプション この新しい関数アプリが作成されるサブスクリプション。 リソース グループ myResourceGroup 関数アプリを作成する新しいリソース グループの名前。 キー コンテナー名 グローバルに一意の名前 新しいキー コンテナーを識別する名前。 コンテナー名に使用できるのは英数字とダッシュのみで、数字で始めることはできません。 価格レベル Standard 課金のオプション。 このチュートリアルには Standard で十分です。 リージョン 優先リージョン ユーザー、または関数がアクセスする他のサービスに近いリージョンを選択します。 [回復オプション] セクションでは、既定の選択をそのまま使用します。
後で使用するために、使用した名前をメモしておきます。
[次へ: アクセス ポリシー] を選択して、[アクセス ポリシー] タブに移動します。
[アクセス許可モデル] で、 [Azure ロールベースのアクセス制御] を選びます
[Review + create](レビュー + 作成) を選択します。 構成を確認し、[作成] を選択します。
アプリの ID とアクセス許可を設定する
Azure Key Vault を使うには、シークレットを読み取るためのアクセス許可を付与できる ID がアプリに必要です。 このアプリでは、アプリが作成される前であってもアクセス許可を設定できるように、ユーザー割り当ての ID を使います。 Azure Functions のマネージド ID の詳細については、「Azure Functions でマネージド ID を使用する方法」を参照してください。
Azure portal で、 [リソースの作成] (+) を選びます。
[リソースの作成] ページで、[ID]>[ユーザー割り当てマネージド ID] を選びます。
[基本] ページで、下の表を使用して ID を構成します。
オプション 推奨値 説明 サブスクリプション 該当するサブスクリプション この新しい関数アプリが作成されるサブスクリプション。 リソース グループ myResourceGroup 関数アプリを作成する新しいリソース グループの名前。 リージョン 優先リージョン ユーザー、または関数がアクセスする他のサービスに近いリージョンを選択します。 名前 グローバルに一意の名前 新しいユーザー割り当て ID を識別する名前。 [Review + create](レビュー + 作成) を選択します。 構成を確認し、[作成] を選択します。
ID が作成されたら、ポータルでそれに移動します。 [プロパティ] を選び、後で必要になるので [リソース ID] をメモしておきます。
[Azure ロールの割り当て] を選び、[ロールの割り当てを追加 (プレビュー)] を選びます。
[ロールの割り当てを追加 (プレビュー)] ページでは、次の表に示すオプションを使用します。
オプション 推奨値 説明 スコープ Key Vault スコープは、ロールの割り当てが適用される一連のリソースです。 スコープには、下位のレベルで継承されるレベルがあります。 たとえば、サブスクリプション スコープを選ぶと、そのロールの割り当ては、サブスクリプション内のすべてのリソース グループとリソースに適用されます。 サブスクリプション 該当するサブスクリプション この新しい関数アプリが作成されるサブスクリプション。 リソース 自分のキー コンテナー 前に作成したキー コンテナー。 ロール Key Vault Secrets User ロールは、付与されているアクセス許可のコレクションです。 キー コンテナー シークレット ユーザーでは、コンテナーからシークレット値を読み取るためのアクセス許可が ID に付与されます。 ** [保存]** を選択します。 ID のロール割り当て一覧を更新したとき、ロールが表示されるまでに 1 から 2 分かかることがあります。
その ID で、キー コンテナーに格納されているシークレットを読み取ることができるようになります。 このチュートリアルで後ほど、さまざまな目的のロール割り当てをさらに追加します。
関数アプリを作成するためのテンプレートを生成する
関数アプリを作成するためのポータル エクスペリエンスは Azure Key Vault とやりとりしないため、Azure Resource Manager テンプレートを生成して編集する必要があります。 その後、このテンプレートを使って、キー コンテナーの Azure Files 接続文字列を参照する関数アプリを作成できます。
重要
ARM テンプレートを編集するまでは、関数アプリを作成しないでください。 Azure Files の構成は、アプリの作成時に設定する必要があります。
Azure portal で、 [リソースの作成] (+) を選びます。
[リソースの作成] ページで、[コンピューティング]>[関数アプリ] を選びます。
[基本] ページで、下の表を使用して関数アプリを構成します。
オプション 推奨値 説明 サブスクリプション 該当するサブスクリプション この新しい関数アプリが作成されるサブスクリプション。 リソース グループ myResourceGroup 関数アプリを作成する新しいリソース グループの名前。 関数アプリ名 グローバルに一意の名前 新しい関数アプリを識別する名前。 有効な文字は、 a-z
(大文字と小文字の区別をしない)、0-9
、および-
です。発行 コード コード ファイルまたは Docker コンテナーの発行を選択します。 ランタイム スタック .NET このチュートリアルでは、.NET を使用します。 リージョン 優先リージョン ユーザー、または関数がアクセスする他のサービスに近いリージョンを選択します。 [Review + create](レビュー + 作成) を選択します。 このアプリでは、 [ホスティング] ページと [監視] ページについては既定値を使います。 生成する ARM テンプレートに含まれている既定のオプションを確認します。
ここで関数アプリを作成するのではなく、 [次へ] ボタンの右側にある [Automation のテンプレートをダウンロードする] を選びます。
テンプレート ページで [デプロイ] を選び、[カスタム デプロイ] ページで [テンプレートの編集] を選びます。
テンプレートの編集
次に、テンプレートを編集して、Key Vault に Azure Files 接続文字列を格納し、関数アプリでそれを参照できるようにします。 続ける前に、これまでのセクションで出てきた次の値がわかっていることを確認します。
- ユーザー割り当て ID のリソース ID
- キー コンテナーの名前
Note
自動化のための完全なテンプレートを作成する場合は、適切な dependsOn
句を使って、ID とロール割り当てのリソースの定義を含める必要があります。 これにより、ポータルを使用していたこれまでの手順が置き換えられます。 Azure Resource Manager のガイダンスと各サービスのドキュメントをご覧ください。
エディターで、
resources
配列の開始位置を見つけます。 関数アプリの定義の前に、Azure Files の接続文字列を Key Vault に格納する次のセクションを追加します。 "VAULT_NAME" は、実際のキー コンテナーの名前に置き換えます。{ "type": "Microsoft.KeyVault/vaults/secrets", "apiVersion": "2016-10-01", "name": "VAULT_NAME/azurefilesconnectionstring", "properties": { "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]" }, "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]" ] },
関数アプリ リソースの定義 (
type
がMicrosoft.Web/sites
に設定されているもの) で、Microsoft.KeyVault/vaults/VAULT_NAME/secrets/azurefilesconnectionstring
をdependsOn
配列に追加します。 ここでも、"VAULT_NAME" は、実際のキー コンテナーの名前に置き換えます。 これにより、シークレットが定義される前にアプリが作成されるのを防ぐことができます。dependsOn
配列は、次の例のようになります。{ "type": "Microsoft.Web/sites", "apiVersion": "2018-11-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": null, "dependsOn": [ "microsoft.insights/components/idcxntut", "Microsoft.KeyVault/vaults/VAULT_NAME/secrets/azurefilesconnectionstring", "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]", "[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]" ], // ... }
次の例の
identity
ブロックを、関数アプリ リソースの定義に追加します。 "IDENTITY_RESOURCE_ID" は、ユーザー割り当て ID のリソース ID に置き換えます。{ "apiVersion": "2018-11-01", "name": "[parameters('name')]", "type": "Microsoft.Web/sites", "kind": "functionapp", "location": "[parameters('location')]", "identity": { "type": "SystemAssigned,UserAssigned", "userAssignedIdentities": { "IDENTITY_RESOURCE_ID": {} } }, "tags": null, // ... }
また、この
identity
ブロックにより、このチュートリアルで後ほど使用するシステム割り当て ID も設定されます。次の例のように、関数アプリの
properties
オブジェクトにkeyVaultReferenceIdentity
プロパティを追加します。 "IDENTITY_RESOURCE_ID" は、ユーザー割り当て ID のリソース ID に置き換えます。{ // ... "properties": { "name": "[parameters('name')]", "keyVaultReferenceIdentity": "IDENTITY_RESOURCE_ID", // ... } }
この構成は、アプリに複数のユーザー割り当て ID が構成されている可能性があるため必要です。 ユーザー割り当て ID を使用する場合は、必ず ID で指定する必要があります。 システム割り当て ID は、この方法で指定する必要はありません。アプリが持てるのは 1 つだけだからです。 マネージド ID を使う多くの機能では、既定でシステム割り当て ID を使う必要があるものと想定されています。
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
のアプリケーション設定が定義されている JSON オブジェクトを見つけます。次の例のようになっているはずです。{ "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]" },
次の例に示すように、
value
フィールドをシークレットへの参照に置き換えます。 "VAULT_NAME" は、実際のキー コンテナーの名前に置き換えます。{ "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", "value": "[concat('@Microsoft.KeyVault(SecretUri=', reference(resourceId('Microsoft.KeyVault/vaults/secrets', 'VAULT_NAME', 'azurefilesconnectionstring')).secretUri, ')')]" },
[保存] を選んで、更新した ARM テンプレートを保存します。
変更したテンプレートをデプロイする
リソース グループなど、作成したオプションが正しいことを確認し、 [確認および作成] を選びます。
テンプレートが検証されたら、 [ストレージ アカウント名] を記録しておきます。後でこのアカウントを使います。 最後に、 [作成] を選んで Azure リソースを作成し、関数アプリにコードをデプロイします。
デプロイが完了したら、 [リソース グループに移動] を選んでから、新しい関数アプリを選びます。
おめでとうございます。 これで、Azure Key Vault の Azure Files 接続文字列を参照する関数アプリが正しく作成されました。
アプリでシークレットへの参照を追加する必要がある場合は、Key Vault に格納されている値を指し示す新しいアプリケーション設定を定義するだけで済みます。 詳細については、「Azure Functions の Key Vault リファレンス」を参照してください。
ヒント
Application Insights 接続文字列とそれに含まれるインストルメンテーション キーは、シークレットとは見なされず、Reader アクセス許可を使用して App Insights から取得できます。 それらを Key Vault に移動することは、できますが、必要ありません。
AzureWebJobsStorage にマネージド ID を使用する
次に、前の手順で構成したシステム割り当て ID を、AzureWebJobsStorage
の接続に使用します。 AzureWebJobsStorage
は、複数の実行中のインスタンスを調整するために、Functions ランタイムおよびいくつかのトリガーとバインディングによって使用されます。 これは関数アプリが動作するために必要であり、Azure Files のように、新しい関数アプリを作成するときに既定で接続文字列を使用して構成されます。
システム割り当て ID にストレージ アカウントへのアクセス権を付与する
ユーザー割り当て ID とキー コンテナーに関して前に行った手順と同様に、ストレージ アカウントへのアクセスをシステム割り当て ID に許可するロールの割り当てを作成します。
Azure portal で、前に関数アプリで作成したストレージ アカウントに移動します。
[アクセス制御 (IAM)] を選択します。 このページで、リソースにアクセスできるユーザーを表示および構成できます。
[追加] を選択し、[ロールの割り当ての追加] を選択します。
[ストレージ BLOB データ所有者] を見つけて選び、[次へ] を選択します
[メンバー] タブの [アクセスの割り当て先] で、 [マネージド ID] を選びます
[メンバーの選択] を選択して、[マネージド ID の選択] パネルを開きます。
[サブスクリプション] が、前にリソースを作成したものであることを確認します。
[マネージド ID] セレクターで、 [システム割り当てマネージド ID] カテゴリから [関数アプリ] を選びます。 [関数アプリ] ラベルの横のかっこ内に、サブスクリプション内でシステム割り当て ID を持っているアプリの数を示す値が含まれている場合があります。
入力フィールドの下の一覧に、自分のアプリが表示されているはずです。 表示されていない場合は、 [選択] ボックスを使って、アプリの名前で結果をフィルター処理できます。
アプリケーションを選択します。 下の [選択したメンバー] セクションにそれが移動します。 [選択] を選択します。
[ロールの割り当てを追加] 画面で、[レビューと割り当て] を選択します。 構成を確認し、[レビューと割り当て] を選択します。
ヒント
BLOB によってトリガーされる関数に関数アプリを使う予定の場合は、AzureWebJobsStorage に使うアカウントで、ストレージ アカウント共同作成者とストレージ キュー データ共同作成者の各ロールに対してこれらの手順を繰り返す必要があります。 詳細については、BLOB トリガー ID ベースの接続に関するページを参照してください。
AzureWebJobsStorage の構成を編集する
次に、ホスト ストレージに BLOB サービスを使用するときにシステム割り当て ID を使用するように、関数アプリを更新します。
重要
AzureWebJobsStorage
の構成は一部のトリガーとバインドによっても使用され、それらの拡張機能で ID ベースの接続を使用できる必要があります。 BLOB トリガーまたはイベント ハブ トリガーを使用するアプリでは、それらの拡張機能を更新することが必要になる場合があります。 このアプリには関数が定義されていないので、まだ問題はありません。 この要件の詳細については、「ID を使用するホスト ストレージへの接続」をご覧ください。
同様に、Linux 従量課金プランでサーバー側ビルドを使用する場合は、AzureWebJobsStorage
がデプロイ成果物に使用されます。 Linux 従量課金プランで AzureWebJobsStorage
に対して ID ベースの接続を有効にするときは、外部デプロイ パッケージを使ってデプロイする必要があります。
Azure portal で関数アプリに移動します。
関数アプリで、[設定] を展開し、[環境変数] を選びます。
[アプリの設定] タブで、AzureWebJobsStorage アプリ設定を選択し、次の表に従って編集します。
オプション 推奨値 Description 名前 AzureWebJobsStorage__accountName 名前を AzureWebJobsStorage から正確な名前 AzureWebJobsStorage__accountName
に更新します。 この設定は、格納されているシークレットを検索する代わりに ID を使用するようにホストに指示します。 新しい設定で使用されている二重アンダースコア (__
) は、アプリケーション設定での特殊文字です。Value 自分のアカウント名 接続文字列から StorageAccountName だけに名前を更新します。 この構成では、ID を使用してリソースに接続するようにシステムに指示します。
[適用] を選択し、[適用]、[確認] の順に選択して変更内容を保存し、アプリ関数を再起動します。
代わりにマネージド ID を使って BLOB に接続するようにアプリを構成することで、AzureWebJobsStorage に対するストレージ接続文字列の要件がなくなりました。
Note
__accountName
構文は AzureWebJobsStorage 接続に固有であり、他のストレージ接続に使うことはできません。 他の接続を定義する方法については、アプリに使う各トリガーとバインドのリファレンスを参照してください。
次のステップ
このチュートリアルでは、シークレットを構成に格納せずに関数アプリを作成する方法について説明しました。
次のチュートリアルに進み、トリガー接続とバインド接続で ID を使用する方法をご覧ください。