ごった煮

色々な事を書いてます

App Service の Key Vault reference を User Assigned MSI で使う

App Service の Key Vault reference を使う際の備忘録です

何をするのか

  • App Service の Key Vault reference を User Assigned Managed Id で繋ぐ

既定の動作

Key Vault reference の規定動作は、System Assigned Managed Id になります。

なので、少し手を加えないと User Assigned Managed Id が使えません。

因みに 2024年7月現在、この設定は実質ポータルから操作できません。

必要なもの

App Service に Managed Id を設定したり、Managed Id に Key Vault の権限を設定する部分は、今回は割愛します。

今回は、Azure CLI を使用します

やってみる

早速やってみましょう

User Assigned Managed Id のリソース Id を取得する

まず、使いたい Managed Id のリソース Id を知りたいので、次のコマンドを流して取得します

az identity show -n {Your Managed Id name} -g {Your resource group name} --query id

ポータルから取得しても ok です

App Service と紐づける

az webapp update -g {Your resource group name} -n {Your Web App name} --set keyVaultReferenceIdentity={Managed Id resource id}

function app の場合は、

az functionapp update -g {Your resource group name} -n {Your Web App name} --set keyVaultReferenceIdentity={Managed Id resource id}

Bicep で紐づけたい場合は、SiteProperties > keyVaultReferenceIdentity に Managed Id のリソース Id を指定します

既定の動作に戻したい

戻す場合は次のようにします

az webapp update -g {Your resource group name} -n {Your Web App name} --set keyVaultReferenceIdentity=SystemAssigned

function app の場合は、

az functionapp update -g {Your resource group name} -n {Your Web App name} --set keyVaultReferenceIdentity=SystemAssigned

余談

ポータルの Key Vault reference のブレードを開くと、User assigned でも System Assigned でも、System assigned managed identity と表示されて分かりづらいですが、 指定した Managed Id で繋がっているはずです

まとめ

ポータルからポチポチ出来ないのでちょっとした検証には不便ですが、これにて一件落着

Microsoft MVP for Microsoft Azure を受賞しました。

今年も Microsoft MVP を受賞させていただきました

2016年から足掛け9年になりました(審査スキップが入っているので受賞は8回)

昨年は、子供が生まれてバタバタしていたこともあり大した事が出来ませんでしたが、 今年はまた細々と活動していければと思います

子供がまだ小さいので、リアル勉強会はあと数年お預けですが、 どこかで見かけたらよろしくお願いします

今年も一年よろしくお願いします

API Management の死活監視を設定する

API Management と Application Insights を組み合わせると、既定の死活監視が動きますが、このあたりの資料が全然出てこないので、 備忘録として簡単に残します。

前提

今回は、ポータルからの操作に対して言及します。

IaC で設定すると、この部分は既定で有効にならないかもしれないので、注意してください。

また、Consumption プランを前提に話を進めるので、それ以外のプランと挙動が異なる可能性があります。

死活監視の動き

API Management に対して、Application Insights を有効化すると死活監視が設定されます。

既定では、{APIM のエンドポイント}/status-0123456789abcdef に対して、世界中のデータセンターからリクエストがリクエストが送られます。

Application Insights のログを見ると、ここに対してガンガンリクエストが送られているのが分かります。

このエンドポイントですが、Consumption プラン以外では、APIM 側でエンドポイントが用意されているようなのですが、Consumption プランでは、 このエンドポイントは既定で 404 になります。

Consumption プランは、可能な限り料金を節約したいユースケースが多いと思うので、このリクエストはあまり歓迎出来ない挙動です。

死活監視を設定する

死活監視の設定は、Application Insights の画面から行います。(APIM の画面にはないので注意)

Application Insights > Investigate > Availability に移動します

↓ のような画面が出てきます。

エンドポイント横の・・・を選択すると、Edit するか、停止するかが出てきます。

シンプルに止めたい場合は、Disable します。

Edit パネルでは、エンドポイントを差し替えることも出来るので、任意のエンドポイントへの変更も可能です。

まとめ

API Management の画面から編集させてほしいですが、こればっかりは仕方ない

ソリューション内で参照されている nuget パッケージにバージョンアップが来てないかを検出する方法

NuGet パッケージの更新って忘れがちなので、自動的にバージョンアップとか検出したいですよね

やり方

バージョンアップの検出

dotnet list {Your solution file path} package --outdated

廃止されたパッケージの検出

dotnet list {Your solution file path} package --deprecated

--format json を付けると、json で返ってくるので、自動化して何かしたいといった時にも便利です

Azure Pipelines に組み込んでみよう

せっかくなんで、Azure Pipelines で動かしてみましょう

pool:
  vmImage: ubuntu-latest

steps:
- checkout: self
  submodules: true
  persistCredentials: true

- task: DotNetCoreCLI@2
  displayName: 'Restore'
  inputs:
    command: 'restore'
    projects: '**/{Your solution file path}'
    feedsToUse: 'select'


- script: |
    result=$(dotnet list {Your solution file path} package --outdated --format json)

    echo $result
    echo $result | jq -c '.projects[]' | while read project; do
      project_path=$(echo "$project" | jq '.path')
      has_frameworks=$(echo "$project" | jq 'has("frameworks")')

      if [[ "$has_frameworks" == "true" ]]; then
        echo '対象があるよ'
      else
        echo '対象が無いよ'
      fi
    done

- script: |
    dotnet list {Your solution file path} package --outdated

- script: |
    dotnet list {Your solution file path} package --deprecated

簡単な検出用のスクリプトを記述してあります。

必要に応じて成型して slack に送るとかそういったことが出来ると思います。

まとめ

一週間に一回 CI を回してチェックするとか良いんじゃないでしょうか

Azure DevOps のサービスコネクションをマニュアルで設定する

Azure DevOps でサービスコネクションを作る際、自分たちの管理下にあるサブスクリプションなら自動設定で概ねどうにかなりますが、 ゲストで参加している Entra 配下にあるサービスコネクションだと、自動設定でサブスクリプションが選択肢に出てきてくれないことが多々あってストレスだったのでメモを残します。

前提

今回の前提は、以下の通りです。

権限が無い場合は適宜調整してください。

また、この設定に利用している画面は、2024年5月23日現在のものなので、タイミングによっては UI が異なる可能性がありますので、 その点にはご留意ください。

  • 対象のサブスクリプションが入っている Entra にゲストで参加している
  • 対象の Entra 内で Enterprise Application を操作する権限がある

設定してみる

さっそく設定してみましょう。

サービスコネクションの作成は、何パターンか方法がありますが、今回は、Workload Identity Federation with OpenID Connect を採用します。

アプリケーションを作る

Entra でサクッとアプリケーションを登録しましょう

詳細は割愛

OpenID Connect に必要な情報を取得する

Entra のアプリケーションに登録する Issuer 情報などを取得します。

Workload Identity federation (manual) を選択します。

適当にサービスコネクションの名前を設定して次へ。

表示される Issuer と Subject identifier をメモしておきます。

こちらを Entra のアプリケーションに設定します。

取得した情報をアプリケーションに登録する

先ほど取得した情報を、アプリケーションへ登録します。

Entra > App registrations > アプリケーション > Certificates & secrets で登録画面へ移動します。

Federated credentials のタブ > Add credential を選択します。

Federated credential scenario で、Other issuer を選択します。

Issuer に、先ほど取得した Issuer、Subject identifier に先ほど取得した Subject identifier を入力します。

これで、DevOps の情報を入力する作業は完了です。

DevOps に登録する情報を取得する

次に、DevOps 側に設定する情報を Azure から取得します。

必要なもの

サブスクリプション情報は、サブスクリプションの Overview から取得します。

Service Principal Id は、アプリケーションの Overview に表示される Application (client) ID を取得します。

テナント Id は、Entra の Overview から取得します。

取得したら、それぞれを DevOps の画面で登録します。

入力したら Verify and save を選択して接続できるか確認します。

まとめ

これにて、Workload Identity federation でサービスコネクションの設定が出来ました。

SI などをしていると、自分たちが管理していないサブスクリプションに対してこの設定をすることは結構あるかと思います。

もうちょっと自動設定がうまく動いてくれればいいのですが、テナント跨ぎをしたりすると致し方ない部分は結構あるのでぜひご参考の程

ASP.NET MVC に Application Insights を導入すると、App Service 上で動かない時がある

ASP.NET MVC (not dotnet core) に Application Insights を NuGet から入れた際にハマったので、備忘録を残します。

何が起きたのか

下記のステップで既存の ASP.NET MVC アプリに Application Insights を入れてみました。

  1. NuGet から Microsoft.ApplicationInsights.DependencyCollector をインストール
  2. NuGet から Microsoft.ApplicationInsights.Web をインストール

1 の状態では、App Service 上でも動きました。

問題は、2の状態で発生しました。

発生したエラー

An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.

This application defines configuration in the system.web/httpModules section.

はてさて

なぜこんなエラーが起きたのか

NuGet から、 Microsoft.ApplicationInsights.Web をインストールした際、Web.config の system.web/httpModules のセクションに下記の設定が自動で差し込まれていました。

    <httpModules>
      <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
    </httpModules>

使っていた App Service は Managed pipeline versionIntegrated だった為、system.web/httpModules のセクションが使えず、エラーになっていました。

Managed pipeline version を、Classic に変更すれば、該当の Web.config でも問題なく動作します。

まとめ

App Service の初期設定は、Integrated なので、注意が必要です。

今は、.NET Framework で新規のコードを書くことは減ったかもしれませんが、既存のコードに導入するといったことは往々にしてあるかと思います。 その際はご注意を

AWS から Azure の KeyVault を利用する

Azure と AWS でそれぞれアプリケーションが稼働していて、外部の API に対して利用するクライアント Id、シークレットを同じものを使いたいという状況はそれなりにあると思います。(要出典

ですが、KeyVault は、Entra 認証が必要なため、Azure 内のシステムからでないと少しアクセス方法がややこしいです。

ということで、連携方法をまとめます。

今回の仕組み

今回構築する仕組みは、Workload Identity Federation の仕組みを利用して、Cognito と User assigned managed Identity を federate して実現します。

実際にやってみる

ステップ01

User assigned managed identity を作成します

とりあえずポータルからポチポチでも何でも良いので、適当に作成します。

ステップ02

Key Vault を作成します。

こちらも、ポータルからポチポチでも何でも良いので、適当に作成します。

作成した Managed Identity に Key Vault の権限を付与する

とりあえず下記3つを IAM で付与します。

  • Key Vault Certificate User
  • Key Vault Secrets User
  • Key Vault Crypto Service Encryption User

Cognito を作ったりするように AWS に IAM ユーザを作る

Root ユーザは怖いので、IAM ユーザを作りましょう

次の2つの権限を割り当てた IAM ユーザがあれば OK です

  • AmazonCognitoPowerUser
  • AWSCloudShellFullAccess

iam:create-role が無いと、Cognito 作成時にエラーが出ますが、今回はあくまで Azure と Federate するだけで、 AWS 内で何かする権限は必要ないので、このままで OK です。

ステップ03

Cognito を作る

ID プールを作る

分かりづらいですが、プルダウンから、 AWS のサービスへのアクセス権を付与する選択して、ID プールを作成を選択します。

ID プールの信頼設定

下記の設定で次へを選択します。

  • ユーザアクセス : 認証されたアクセス
  • 認証された ID ソース : カスタムデベロッパープロバイダー

許可を設定

下記の設定で次へを選択します。 ※ IAM ロールを作成する権限が無いはずなので、あとでエラーになります。

  • IAM ロール : 新しい IAM ロールを作成
  • IAM ロール名に適当な名前を入れる

ID プロバイダーを接続する

下記の設定で次へを選択します。

  • デベロッパープロバイダー名に適当な名前を入れる(今回は、azure-access にします。)

プロパティを設定する

ID プール名に適当な名前を入れて次へを選択します。

確認と作成

確認画面で、問題が無さそうなら、ID プールを作成を選択します。

ステップ04

Cognito の設定をする

Identity プールに Identity を作成する

ここからコマンドを流す必要があります。

AWS CLI が必要なので、CloudSehll を使いましょう

CloudShell で下記のコマンドを流します。

aws cognito-identity get-open-id-token-for-developer-identity \
--identity-pool-id {ID プールの id} \
--logins {デベロッパープロバイダー名}={適当なテキスト(managed id の client id とか)}

コマンドを流すと下記のような json が取れるので、Token の値を jwt デコーダでデコードします。

{
    "Token": "{jwt トークン}",
    "IdentityId": "{登録した Identity の Id}"
}

ステップ05

Managed Identity と Cognito を federate する

Azure CLI を使うので、Azure CLI が使える環境をご用意ください

下記のコマンドを流します。(PowerShell 前提になっているので、他のシェルを使う場合は、改行の調整をしてください)

az identity federated-credential create `
--name {Managed Identity の Federated credentials として登録する名前} `
--identity-name {managed identity の名前} `
--resource-group {resource group の名前} `
--issuer {jwt から取得した iss} `
--subject {jwt から取得した sub} `
--audience {jwt から取得した aud}

ステップ06

Cognito のトークンを使って Azure にログインする

まず、Cognito からトークンを取得します。

ステップ04 で流したコマンドをもう一度流して、トークンを取得します。

下記のコマンドで Azure CLI からログインします。

az login --federated-token {cognito から取得したトークン(jwt)} `
--tenant {Entra のテナント Id} `
--service-principal -u {managed identity の client id}

ステップ07

KeyVault へアクセスできるかをチェックする

とりあえず Secrets を取得してみましょう

az keyvault secret list --vault-name {key vault の名前}

エラーが出なければ、成功です。

ステップ07

REST API を使って、Key Vault にアクセスする

Azure へのアクセストークンを取得する

下記の設定で API を呼びます。(Postman 等を使いましょう)

リクエスト Body

Key Value
client_id {Managed Identity の Client Id}
grant_type client_credentials
scope {必要な scope 設定。Key Vault の場合は、https://vault.azure.net/.default}
client_assertion {Cognito のトークン}
client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer

下記のレスポンスが返ってきます。

{
  "token_type": "Bearer",
  "expires_in": {有効期限(秒)},
  "access_token": "{アクセストークン}"
}

Key Vault を呼び出す

認証

Bearer {取得したアクセストークン}

Secrets を取得する

  • Endpoint : {KeyVault エンドポイント}/secrets?maxresults=1&api-version=7.4
  • メソッド : GET

まとめ

これで、AWS の環境から KeyVault にアクセスできるようになりました。

Managed Identity で接続できるサービスは、権限を調整すればこれで接続できるはずです。

世の中にある大抵のシステムは、パブリッククラウドを跨いで何かするということは無いと思いますが、いざというときに使えると便利です。

SDK を使った方法については気が向いたらまとめようと思います。