Foundry Agent Service からの OpenAPI ツール呼び出しをセキュリティで保護する

Foundry Agent Serviceは、App ServiceのOpenAPIエンドポイントを匿名またはマネージドIDで呼び出すことができます。 エンドポイントを保護するために、App Service認証がエンドポイントを保護する場合は管理型IDを使いましょう。

このシナリオには、2つの独立したマネージドID方向が含まれています。

  • App ServiceがFoundryに連絡すると、発信者はApp Serviceシステムに割り当てられた管理IDです。 Foundryリソースまたはプロジェクト上のAzureロールベースアクセス制御(RBAC)が通話を承認します。
  • FoundryがApp Service OpenAPIエンドポイントを呼び出す際、呼び出し者は親のFoundryリソースシステムに割り当てられた管理型アイデンティティです。 App Service認証トークン検証と許可リストが通話を承認します。

App Service認証のMicrosoft Entraアプリケーションが保護されたAPIリソースです。 どちらのマネージド ID 呼び出しも置き換えるものではありません。

以下の表は、このシナリオにおける識別子と応用を要約しています。

アイデンティティまたは応用 Purpose コンフィギュレーション
App Service 認証 Microsoft Entra アプリケーション 保護されたウェブ/APIリソースとブラウザのサインイン アプリケーションID URI、リダイレクトURI、トークンオーディエンス
App Service システム割り当て ID App Service が Foundry を呼び出します Foundry 上の Azure RBAC
App Service認証ユーザー割り当てID(任意) Secretless App Service 認証クライアントアサーション フェデレーション ID 資格情報
親ファウンドリーリソースシステム割り当てアイデンティティ Foundry OpenAPIツールがApp Serviceを呼びます 許可されたクライアントアプリケーションとオプションの許容アイデンティティ
鋳造所プロジェクトのアイデンティティ Projectレベルのファウンドリー業務 OpenAPI HTTP呼び出しには使用されていません

[前提条件]

親FoundryリソースのマネージドIDを探す

Foundry Agent Serviceは、 親Foundryリソースの システム割り当て管理IDをOpenAPIツールを呼び出す際に使用します。 このリクエストにはFoundryプロジェクトのマネージドIDは使われていません。

親リソース識別子には2つの識別子が必要です:

  • アプリケーションID(クライアントID): アクセストークンの azp 請求に現れ、App Service認証で許可されたクライアントアプリケーションチェックに使用されます。
  • オブジェクト(プリンシパル)ID: トークンの oid 請求に現れ、App Service認証が特定のIDへのアクセスを制限する場合に使用されます。
  1. Foundryポータルでプロジェクトを開き、上部メニューで「管理」を選択します。

  2. Projectの詳細で親リソースを選択し、その後「Azureで開く」ポータルを選択します。

  3. Foundry リソースの左側のメニューで、 リソース管理>Identity を選択します。

  4. システム割り当て済み で、オブジェクト (プリンシパル) ID の値をコピーし、後で参照します。

  5. Azure portal で、 Microsoft Entra ID を検索して選択します。

  6. 検索ボックスで、コピーしたオブジェクト ID を検索し、検索結果で選択します。

  7. [ 概要 ] ページで、 アプリケーション ID の値をコピーします。

    オブジェクトIDはシステムに割り当てられた管理IDと同じです。 App Service認証の設定のために、アプリケーションIDとオブジェクトIDの両方を保存してください。

アプリの Microsoft Entra 認証を構成する

  1. Azure portal で、App Service アプリに移動します。

  2. アプリの左側のメニューで [設定]>[認証] を選び、[ID プロバイダーの追加] を選びます。

  3. [ID プロバイダーの追加] ページで、ID プロバイダーとして Microsoft を選択して新しいアプリ登録を作成します。

  4. [アクセスの制限] で、[認証が必要] を選びます。

  5. [ 追加のチェック] の [ クライアント アプリケーションの要件] で、[ 特定のクライアント アプリケーションからの要求を許可する] を選択します。

  6. 鉛筆アイコンを選択し、許可されているクライアントアプリケーションを設定します:

    • コピーした アプリケーションID を「 親Foundryリソースの管理IDを探す」に追加してください。 このIDは親Foundryリソース識別子から要求されたトークンを許可します。
    • アプリがインタラクティブなブラウザサインインをサポートしている場合は、App Service認証のMicrosoft Entraアプリケーション固有のアプリケーション(クライアント)IDも追加してください。 このIDは、ユーザーのサインイン時にウェブアプリケーションに発行されるトークンを可能にします。 新しいアプリ登録を作成する場合は、アイデンティティプロバイダーを作成した後にこのIDを追加してください。
  7. アイデンティティ要件の設定:

    • Foundryのみが呼び出すエンドポイントで最も狭いポリシーを選択する場合は、「 特定のアイデンティティからのリクエストを許可」を選択します。 鉛筆アイコンを選択し、親のFoundryリソース識別の オブジェクトIDを追加します。
    • アプリがインタラクティブなブラウザサインインもサポートしている場合は、「 任意の身分からのリクエストを許可 」を選択してテナントユーザーがブロックされないようにしてください。 この設定では匿名アクセスはできません。 リクエストには、許可されたクライアントアプリケーションおよび設定されたテナントからの有効なトークンが依然として含まれている必要があります。
  8. テナント要件については、「発行者テナントからの要求のみ許可」を選択してください。 親Foundryリソースのアイデンティティとサインインするすべてのユーザーはこのテナントに含まれている必要があります。

  9. 認証されていないリクエストの設定:

    • アプリがAPIクライアントのみに対応している場合は、 APIに対してHTTP 401 Unauthorized: Recommendedを選択します。
    • アプリがインタラクティブなブラウザサインインをサポートしている場合、HTTP 302 Foundリダイレクトを選択し、リダイレクトプロバイダーとしてMicrosoftを選択します。
  10. [ 追加] を選択して ID プロバイダーを作成します。

    以下の画像は、ファウンドリー専用の最も狭い構成を示しています。

    App Service での新しい Microsoft 認証プロバイダーの構成を示すスクリーンショット。

  11. アプリがインタラクティブなブラウザサインインをサポートしている場合は、プロバイダーを編集し、 トークンストア が有効になっていることを確認してください。 新しいアプリ登録を作成したら、そのアプリケーションIDを許可されたクライアントアプリケーションに追加してください。

インタラクティブなブラウザサインインをサポートする場合は、両方のアプリケーションIDが必要です。 Foundry専用APIは親Foundryリソース識別元のアプリケーションIDのみを必要とします。

アプリ登録のアプリケーション ID URI を更新する

Application ID URIは保護されたAPIをOAuthリソースとして識別します。 管理型IDのOpenAPIツールでは、オーディエンスがApp Service認証のMicrosoft Entraアプリケーションに登録されたApplication ID URIと正確に一致しなければなりません。 Foundryは親リソース識別子のアクセストークンを要求する際に、その値をオーディエンスとして使用します。

アプリケーションIDアプリケーションID URIは異なるプロパティです:

  • アプリケーションIDはクライアントIDとも呼ばれ、生成されたGUIDです。
  • アプリケーションID URIとは、アプリケーションが所有するAPIやリソースを特定するURIです。 アプリケーションクライアントIDを含める必要はありません。

安定したアプリケーションID URIを選択し、それをAPI契約の一部として扱います:

フォーマット 適合性が良い Considerations
api://<client-id> 多くのクライアントや展開スロットを持つ再利用可能なMicrosoft Entra保護API 従来型でホストに依存しませんが、生成されたクライアントIDには宣言的プロビジョニングの第二段階が必要になることがあります。
https://<app>.azurewebsites.net App Service固有の統合とワンパスのBicep 計算は簡単でこのガイドにも合致しますが、APIのアイデンティティはApp Serviceのホスト名に結びついています。 各デプロイスロットは異なるホスト名を持っています。
api://<tenant-id>/<logical-name> ホスト非依存で予測可能な宣言型API識別元 安定していてテナント適格ですが、クライアントには識別子を明示的に与える必要があります。

URIは有効で、テナント内で一意であり、テナントのApplication ID URIポリシーに受け入れられなければなりません。 some-random-stringのような単純な文字列は有効なアプリケーションID URIではありません。

このガイドでは、HTTPS App Serviceの全URLを使用しています:

https://<app-name>.azurewebsites.net
  1. Microsoft プロバイダーの構成が完了したら、[ ID プロバイダー ] 列でそれを選択して、アプリの登録ページを開きます。

  2. 左側のメニューで、[管理] >[API をExpose] を選択します。

  3. [アプリケーション ID URI] の横にある [編集] を選択します。

  4. 値をApp Serviceアプリの完全なHTTPSURLに変更してください。例えば https://<app-name>.azurewebsites.net

    アプリのホスト名は、既定のドメイン[概要] ページにあります。

  5. 新しいアプリ登録の場合は、 アクセストークンのバージョン2に設定してください。

  6. 保存 を選択します。

Warnung

App Service アプリを削除する場合は、アプリの登録を削除し、アプリケーション ID URI を参照するすべての認証リソースをクリーンアップする必要もあります。 Microsoft Entraアプリケーションはテナントリソースであり、App Serviceリソースグループで削除されることはありません。 登録を削除しないとセキュリティ上の脆弱性が生じます。もし誰かが同じURLでアプリを作成した場合、孤立したアプリ登録を信頼するリソースに不正アクセスを得られる可能性があります。

後でApplication ID URIを変更するには、FoundryツールのオーディエンスやAPIのトークンを要求するすべてのクライアントを更新する必要があります。

対応するOpenAPIツールの認証設定は以下の通りです:

{
  "type": "managed_identity",
  "security_scheme": {
    "audience": "https://<app-name>.azurewebsites.net"
  }
}

ツールのオーディエンスを 「許可トークンオーディエンス」にリストアップする必要はありません。 App Service認証は、Microsoft Entraアプリケーションに登録したリソース識別子を認識します。 逆に、Allowed token audiencesのみに値を追加するとOAuthリソースが登録されず、Microsoft Entraがトークンを発行することもできません。

その値そのものを Application ID URI としても構成している場合を除き、Foundry プロジェクトのエンドポイントや App Service クライアント ID をオーディエンスとして使用しないでください。 他の有効なアプリケーションID URIフォーマット( api:// URIを含む)は、登録値とオーディエンスが正確に一致した場合に機能します。 関連する例外ケースについては、 よくある質問をご覧ください。

保護されたAPIを宣言的に設定してください

保護されたAPIとApp Service認証ポリシーを設定するには、Bicepを使ってください。 以下のパターンは以下を前提としています:

  • webApp はApp Serviceリソースです。
  • entraAppはApp Service認証のMicrosoft Entraアプリケーションを作成するモジュールです。
  • foundryAccountClientId は親Foundryリソース識別のアプリケーションIDです。
  • appServiceAuthCredentialSettingName は既存のApp Service認証クライアント秘密を含むアプリ設定の名前です。

Microsoft Graph Bicepアプリケーションモジュールで、App Service URLを識別子URIとして設定し、バージョン2のアクセストークンを要求します:

extension microsoftGraphV1

param environmentName string
param appServiceUrl string

resource app 'Microsoft.Graph/applications@v1.0' = {
  uniqueName: 'my-app-${environmentName}'
  displayName: 'My app (${environmentName})'
  signInAudience: 'AzureADMyOrg'
  identifierUris: [
    appServiceUrl
  ]
  api: {
    requestedAccessTokenVersion: 2
  }
  web: {
    homePageUrl: appServiceUrl
    redirectUris: [
      '${appServiceUrl}/.auth/login/aad/callback'
    ]
  }
}

output clientId string = app.appId
output webAppUrl string = appServiceUrl

以下の authsettingsV2 例は、インタラクティブなブラウザのサインインとFoundry OpenAPIの両方の呼び出しを可能にします:

@description('Parent Foundry resource identity application ID')
param foundryAccountClientId string = ''

resource webAppAuthSettings 'Microsoft.Web/sites/config@2024-11-01' = {
  name: '${webApp.name}/authsettingsV2'
  properties: {
    platform: {
      enabled: true
    }
    globalValidation: {
      requireAuthentication: true
      unauthenticatedClientAction: 'RedirectToLoginPage'
      redirectToProvider: 'azureActiveDirectory'
    }
    identityProviders: {
      azureActiveDirectory: {
        enabled: true
        registration: {
          clientId: entraApp.outputs.clientId
          clientSecretSettingName: appServiceAuthCredentialSettingName
          openIdIssuer: 'https://login.microsoftonline.com/${tenant().tenantId}/v2.0'
        }
        validation: {
          allowedAudiences: [
            'api://${entraApp.outputs.clientId}'
          ]
          defaultAuthorizationPolicy: {
            allowedApplications: concat(
              [
                entraApp.outputs.clientId
              ],
              empty(foundryAccountClientId) ? [] : [foundryAccountClientId]
            )
            allowedPrincipals: {}
          }
        }
      }
    }
    login: {
      tokenStore: {
        enabled: true
      }
    }
    httpSettings: {
      requireHttps: true
    }
  }
}

Foundry resource identity application ID を Azure Developer CLI (AZD) で渡してください:

{
  "foundryAccountClientId": {
    "value": "${AZURE_AI_FOUNDRY_ACCOUNT_CLIENT_ID=}"
  }
}

その後、環境を設定して再デプロイします:

azd env set AZURE_AI_FOUNDRY_ACCOUNT_CLIENT_ID <application-id>
azd provision

App Service認証がクライアントシークレットを使う場合は、既存のシークレット設定を維持してください。 完全宣言型シークレットレス展開の場合、App Service認証はユーザー割り当ての管理IDとフェデレーテッドID認証を使用できます。 その認証情報は、OpenAPIエンドポイントを呼び出す親FoundryリソースIDとは別です。

Microsoft Foundry で OpenAPI ツールを構成する

このセクションでは、「 前提条件」 セクションのチュートリアルの 1 つを既に完了していることを前提としています。ここで、匿名認証を使用して Microsoft Foundry で OpenAPI ツールとしてアプリを追加しました。 これで、マネージド ID 認証を使用するようにツールを更新します。

  1. Foundry ポータルに戻り、エージェントを選択します。

  2. OpenAPI ツールを見つけて、...> を選択します編集。

  3. OpenAPI 3.0+のスキーマボックスにApp Serviceアプリのスキーマが含まれているか確認してください。 もしダメなら、OpenAPIスキーマを貼り付けてください。 詳細については、「 Foundry Agent Service で OpenAPI を使用する方法」を参照してください。

  4. [認証方法] で、[マネージド ID] を選択します

  5. Audienceでは、先に設定したApplication ID URIを入力してください。 このガイドの設定では、App Serviceアプリの完全なHTTPS URL(例えば https://<app-name>.azurewebsites.net)を使ってください。 値が完全に一致していなければなりません。

  6. [ 更新ツール] を選択します

ヒント

Foundry Agent Serviceは、親リソースのシステム割り当て管理IDを使ってアプリと認証します。 Foundryのみのポリシーでは、アプリケーションIDがクライアントアプリケーションを認可し、オブジェクトIDがアイデンティティを承認します。 アプリがインタラクティブなブラウザサインインをサポートしている場合、アプリ独自のアプリケーションIDがユーザーのサインイントークンを承認し、ポリシーは設定されたテナントからの任意のIDを許可します。

エージェントをテストする

  1. Foundry ポータルで、エージェントを選択し、[ プレイグラウンドで試す] を選択します。

  2. エージェントとチャットして、OpenAPI エンドポイントをテストします。 例えば次が挙げられます。

    • すべてのタスクを表示します。
    • "食料品の購入" というタスクを作成します。
    • そのタスクを 「食料品を購入して夕食を作る」に更新します。

正しく認証を設定していれば、エージェントはOpenAPIツールを通じてアプリのAPIを呼び出します。

よく寄せられる質問

なぜApp Service認証を設定する前にOpenAPIツールを保存できるのですか?

OpenAPIツールを保存すると、Foundryはそのスキーマ、オーディエンスフォーマット、定義を検証します。 App Serviceエンドポイントを呼び出すことはありません。 したがって、親FoundryリソースIDをApp Serviceの許可リストに追加する前にツールを保存できます。

プレイグラウンドや実行時にツールを呼び出す前に、許可リストを設定してください。 それまでは、App Serviceはツール呼び出しを拒否します。

なぜデフォルトの api://<client-id> オーディエンスは時々失敗するのでしょうか?

App Serviceポータルは、api://<application-client-id>をApplication ID URIとしてMicrosoft Entraアプリケーションを作成することが一般的です。 その場合、Foundryはオーディエンスと同じ価値を利用できます。

カスタムまたは宣言型のプロビジョニングでは、App Service 認証の identifierUrisapi://<client-id> が表示されている場合でも、Microsoft Entra アプリケーションの コレクションが空になることがあります。 その状態では、Foundryはその値の管理IDトークンを取得することができません。なぜなら、その値が登録されたリソース識別子でないからです。

問題を解決するには、以下のいずれかの方法をご利用ください:

  • api://<client-id>をアプリケーションID URIとして登録し、Foundryのオーディエンスとして使用してください。
  • App Service HTTPS URLをApplication ID URIとして登録し、そのURLをFoundryのオーディエンスとして使用してください。

allowedAudiencesに任意の文字列を追加して不一致を解決しないでください。

App Service認証はApplication ID URIなしで機能しますか?

インタラクティブなブラウザサインインは、ブラウザフローがウェブアプリケーションのクライアントIDにIDトークンを使用するため、アプリケーションID URIなしで動作します。

FoundryのマネージドアイデンティティOpenAPIフローには、登録されたAPIリソースのためのアクセストークンが必要です。 このフローでは、Application ID URIを設定し、ツールオーディエンスと同じ値を使用します。

認証と認可のトラブルシューティング

OpenAPIツールはHTTP 401を受け取ります

HTTP 401応答の場合、App Service認証がリクエストを認証できなくなります。 次の原因が考えられます。

  • OpenAPIツールでマネージドアイデンティティを選択していません。
  • 対象者はMicrosoft EntraのApplication ID URIとは完全に一致しません。
  • トークン発行者やテナントがApp Service認証と一致しません。
  • Microsoft EntraアプリケーションでApplication ID URIを設定していません。

OpenAPIのオーディエンスが登録されたApplication ID URIと正確に一致しているか確認してください。 このガイドの設定では、この値はApp Serviceの完全なHTTPS URLです。

OpenAPIツールはHTTP 403を受信します

HTTP 403応答は認証に成功したが、承認チェックが呼び出し元を拒否したことを意味します。 次の原因が考えられます。

  • 許可リストには親のFoundryリソース識別子ではなく、Foundryプロジェクトのアイデンティティを追加しました。
  • App Service認証が必要な場合、オブジェクトIDを入力しました。
  • 親リソースアプリケーションIDを allowedApplicationsに追加していません。
  • Foundry専用の設定で親リソースオブジェクトIDを許可されたアイデンティティリストに追加していません。

アクセストークンの主張を調べてください:

  • azp 親のFoundryリソース識別子のアプリケーションIDと等しいはずです。
  • oid 親のFoundryリソース識別元のオブジェクトIDと等しいはずです。

ブラウザユーザーはサインイン後にHTTP 403を受け取ります

インタラクティブなブラウザサインインをサポートするアプリについては、以下の設定を確認してください:

  • ウェブアプリ自身のクライアントIDは allowedApplicationsのままです。
  • アイデンティティ要件により通常のテナントユーザーも許可されています。
  • 認証されていないブラウザリクエストはHTTP 401ではなくHTTP 302を使用します。

このツールは匿名で動作しますが、認証を有効にすると失敗します

ツールを匿名から管理型アイデンティティに更新し、オーディエンスを登録済みのApplication ID URIに設定し、親FoundryリソースIDを許可します。

リソースをクリーンアップする

このシナリオからリソースを削除または置き換える場合:

  • Foundryリソースを削除または置き換える際に、親Foundryリソース識別子をApp Service認証から削除してください。
  • App Serviceアプリを永久に削除する際には、App Service認証のMicrosoft Entraアプリケーションを削除してください。 このステップは、先述の孤児Application ID URIリスクも防ぐものです。
  • ユーザー割り当て ID とフェデレーション ID 資格情報を使用してシークレットレスの App Service 認証を行う場合は、アプリと一緒にその ID とフェデレーション資格情報を削除してください。