0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Logic Apps閉域とMI認証

0
Last updated at Posted at 2026-05-28

Logic Apps閉域とMI認証

本記事記述および実装内容は、多くの部分をAIで処理しており、人間チェックは甘いです

はじめに

Logic Apps Standard を閉域化したいとき、ASE v3 を使うべきか、
host storage を Managed Identity 認証にできるのかで迷うことがあります。

今回、非 ASE の Logic Apps Standard を VNet Integration と
Private Endpoint で閉域化し、User-assigned Managed Identity
(UAMI) で host storage 認証をどこまで置き換えられるか検証しました。

対象読者は次のような方です。

  • Logic Apps Standard を閉域構成で使いたい
  • host storage の接続文字列をできるだけ排除したい
  • ASE v3 を使うべきか判断したい
  • Bicep で再現可能な構成を知りたい

結論

  • ✅ 非 ASE でも、Blob / Queue / Table の host storage は
    UAMI 認証で動作しました。
  • ✅ Logic Apps Standard の閉域化は、VNet Integration と
    Private Endpoint で実現できました。
  • ⚠️ Azure Files は SMB の Microsoft Entra 認証に未対応です。
    SKU や ASE 有無に関係なく、Files は接続文字列が必要です。
  • ⚠️ Workflow Extension が AzureWebJobsStorage
    接続文字列としても要求します。
    そのため、現時点で真の MI-only 構成ではなく、
    MI 設定と Key Vault 参照を併設するハイブリッド構成が必要でした。

この記事での「MI 化」は、Blob / Queue / Table の host storage
データプレーンを UAMI 認証にする、という意味です。
Azure Files の SMB マウントは別枠で、接続文字列が残ります。

アーキテクチャ

主な構成は次の通りです。

要素 内容
VNet 10.50.0.0/16
Subnet snet-logicappsnet-pe
Private Endpoint blob / queue / table / file / sites の 5 本
Private DNS Zone blob / queue / table / file / azurewebsites の 5 個
Logic Apps plan Workflow Standard WS1
Storage Standard_LRS, public network access disabled
NSG snet-logicapp から SMB 445 outbound を明示許可
UAMI roles Blob Owner / Queue Contributor / Table Contributor
Key Vault role Key Vault Secrets User

構築の要点

Logic Apps 流の app setting キー名を使う

ここが一番重要でした。
Functions の identity-based connection 設定をそのまま使うと、
Logic Apps Standard の host storage では期待通りに動きませんでした。

パターン キー名 結果
❌ Functions 流 __credential=managedidentity + __clientId=<GUID> 起動失敗
✅ Logic Apps 流 __credentialType + __managedIdentityResourceId 動作

採用した設定は次の形です。

appsettings.txt
AzureWebJobsStorage__credentialType = managedIdentity
AzureWebJobsStorage__managedIdentityResourceId = <UAMI resourceId>
AzureWebJobsStorage__accountName = <storage account name>
AzureWebJobsStorage__blobServiceUri = https://<storage>.blob.core.windows.net
AzureWebJobsStorage__queueServiceUri = https://<storage>.queue.core.windows.net
AzureWebJobsStorage__tableServiceUri = https://<storage>.table.core.windows.net
AzureWebJobsStorage = @Microsoft.KeyVault(SecretUri=https://<kv>.vault.azure.net/secrets/<secret>/)
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING = @Microsoft.KeyVault(SecretUri=https://<kv>.vault.azure.net/secrets/<secret>/)
AzureWebJobsSecretStorageType = Files

Bicep の主要部分

Logic App には UAMI を割り当て、Key Vault reference も同じ UAMI で
解決させます。

infra/modules/logic-app.bicep
resource logicApp 'Microsoft.Web/sites@2024-04-01' = {
  name: logicAppName
  location: location
  tags: tags
  kind: 'functionapp,workflowapp'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${uamiId}': {}
    }
  }
  properties: {
    serverFarmId: appServicePlan.id
    publicNetworkAccess: 'Disabled'
    virtualNetworkSubnetId: snetLogicAppId
    vnetRouteAllEnabled: true
    keyVaultReferenceIdentity: uamiId
  }
}

app settings は、MI 用の分解キーと AzureWebJobsStorage
Key Vault 参照を併設します。

infra/modules/logic-app.bicep
resource appSettings 'Microsoft.Web/sites/config@2024-04-01' = {
  parent: logicApp
  name: 'appsettings'
  properties: {
    AzureWebJobsStorage__credentialType: 'managedIdentity'
    AzureWebJobsStorage__managedIdentityResourceId: uamiId
    AzureWebJobsStorage__accountName: storageAccountName
    AzureWebJobsStorage__blobServiceUri: 'https://${storageAccountName}.blob.${environment().suffixes.storage}'
    AzureWebJobsStorage__queueServiceUri: 'https://${storageAccountName}.queue.${environment().suffixes.storage}'
    AzureWebJobsStorage__tableServiceUri: 'https://${storageAccountName}.table.${environment().suffixes.storage}'
    AzureWebJobsStorage: '@Microsoft.KeyVault(SecretUri=https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${fileConnSecretName}/)'
    WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: '@Microsoft.KeyVault(SecretUri=https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${fileConnSecretName}/)'
    AzureWebJobsSecretStorageType: 'Files'
  }
}

UAMI には Storage と Key Vault のロールを付与します。

infra/modules/rbac.bicep
// UAMI -> Storage
// - Storage Blob Data Owner
// - Storage Queue Data Contributor
// - Storage Table Data Contributor

// UAMI -> Key Vault
// - Key Vault Secrets User

デプロイ

deploy.sh
cd logic-app-private
azd env new <env-name>
azd env set AZURE_LOCATION japaneast
azd up

検証後は次で削除できました。

cleanup.sh
azd down --force --purge

ハマったポイントと解決策

Workflow Extension が接続文字列も要求する

MI 用の分解キーだけを設定し、AzureWebJobsStorage 自体を消すと、
Workflow Extension の初期化で失敗しました。

例外の発生箇所は次のコンポーネントでした。

error.txt
Microsoft.Azure.Workflows.WebJobs.Extensions.WorkflowExtensionProvider.Initialize
Value cannot be null. (Parameter 'connectionString')

つまり、Functions runtime 側は MI 用の分解キーを解釈できても、
Workflow Extension 側は AzureWebJobsStorage を接続文字列としても
読みます。

そのため、次のハイブリッド構成にしました。

用途 設定 認証
Blob host storage AzureWebJobsStorage__blobServiceUri UAMI
Queue host storage AzureWebJobsStorage__queueServiceUri UAMI
Table host storage AzureWebJobsStorage__tableServiceUri UAMI
Workflow Extension 用 AzureWebJobsStorage Key Vault 参照
Files content WEBSITE_CONTENTAZUREFILECONNECTIONSTRING KV 参照

App setting には平文の AccountKey= が出ない構成にしています。
ただし Storage Account 側では Azure Files 用に Shared Key が必要です。

Azure Files SMB は Entra OAuth 未対応

Azure Functions の公式チュートリアルには、次の記載があります。

Azure Files is an example of a service that doesn't yet support Microsoft
Entra authentication for Server Message Block (SMB) file shares.

これは Logic Apps / Functions / App Service の SKU ではなく、
Azure Files の SMB マウント側の制約です。
そのため、ASE v3 にしても Files の MI 認証はできません。

Azure Files の中身

Azure Files の中身は以下の通り
content-pioq2bvneff7s (5120 GiB クォータ、実使用は数 MB 程度) の中身は 7 カテゴリ:

 content-pioq2bvneff7s/
 ├── site/                         ← アプリ本体(アクティブな実行コード)
 │   ├── wwwroot/                  ← ★ ここがあなたが書いた workflow
 │   │   ├── host.json             (Logic Apps host 設定)
 │   │   └── ping-workflow/        (workflow.json + connections.json)
 │   ├── deployments/              ← zip deploy 履歴
 │   │   ├── active                (現在 active な deployment ID)
 │   │   ├── latest.json           (最新メタデータ)
 │   │   └── <commit-hash>/        (各デプロイのスナップショット)
 │   └── locks/                    ← 排他制御用
 ├── data/Functions/
 │   └── secrets/host.json         ← マスター/関数/system キー (暗号化済)
 ├── ASP.NET/DataProtection-Keys/  ← Cookie/トークン暗号鍵 (90日ローテ)
 ├── LogFiles/
 │   ├── Application/              (アプリ stdout/stderr)
 │   ├── kudu/                     (SCM 操作ログ)
 │   └── eventlog.xml
 ├── .ssh/                         (Kudu Bash 用 SSH 設定)
 ├── .gitconfig                    (Kudu git 操作用)
 └── ShutdownSentinel              (インスタンス停止検知用 sentinel)

image.png

SMB 445 outbound を明示許可する

Logic App の content share は Azure Files です。
閉域構成で File Private Endpoint に到達させるため、
snet-logicapp の NSG に 445/TCP outbound を明示しました。

infra/modules/network.bicep
resource nsgLogicApp 'Microsoft.Network/networkSecurityGroups@2024-05-01' = {
  name: 'nsg-snet-logicapp'
  location: location
  tags: tags
  properties: {
    securityRules: [
      {
        name: 'AllowOutboundSmbToVNet'
        properties: {
          direction: 'Outbound'
          access: 'Allow'
          protocol: 'Tcp'
          destinationAddressPrefix: 'VirtualNetwork'
          destinationPortRange: '445'
        }
      }
    ]
  }
}

検証結果

S1 から S11 の v1 検証と、UAMI 化した v2 追加検証はすべて PASS でした。

ID 確認内容 結果
S1 全リソースの provision 成功
S2 Storage の public network access disabled
S3 Logic App の public network access disabled
S4 5 本の Private Endpoint が Approved
S5 必要な RBAC が付与済み
S6 外部から Logic App HTTPS が 403
S6b 外部から SCM / Kudu が 403
S7 5 個の Private DNS Zone が VNet link 済み
S8 外部から Storage が 403
S9 閉域下で workflow run が Succeeded
S10 app settings に平文 AccountKey= なし
S11 azd down --force --purge で削除可能
S5b UAMI 割当と Storage data roles を確認
S9b UAMI 構成で Recurrence workflow 成功
S10b MI 設定と Files の KV 参照を確認
v2 で確認した app settings
appsettings-sanitized.txt
AzureWebJobsStorage__credentialType = managedIdentity
AzureWebJobsStorage__managedIdentityResourceId = <UAMI resourceId>
AzureWebJobsStorage__accountName = <storage account name>
AzureWebJobsStorage__blobServiceUri = https://<storage>.blob.core.windows.net
AzureWebJobsStorage__queueServiceUri = https://<storage>.queue.core.windows.net
AzureWebJobsStorage__tableServiceUri = https://<storage>.table.core.windows.net
AzureWebJobsSecretStorageType = Files
WEBSITE_CONTENTSHARE = <content share name>
AzureWebJobsStorage = @Microsoft.KeyVault(SecretUri=https://<kv>.vault.azure.net/secrets/<secret>/)
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING = @Microsoft.KeyVault(SecretUri=https://<kv>.vault.azure.net/secrets/<secret>/)

リソース

dev 用途では、主なコストは WS1、Private Endpoint、Storage、
Key Vault、Application Insights です。

ASE v3 を使う構成よりは軽く、閉域化そのものが目的なら
非 ASE の Standard 構成で十分検討できます。
検証後は azd down --force --purge で削除する運用が前提です。

まとめ

  • 非 ASE の Logic Apps Standard でも閉域化は可能でした。
  • Blob / Queue / Table の host storage は UAMI 認証で動作しました。
  • Logic Apps では __credentialType
    __managedIdentityResourceId を使うのがポイントでした。
  • Azure Files SMB は Entra OAuth 未対応のため、Files は MI 化できません。
  • Workflow Extension が AzureWebJobsStorage を接続文字列としても
    要求するため、現時点ではハイブリッド構成が現実解です。

「閉域化できるか」と「Shared Key を完全に消せるか」は別問題です。
前者は非 ASE でも可能でしたが、後者は Azure Files の制約により
現時点では達成できませんでした。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?