アンチパターン: API プロキシから Management API を呼び出す

Edge には「管理 API」と呼ばれる強力なユーティリティがあり、以下のようなサービスを提供します。

  • API プロキシのデプロイとデプロイ解除
  • 仮想ホスト、キーストア、トラストストアなどの構成
  • KeyValueMap、API プロダクト、デベロッパー アプリ、デベロッパー、コンシューマ キーなどのエンティティの作成、削除、更新
  • これらのエンティティの情報の取得

これらのサービスには、Apigee Edge プラットフォームの Management Server と呼ばれるコンポーネントを通じてアクセスできます。シンプルな Management API 呼び出しを利用して、これらのサービスを簡単に呼び出すことができます。

ランタイム時に、API プロキシからこれらのサービスを使用しなければならない場合があります。その理由は、KeyValueMap、OAuth アクセス トークン、API プロダクト、デベロッパー アプリ、デベロッパー、コンシューマ キーなどのエンティティに、Key-Value ペアやカスタム属性の形式で、またはプロファイルの一部として、有益な情報が含まれているからです。

たとえば、KeyValueMap 内に以下のような情報を格納すると、ランタイム時にセキュリティを確保しながらアクセス可能にできます。

  • バックエンドのターゲット URL
  • 環境プロパティ
  • バックエンドまたはサードパーティ システムのセキュリティ認証情報

同様に、ランタイム時に API プロダクトのリストやデベロッパーのメールアドレスを取得する必要が生じることがあります。これらの情報は、デベロッパー アプリのプロファイルの一部として取得可能です。

これらすべての情報をランタイム時に効果的に使用することにより、Apigee Edge 内のポリシーやカスタムコードで動的な動作を実現できます。

アンチパターン

管理 API は管理タスクを行うのに便利であり、推奨される方法です。しかし、API プロキシのフロー内でランタイム ロジックを実行するために管理 API を使用すべきではありません。理由は次のとおりです。

  • KeyValueMap、OAuth アクセス トークンなどのエンティティに関する情報へのアクセス、または API プロキシの他の目的で管理 API を使用することは、Management Server への依存につながります。
  • Management Server は Edge ランタイム コンポーネントに含まれないので、可用性がそれほど高くない可能性があります。
  • また、Management Server は必ずしも同じネットワークやデータセンター内にプロビジョニングされるわけではありません。そのためランタイム時にネットワークのレイテンシが発生する場合があります。
  • Management Server 内のエントリがキャッシュされる期間は長いので、短期間に書き込みと読み込みを実行した場合、API プロキシで最新のデータをすぐに表示できないことがあります。
  • ランタイム時にネットワーク ホップが増加します。

以下のコードサンプルでは、JavaScript のカスタムコードによって Management API を呼び出し、KeyValueMap から情報を取得します。

var response = httpClient.send('https://api.enterprise.apigee.com/v1/o/org_name/e/env_name/keyvaluemaps/kvm_name')

Management Server が利用不可の場合、Management API を呼び出す JavaScript コードは失敗します。これにより、以降の API リクエストも失敗することになります。

影響

  • ランタイム時に Management Server への依存性がさらに増します。Management Server の障害は API 呼び出しに影響を与えます。
  • 管理 API のユーザー認証情報を、ローカルに保管するか、または暗号化された KVM などの安全な保存場所に保管する必要があります。
  • ネットワークを介して管理サービスを呼び出すことによるパフォーマンスの影響。
  • Management Server ではキャッシュの保存期間が長いため、最新の値がすぐに表示されない場合があります。

ベスト プラクティス

ランタイム時に KeyValueMap、API プロダクト、デベロッパー アプリ、デベロッパー、コンシューマ キーなどのエンティティから情報を取得する効率的な方法は他にもあります。いくつかの例を示します。

  • KeyValueMapOperations ポリシーを使用して、KeyValueMap の情報にアクセスします。以下のサンプルコードは、KeyValueMap から情報を取得する方法を示しています。
    <!-- /antipatterns/examples/2-6.xml -->
    <KeyValueMapOperations mapIdentifier="urlMap" async="false"
        continueOnError="false" enabled="true" name="GetURLKVM">
      <DisplayName>GetURLKVM</DisplayName>
      <ExpiryTimeInSecs>86400</ExpiryTimeInSecs>
      <Scope>environment</Scope>
      <Get assignTo="urlHosti" index="2">
        <Key>
          <Parameter>urlHost_1</Parameter>
        </Key>
      </Get>
    </KeyValueMapOperations>
  • API プロダクト、デベロッパー アプリ、デベロッパー、コンシューマ キーなどの情報に API プロキシ内でアクセスするには、以下のいずれかの方法を利用します。
    • API プロキシのフローに VerifyAPIKey ポリシーがある場合は、このポリシーの中で設定されたフロー変数を使用して情報にアクセスできます。以下のサンプルコードは、JavaScript を使用してデベロッパー アプリの名前と created_by の情報を取得する方法を示しています。
      <!-- /antipatterns/examples/2-7.xml -->
      print("Application Name ", context.getVariable(""verifyapikey. VerifyAPIKey.app.name"));
      print("Created by:", context.getVariable("verifyapikey. VerifyAPIKey.app.created_by"));
    • API プロキシのフローに VerifyAPIKey ポリシーがない場合は、Access Entity ポリシーと Extract Variables ポリシーを使用して、API プロダクトやデベロッパー アプリなどのプロファイルにアクセスできます。
      1. AccessEntity ポリシーを使用して DeveloperApp のプロファイルを取得します。
        <!-- /antipatterns/examples/2-8.xml -->
        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <AccessEntity async="false" continueOnError="false" enabled="true" name="GetDeveloperApp">
          <DisplayName>GetDeveloperApp</DisplayName>
          <EntityType value="app"></EntityType>
          <EntityIdentifier ref="developer.app.name" type="appname"/>
          <SecondaryIdentifier ref="developer.id" type="developerid"/>
        </AccessEntity>
      2. ExtractVariables ポリシーを使用して、DeveloperApp から appId を抽出します。
        <!-- /antipatterns/examples/2-9.xml -->
        <ExtractVariables name="Extract-Developer App-Info">
          <!--
            The source element points to the variable populated by AccessEntity policy.
            The format is <policy-type>.<policy-name>
            In this case, the variable contains the whole developer profile.
          -->
          <Source>AccessEntity.GetDeveloperApp"</Source>
          <VariablePrefix>developerapp</VariablePrefix>
          <XMLPayload>
            <Variable name="appld" type="string">
              <!-- You parse elements from the developer profile using XPath. -->
              <XPath>/App/AppId</XPath>
            </Variable>
          </XMLPayload>
        </ExtractVariables>

関連情報