ExternalCallout 정책

이 페이지는 ApigeeApigee Hybrid에 적용됩니다.

Apigee Edge 문서 보기

정책 아이콘

대상

ExternalCallout 정책을 사용하면 Apigee 정책으로 지원되지 않는 커스텀 동작을 구현하기 위해 gRPC 요청을 gRPC 서버로 전송할 수 있습니다. 서버 코드에서 프록시 흐름 내에서 흐름 변수에 쉽게 액세스하고 이를 수정할 수 있습니다.

Apigee는 API에서 ExternalCallout 정책을 통해 gRPC 서버와 통신합니다. Apigee는 API를 사용하여 흐름 변수를 gRPC 서버로 전송합니다. gRPC 서버 내에서 정책 XML 내에 지정하는 추가 변수는 물론 흐름 변수 참조 페이지에 나열된 흐름 변수를 읽고, 변수에 따라 수정할 수도 있습니다.

Apigee로 gRPC 서버를 구성하고 이 정책을 프록시에 포함하면 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 선택 정책을 시행하려면 true로 설정합니다. 정책을 중지하려면 false로 설정합니다. 정책이 흐름에 연결되어 있어도 정책이 시행되지 않습니다.
async   false 지원 중단됨 이 속성은 지원이 중단되었습니다.

다음 표에서는 <ExternalCallout>의 하위 요소를 설명합니다.

하위 요소 필수 설명
<TimeoutMs> 필수 gRPC 요청에 대한 요청 제한 시간(밀리초)입니다.
<GrpcConnection> 필수 요청을 전송할 gRPC 서버로 사용할 기존 TargetServer의 이름을 지정합니다.
<Configurations> 선택사항 <Property><FlowVariable> 요소를 포함하여 ExternalCallout 정책의 여러 측면을 구성할 수 있습니다.

예 1

ExternalCallout의 작업 예시는 GitHub의 External Callout 샘플에서 이용하세요.

다음 예시는 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 서버에 전송된 요청에서 FlowVariable 요소로 지정된 추가적인 흐름 변수 example1.flow.variableexample2.flow.variable을 포함합니다.

예 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> 요소는 name 속성으로 지정된 기존 TargetServer가 되도록 gRPC 서버를 설정합니다. TargetServer 리소스 참조 페이지를 참조하세요.

참고: TargetServer프로토콜GRPC여야 합니다.

다음 코드를 예로 들어 보겠습니다.

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

external-target-server라는 기존 TargetServer가 될 gRPC 서버를 지정합니다.

<Authentication> 요소(이 섹션의 뒷부분에서 설명)를 사용하여 Google에서 발급한 OpenID Connect 토큰을 생성하여 Cloud Run에서 호스팅되는 커스텀 서비스와 같은 gRPC 기반 서비스에 인증된 호출을 수행합니다.

다음 표에서는 <GrpcConnection>의 하위 요소를 설명합니다.

하위 요소 필수 여부 설명
<Server> 요소 필수 gRPC 서버를 지정합니다.
<Authentication> 요소 선택사항 Google에서 발급한 OpenID Connect 토큰을 생성하여 Cloud Run과 같은 gRPC 기반 서비스에 인증된 호출을 수행합니다.

<Server> 요소

gRPC 서버를 지정합니다.

다음 표에서는 <Server> 요소 속성을 설명합니다.

속성 설명 기본값 Presence 유형
name

요청을 전송할 gRPC 서버가 될 기존 TargetServer의 이름입니다.

해당 사항 없음 필수 문자열

<Authentication> 요소

Google에서 발급한 OpenID Connect 토큰을 생성하여 Cloud Run에서 호스팅되는 커스텀 서비스와 같은 gRPC 기반 서비스에 인증된 호출을 수행합니다. 이 요소를 사용하려면 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는 Bearer 토큰을 생성하고 이를 대상 시스템으로 전송된 메시지의 Authorization 헤더에 삽입합니다. HeaderName 요소를 사용하면 해당 Bearer 토큰을 보유할 다른 헤더의 이름을 지정할 수 있습니다. 이 기능은 대상이 X-Serverless-Authorization 헤더를 사용하는 Cloud Run 서비스인 경우에 특히 유용합니다. Authorization 헤더가 있는 경우 수정되지 않은 상태로 유지되며 요청에도 전송됩니다.

기본값 해당 사항 없음
필수 여부 아니요
유형 문자열
상위 요소 <Authentication>
하위 요소 없음

HeaderName 요소는 다음 문법을 사용합니다.

구문

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

정적 문자열 사용

이 예시에서는 생성된 Bearer 토큰이 기본적으로 대상 시스템으로 전송되는 X-Serverless-Authorization이라는 헤더에 추가됩니다. Authorization 헤더가 있는 경우 수정되지 않은 상태로 유지되며 요청에도 전송됩니다.

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

변수 참조 사용

이 예시에서는 생성된 Bearer 토큰이 기본적으로 대상 시스템으로 전송되는 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 토큰을 생성하여 Cloud Run에서 호스팅되는 커스텀 서비스와 같은 Google 서비스에 인증된 호출을 수행합니다.

기본값 해당 사항 없음
필수 여부 필수
유형 문자열
상위 요소 <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입니다.

useTargetUrl의 기본값은 false입니다.

<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> 요소를 사용하면 <Property><FlowVariable>을 포함하여 ExternalCallout 정책의 여러 특성을 구성할 수 있습니다.

다음 표에서는 <Configurations>의 하위 요소를 설명합니다.

하위 요소 필수 여부 설명
<Property> 필수

요청/응답 헤더 또는 콘텐츠가 서버로 전송되는지 여부를 지정합니다. 가능한 값은 true 또는 false입니다. 기본값은 false입니다.

<FlowVariable> 필수

서버로 전송할 추가적인 흐름 변수를 지정합니다.

<Property>

<Property> 요소는 요청/응답 헤더 또는 콘텐츠가 서버로 전송되는지 여부를 지정합니다. 가능한 값은 true(항목이 전송됨) 또는 false(항목이 전송되지 않음)입니다. 기본값은 false입니다.

다음 표에서는 <Property> 요소 속성을 설명합니다.

속성 설명 기본값 Presence 유형
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> 태그로 구성되었을 때 서비스 계정이 누락된 경우에 발생합니다.

예를 들면 다음과 같습니다.

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED 이 오류는 프록시가 <Authentication> 태그로 구성된 경우 서비스 계정에 권한 문제가 있으면 발생합니다. 가능한 원인은 다음과 같습니다.
  • 서비스 계정이 없습니다.
  • Apigee 조직과 동일한 Google Cloud 프로젝트에서 서비스 계정이 생성되지 않았습니다.
  • 배포자에게 서비스 계정에 대한 iam.serviceAccounts.actAs 권한이 없습니다. 자세한 내용은 서비스 계정 권한 정보를 참고하세요.

런타임 오류

다음 표에서는 정책이 실행될 때 발생할 수 있는 런타임 오류를 설명합니다.

오류 코드 HTTP 상태 원인
GrpcTlsInitFailed 500

이 오류는 gRPC 서버에서 TLS를 초기화할 때 키 저장소 또는 트러스트 저장소 문제와 같은 문제가 있을 때 발생합니다.

steps.externalcallout.[error_code] 500

[error_code]는 오류 메시지의 errorCode 필드에 따라 결정됩니다. 오류의 오류 문자열은 오류 메시지의 faultstring 필드가 됩니다.

steps.externalcallout.ExecutionError 500

이 오류는 이 정책 실행 중 다른 예외 사항이 발생할 때 발생합니다. 기본 예외 사항은 오류 문자열로 노출됩니다. 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 프록시가 <Authentication> 요소로 구성된 경우에 발생합니다. 가능한 원인:

  • 프록시로 배포된 서비스 계정:
    • 프로젝트에 존재하지 않음(배포 시 존재했지만 배포 후에 삭제됨)
    • 중지됨
    • (Apigee Hybrid만 해당) apigee-runtime 서비스 계정에 대해 roles/iam.serviceAccountTokenCreator 역할이 부여되지 않음
  • (Apigee Hybrid만 해당) apigee-runtime 서비스 계정의 소스 프로젝트에서 IAMCredentials API가 사용 중지됩니다.

    참고: Apigee Hybrid의 경우 문제 디버깅에 도움이 될 수 있는 보다 자세한 오류 메시지를 찾으려면 런타임 컨테이너 로그에서 externalcallout.ExecutionError를 찾습니다.

PERMISSION DENIED가 포함된 faultstring이 있는 steps.externalcallout.ExecutionError

예를 들어 faultstring은 Cloud Run의 경우 다음과 같이 표시됩니다.

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

500

이 오류는 API 프록시가 <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

관련 주제