ExternalCallout policy

本頁內容適用於 ApigeeApigee Hybrid

查看 Apigee Edge 說明文件。

政策圖示

結果

您可以使用 ExternalCallout 政策,將 gRPC 要求傳送至 gRPC 伺服器,藉此實作 Apigee 政策不支援的自訂行為。在伺服器的程式碼中,您可以輕鬆存取及修改 Proxy 流程中的流程變數。

Apigee 會透過 API,透過 ExternalCallout 政策與 gRPC 伺服器通訊。 Apigee 會使用 API 將流程變數傳送至 gRPC 伺服器。 在 gRPC 伺服器中,您可以讀取 (並視變數而定,修改)「流程變數」參考頁面中列出的流程變數,以及您在政策 XML 中指定的其他變數。

如果您使用 Apigee 設定 gRPC 伺服器,並在 Proxy 中加入這項政策,Apigee 會按照下列方式處理 API 要求:

  1. Apigee 會將含有流程變數的訊息傳送至 gRPC 伺服器。
  2. gRPC 伺服器程式碼會執行,並存取及修改程式碼中定義的變數。然後,gRPC 伺服器會將包含所有流程變數的回應傳回 Apigee。
  3. Apigee 會讀取 gRPC 伺服器的回應。如果新增任何變數或修改可修改的流程變數,系統就會在 Apigee 中更新這些變數。

這項政策屬於標準政策,可部署至任何環境類型。如要瞭解各環境類型適用的政策類型和可用性,請參閱「政策類型」。

如要進一步瞭解如何傳送 gRPC 要求,請參閱下列連結:

<ExternalCallout>

定義 ExternalCallout 政策。

<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">

這個元素包含下列所有政策都適用的屬性:

屬性 預設 是否必要? 說明
name 不適用 必要

政策的內部名稱。name 屬性的值可以包含英文字母、數字、空格、連字號、底線和句號。這個值不得超過 255 個半形字元。

您可以選擇使用 <DisplayName> 元素,在管理 UI 代理程式編輯器中為政策加上不同、自然語言的名稱。

continueOnError false 選用 將其設為 false,即可在政策失敗時傳回錯誤。這是大多數政策的預期行為。將其設為 true,即使政策失敗,流程執行作業仍會繼續進行。另請參閱:
enabled 選用 設為 true 即可強制執行政策。設為 false 即可關閉政策。即使政策仍附加至流程,系統也不會強制執行這項政策。
async   false 已淘汰 此屬性已淘汰。

下表說明 <ExternalCallout> 的子元素。

子元素 必填 說明
<TimeoutMs> 必填 gRPC 要求的逾時時間 (以毫秒為單位)。
<GrpcConnection> 必填 指定現有 TargetServer 的名稱,做為要傳送要求的 gRPC 伺服器。
<Configurations> 選用 可讓您設定 ExternalCallout 政策的各個層面,包括 <Property><FlowVariable> 元素。

範例 1

如需 ExternalCallout 的工作範例,請前往 GitHub 的「External Callout Samples」。

以下範例說明 ExternalCallout 政策設定。

<ExternalCallout enabled="true" continueOnError="false" name="ExternalCallout-1">
  <DisplayName>External Callout 1</DisplayName>
  <TimeoutMs>5000</TimeoutMs>
  <GrpcConnection>
    <Server name="external-target-server"/>
  </GrpcConnection>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">false</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">false</Property>
    <FlowVariable>example1.flow.variable</FlowVariable>
    <FlowVariable>example2.flow.variable</FlowVariable>
  </Configurations>
<ExternalCallout>

這個範例會將要求傳送至以名為 external-target-server TargetServer 代表的外部 gRPC 伺服器,並採用下列設定:

  • <Property>:在傳送至 gRPC 伺服器的要求中,納入要求和回應內容,但不納入要求和回應標頭。
  • <FlowVariable>:在傳送至 gRPC 伺服器的要求中,加入 example1.flow.variableexample2.flow.variable,以及 FlowVariable 元素指定的其他流程變數

範例 2

在以下範例中,Audience 元素的 useTargetUrl 屬性設為 true。如果 useTargetUrltrue,則 gRPC 目標伺服器的主機名稱會做為對象。舉例來說,如果伺服器主機是 my-grpc-server-java.a.run.app,則使用的目標對象為 https://my-grpc-server-java.a.run.app

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience useTargetUrl="true"/>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>

子元素參照

以下各節說明 ExternalCallout 的子項元素。

<TimeoutMs>

gRPC 要求的逾時時間 (以毫秒為單位)。<TimeoutMs> 必須是正數。

<GrpcConnection>

<GrpcConnection> 元素會將 gRPC 伺服器設為現有的 TargetServer,並由 name 屬性指定。請參閱 TargetServer 資源參考頁面。

注意:TargetServer 的通訊協定必須為 GRPC

舉例來說,下列程式碼

<GrpcConnection>
  <Server name="external-target-server"/>
</GrpcConnection>

指定 gRPC 伺服器為現有的 TargetServer 名為 external-target-server

使用 <Authentication> 元素 (本節稍後會說明),產生 Google 發行的 OpenID Connect 權杖,向以 gRPC 為基礎的服務 (例如在 Cloud Run 中代管的自訂服務) 發出經過驗證的呼叫。

下表說明 <GrpcConnection> 的子元素。

子元素 是否必要 說明
<Server> 元素 必要 指定 gRPC 伺服器。
<Authentication> 元素 選用 產生 Google 發行的 OpenID Connect 權杖,向以 gRPC 為基礎的服務 (例如 Cloud Run) 發出已驗證的呼叫。

<Server> 元素

指定 gRPC 伺服器。

下表說明 <Server> 元素的屬性。

屬性 說明 預設 存在必要性 類型
name

現有 TargetServer 的名稱,gRPC 伺服器會將要求傳送至該名稱。

不適用 必填 字串

<Authentication> 元素

產生 Google 發行的 OpenID Connect 權杖,對以 gRPC 為基礎的服務 (例如託管於 Cloud Run 的自訂服務) 進行已驗證的呼叫。如要使用這個元素,請按照「使用 Google 驗證」一文所述的步驟進行設定及部署。設定完成後,這項政策會為您建立驗證權杖,並將其新增至服務要求。

這個元素有一個必要子元素:GoogleIDToken

預設 不適用
必填與否 選填。
類型 複雜型別
父項元素 <GrpcConnection>
子元素 <GoogleIDToken>

Authentication 元素使用下列語法:

語法

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
      <GoogleIDToken>
         <Audience ref="variable-1">STRING</Audience>
         <IncludeEmail ref="variable-2">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

範例

以下範例顯示 GoogleIDToken 元素:

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
     <Server name="cloud_run_server_name"/>
     <Authentication>
        <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
        <GoogleIDToken>
           <Audience>https://cloudrun-hostname.a.run.app</Audience>
        </GoogleIDToken>
     </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>
屬性

無。

<HeaderName> 子項元素

根據預設,如果存在驗證設定,Apigee 會產生不記名權杖,並將其插入傳送至目標系統的訊息中的 Authorization 標頭。HeaderName 元素可讓您指定其他標頭的名稱,用來保存該不記名權杖。如果目標是使用 X-Serverless-Authorization 標頭的 Cloud Run 服務,這項功能就特別實用。如果存在 Authorization 標頭,則會保留不變,並一併傳送至要求。

預設 不適用
必填與否
類型 字串
父項元素 <Authentication>
子元素

HeaderName 元素使用下列語法:

語法

<ExternalCallout>
...
  <Authentication>
    <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
    <GoogleIDToken>
    ... 
    </GoogleIDToken>
  </Authentication>
  ...
</ExternalCallout>

使用靜態字串

在本例中,系統預設會將產生的不記名權杖新增至名為 X-Serverless-Authorization 的標頭,並傳送至目標系統。如果存在 Authorization 標頭,則會保留不變,並一併傳送至要求。

<Authentication>
  <HeaderName>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>

含變數參照

在本例中,系統預設會將產生的不記名權杖新增至名為 X-Serverless-Authorization 的標頭,並傳送至目標系統。如果 my-variable 有值,系統會使用該值,而非預設字串。如果存在 Authorization 標頭,則會保留不變,並一併傳送至要求。

<Authentication>
  <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>
<GoogleIDToken> 子元素

產生 Google 發行的 OpenID Connect 權杖,以便向 Google 服務 (例如託管於 Cloud Run 的自訂服務) 發出經過驗證的呼叫。

預設 不適用
必填與否 必填
類型 字串
父項元素 <Authentication>
子元素 <Audience>
<IncludeEmail>

GoogleIDToken 元素使用下列語法:

語法

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience ref="context-variable" useTargetUrl='BOOLEAN'>STRING</Audience>
        <IncludeEmail ref="context-variable">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

範例

以下範例顯示 GoogleIDToken 元素:

<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
<Audience> 子元素

產生的驗證權杖適用對象,例如權杖授予存取權的 API 或帳戶。

如果 Audience 的值為空,ref 為空或解析為空值,且 useTargetUrltrue,則「https://」+ (gRPC 目標伺服器的主機名稱) 會做為目標對象。舉例來說,如果伺服器主機是 my-grpc-server-java.a.run.app,則使用的目標對象會是 https://my-grpc-server-java.a.run.app

根據預設,useTargetUrlfalse

<Audience>explicit-audience-value-here</Audience>

or:

<Audience ref='variable-name-here'/>

or:

<Audience ref='variable-name-here' useTargetUrl='true'/>

or:

<Audience useTargetUrl='true'/>
預設 不適用
必填與否 必填
類型 字串
父項元素 <GoogleIDToken>
子元素
<IncludeEmail> 子元素

如果設為 true,產生的驗證權杖會包含服務帳戶 emailemail_verified 聲明。

預設 false
必填與否 選用
類型 布林值
父項元素 <GoogleIDToken>
子元素

<Configurations>

<Configurations> 元素可讓您設定 ExternalCallout 政策的各個層面,包括 <Property><FlowVariable>

下表說明 <Configurations> 的子元素。

子元素 是否必要 說明
<Property> 必要

指定是否要將要求/回應標頭和/或內容傳送至伺服器。可能的值為 truefalse。 預設值為 false

<FlowVariable> 必要

指定應傳送至伺服器的其他流程變數。

<Property>

<Property> 元素會指定要求/回應標頭和/或內容是否會傳送至伺服器。可能的值為 true (系統會傳送項目) 或 false (系統不會傳送項目)。預設值為 false

下表說明 <Property> 元素的屬性。

屬性 說明 預設 存在必要性 類型
name

指定要傳送至伺服器的內容。name 的可能值包括:

  • with.request.content
  • with.request.headers
  • with.response.content
  • with.response.headers
不適用 必填 字串

<FlowVariable>

<FlowVariable> 元素會指定要傳送至伺服器的其他流程變數。<FlowVariable> 的值是變數的前置字串,而非完整變數名稱。舉例來說,如果 元素是 a.b.c,系統會將名為 a.b.c 的變數值傳送至伺服器。同樣地,系統會將名為 a.b.c.my-variable 的變數值傳送至伺服器。但系統不會傳送名為 a.x.another-variable 的變數值,因為該變數沒有 a.b.c 前置字串。以下列舉幾個例子

<Configurations>
  <FlowVariable>a.b.c</FlowVariable>
  <FlowVariable>d.e.f</FlowVariable>
</Configurations>

錯誤參考資料

部署錯誤

錯誤名稱 原因
FAILED_PRECONDITION 如果使用 <Authentication> 標記設定 Proxy 時缺少服務帳戶,就會發生這個錯誤。

例如:

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED 如果 Proxy 是使用 <Authentication> 標記設定,服務帳戶發生權限問題時就會發生這個錯誤。可能原因:
  • 服務帳戶不存在。
  • 服務帳戶並非在與 Apigee 機構相同的 Google Cloud 專案中建立。
  • 部署者具備服務帳戶的 iam.serviceAccounts.actAs 權限。詳情請參閱「關於服務帳戶權限」。

執行階段錯誤

下表說明政策執行時可能發生的執行階段錯誤。

錯誤碼 HTTP 狀態 原因
GrpcTlsInitFailed 500

如果使用 gRPC 伺服器初始化 TLS 時發生任何問題 (例如金鑰儲存區或信任儲存區問題),就會發生這個錯誤。

steps.externalcallout.[error_code] 500

[error_code] 是由 Fault 訊息的 errorCode 欄位決定。錯誤的錯誤字串會是錯誤訊息的 faultstring 欄位。

steps.externalcallout.ExecutionError 500

如果執行這項政策時發生任何其他例外狀況,就會出現這個錯誤。基礎例外狀況會顯示在 faultstring 中。 如果 gRPC 伺服器的憑證有問題,錯誤訊息會類似如下:

{
  "fault": {
    "faultstring": "Encountered the following exception while sending the gRPC request or
     processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed
     to obtain metadata].",
    "detail": {
      "errorcode": "steps.externalcallout.ExecutionError"
    }
  }
}

您可以查看 MP 的記錄,取得進一步的偵錯指標。

googletoken.EmptyIDTokenAudience 500

已啟用 <GoogleIDToken>,但 useTargetUrl 設為 false,且未直接或透過參照,在發生錯誤時提供值給 <Audience>

steps.externalcallout.ExecutionError

錯誤字串:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata]

500

如果 API Proxy 是使用 <Authentication> 元素設定,就會發生這個錯誤。 可能原因:

  • 透過 Proxy 部署的服務帳戶:
    • 不存在於專案中 (部署時存在,但部署後已刪除)
    • 已停用
    • (僅限 Apigee Hybrid) 尚未在 apigee-runtime 服務帳戶中授予 roles/iam.serviceAccountTokenCreator 角色。
  • (僅限 Apigee Hybrid) IAMCredentials API 已在 apigee-runtime 服務帳戶的來源專案中停用。

    注意:僅限 Apigee Hybrid,請檢查執行階段容器的記錄檔,並搜尋 externalcallout.ExecutionError,找出可能有助於偵錯問題的詳細錯誤訊息。

steps.externalcallout.ExecutionError,且 faultstring 包含 PERMISSION DENIED

舉例來說,Cloud Run 的 faultstring 如下所示:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: PERMISSION_DENIED: HTTP status code 403 …]

500

如果 API Proxy 是使用 <Authentication> 元素設定,就會發生這個錯誤。可能原因:

  • 代理服務帳戶存在且已啟用,但沒有存取服務的正確權限。
  • 服務需要驗證,但要求沒有驗證標頭 (例如:政策 XML 中未包含驗證 XML)。

其他錯誤

下表說明其他錯誤。詳情請參閱原因。

錯誤碼 原因
ReferencesExistToGrpcServer

如果使用者嘗試刪除 gRPC 目標伺服器,但該伺服器仍由其他政策使用,就會發生這個錯誤。

斷層

下表中的錯誤變數預設會為所有政策設定。請參閱「 與政策錯誤相關的變數」。

變數 地點 範例
fault.name="fault_name" fault_name 是故障名稱,如上方的「執行階段錯誤」表格所示。故障名稱是故障代碼的最後一部分。 fault.name 與「ExecutionError」相符。
externalcallout.[policy_name].failed policy_name 是使用者指定的政策名稱,該政策擲回了錯誤。 externalcallout.ExternalCallout-1.failed = true

相關主題