GSP844
개요
Apigee는 API를 개발하고 관리하는 데 사용할 수 있는 플랫폼입니다. Apigee를 사용하면 API에 대한 액세스를 보호하고 액세스 비율을 제한할 수 있습니다. Apigee는 API 데이터에 대한 내부 액세스를 보호하는 데 사용되는 기능도 제공합니다.
이 실습에서는 액세스하려면 OAuth 토큰이 필요한 API를 만듭니다. SpikeArrest 정책을 사용하여 애플리케이션별 API 호출 비율을 제한하고 비공개 변수 및 데이터 마스킹을 사용하여 API 트래픽을 디버깅하는 사용자에게 민감한 정보를 표시하지 않습니다.
목표
이 실습에서는 다음 작업을 수행하는 방법을 알아봅니다.
- OAuth 토큰을 요구하여 API에 대한 액세스 보호
- SpikeArrest 정책으로 전체 트래픽 비율과 애플리케이션별 비율 제한
- API 호출을 디버깅하는 동안 비공개 변수와 데이터 마스킹을 사용하여 민감한 정보 숨기기
- 백엔드 호출을 지정된 리소스로 제한
- 데이터 유출이 방지되도록 백엔드 오류 메시지 다시 작성
설정 및 요건
실습 시작 버튼을 클릭하기 전에
다음 안내를 확인하세요. 실습에는 시간 제한이 있으며 일시중지할 수 없습니다. 실습 시작을 클릭하면 타이머가 시작됩니다. 이 타이머는 Google Cloud 리소스를 사용할 수 있는 시간이 얼마나 남았는지를 표시합니다.
실무형 실습을 통해 시뮬레이션이나 데모 환경이 아닌 실제 클라우드 환경에서 실습 활동을 진행할 수 있습니다. 실습 시간 동안 Google Cloud에 로그인하고 액세스하는 데 사용할 수 있는 새로운 임시 사용자 인증 정보가 제공됩니다.
이 실습을 완료하려면 다음을 준비해야 합니다.
- 표준 인터넷 브라우저 액세스 권한(Chrome 브라우저 권장)
참고: 이 실습을 실행하려면 시크릿 모드(권장) 또는 시크릿 브라우저 창을 사용하세요. 개인 계정과 학습자 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.
- 실습을 완료하기에 충분한 시간(실습을 시작하고 나면 일시중지할 수 없음)
참고: 이 실습에는 학습자 계정만 사용하세요. 다른 Google Cloud 계정을 사용하는 경우 해당 계정에 비용이 청구될 수 있습니다.
참고: 새 시크릿 창을 사용하여 이 실습을 완료하는 것이 좋습니다.
실습을 시작하고 Google Cloud 콘솔에 로그인하는 방법
-
실습 시작 버튼을 클릭합니다. 실습 비용을 결제해야 하는 경우 결제 수단을 선택할 수 있는 대화상자가 열립니다.
왼쪽에는 다음과 같은 항목이 포함된 실습 세부정보 창이 있습니다.
- Google Cloud 콘솔 열기 버튼
- 남은 시간
- 이 실습에 사용해야 하는 임시 사용자 인증 정보
- 필요한 경우 실습 진행을 위한 기타 정보
-
Google Cloud 콘솔 열기를 클릭합니다(Chrome 브라우저를 실행 중인 경우 마우스 오른쪽 버튼으로 클릭하고 시크릿 창에서 링크 열기를 선택합니다).
실습에서 리소스가 가동되면 다른 탭이 열리고 로그인 페이지가 표시됩니다.
팁: 두 개의 탭을 각각 별도의 창으로 나란히 정렬하세요.
참고: 계정 선택 대화상자가 표시되면 다른 계정 사용을 클릭합니다.
-
필요한 경우 아래의 사용자 이름을 복사하여 로그인 대화상자에 붙여넣습니다.
{{{user_0.username | "Username"}}}
실습 세부정보 창에서도 사용자 이름을 확인할 수 있습니다.
-
다음을 클릭합니다.
-
아래의 비밀번호를 복사하여 시작하기 대화상자에 붙여넣습니다.
{{{user_0.password | "Password"}}}
실습 세부정보 창에서도 비밀번호를 확인할 수 있습니다.
-
다음을 클릭합니다.
중요: 실습에서 제공하는 사용자 인증 정보를 사용해야 합니다. Google Cloud 계정 사용자 인증 정보를 사용하지 마세요.
참고: 이 실습에 자신의 Google Cloud 계정을 사용하면 추가 요금이 발생할 수 있습니다.
-
이후에 표시되는 페이지를 클릭하여 넘깁니다.
- 이용약관에 동의합니다.
- 임시 계정이므로 복구 옵션이나 2단계 인증을 추가하지 않습니다.
- 무료 체험판을 신청하지 않습니다.
잠시 후 Google Cloud 콘솔이 이 탭에서 열립니다.
참고: Google Cloud 제품 및 서비스에 액세스하려면 탐색 메뉴를 클릭하거나 검색창에 제품 또는 서비스 이름을 입력합니다.
Cloud Shell 활성화
Cloud Shell은 다양한 개발 도구가 탑재된 가상 머신으로, 5GB의 영구 홈 디렉터리를 제공하며 Google Cloud에서 실행됩니다. Cloud Shell을 사용하면 명령줄을 통해 Google Cloud 리소스에 액세스할 수 있습니다.
-
Google Cloud 콘솔 상단에서 Cloud Shell 활성화
를 클릭합니다.
-
다음 창을 클릭합니다.
- Cloud Shell 정보 창을 통해 계속 진행합니다.
- 사용자 인증 정보를 사용하여 Google Cloud API를 호출할 수 있도록 Cloud Shell을 승인합니다.
연결되면 사용자 인증이 이미 처리된 것이며 프로젝트가 학습자의 PROJECT_ID, (으)로 설정됩니다. 출력에 이 세션의 PROJECT_ID를 선언하는 줄이 포함됩니다.
Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}
gcloud는 Google Cloud의 명령줄 도구입니다. Cloud Shell에 사전 설치되어 있으며 명령줄 자동 완성을 지원합니다.
- (선택사항) 다음 명령어를 사용하여 활성 계정 이름 목록을 표시할 수 있습니다.
gcloud auth list
-
승인을 클릭합니다.
출력:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (선택사항) 다음 명령어를 사용하여 프로젝트 ID 목록을 표시할 수 있습니다.
gcloud config list project
출력:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
참고: gcloud 전체 문서는 Google Cloud에서 gcloud CLI 개요 가이드를 참고하세요.
Apigee 콘솔 열기
Apigee 콘솔을 열려면 다음 단계를 따르세요.
- Google Cloud 콘솔의 검색 창에
Apigee를 입력한 다음 검색 결과에서 Apigee API 관리를 클릭합니다.
Apigee 콘솔이 열리고 자주 사용되는 위치로 연결되는 빠른 링크가 방문 페이지에 표시됩니다.
-
탐색 메뉴(
)에서 Apigee 옆에 있는 즐겨찾기(
)를 클릭합니다.
이제 Apigee가 탐색 메뉴에 즐겨찾기로 추가됩니다.
작업 1. Apigee API 프록시를 사용하여 백엔드 서비스 프록시
이 작업에서는 백엔드 서비스의 퍼사드 역할을 하는 Apigee API 프록시를 만듭니다. API 프록시는 서비스 계정을 사용하여 Cloud Run 서비스에 OpenID Connect ID 토큰을 제공합니다.
simplebank-rest라는 백엔드 서비스가 이미 생성되어 Cloud Run에 배포되었습니다. 서비스 계정도 자동으로 생성되었습니다.
Apigee 프록시 만들기
-
Cloud Shell에서 백엔드 서비스 URL을 가져오려면 다음 명령어를 사용합니다.
gcloud run services describe simplebank-rest --platform managed --region {{{project_0.default_region |REGION}}} --format 'value(status.url)'
이 URL은 API 프록시를 만들 때 사용되므로 이 URL을 저장합니다.
-
Cloud 콘솔에서 Apigee UI로 이동합니다.
-
왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택합니다.
-
프록시 마법사를 사용하여 새 프록시를 만들려면 + 만들기를 클릭합니다.
백엔드 서비스의 리버스 프록시를 만듭니다. 이 API 프록시는 OpenAPI 사양을 사용하여 API의 스켈레톤을 만듭니다.
-
프록시 템플릿 상자의 OpenAPI 사양 템플릿에서 리버스 프록시(가장 일반적)를 선택합니다 .
-
OpenAPI 파일의 경우 브라우저에서 URL을 엽니다. 그러면 OpenAPI 사양 YAML 파일이 컴퓨터에 다운로드됩니다.
https://storage.googleapis.com/spls/gsp844/simplebank-backend.yaml
-
찾아보기를 클릭하고 컴퓨터에서 OpenAPI 파일에 사용할 파일을 선택한 후 다음을 클릭합니다.
-
프록시 세부정보에 다음을 지정합니다.
| 속성 |
값 |
| 프록시 이름 |
bank-v1 |
| 기본 경로 |
/bank/v1 |
| 설명 |
SimpleBank 읽기 전용 API |
| 대상(기존 API) |
백엔드 URL |
참고:
기본 경로에 '/bank-v1'이 아닌 '/bank/v1'을 사용하고 있는지 확인하세요.
대상은 작업 초반에 검색한 백엔드 URL이어야 합니다. 대상은 다음과 같이 표시됩니다.
https://simplebank-rest-nu7rb74j5a-uw.a.run.app
-
다음을 클릭합니다.
-
다른 설정을 기본값으로 두고 만들기를 클릭합니다.
-
개발 탭을 클릭합니다.
참고: 프록시 엔드포인트에 흐름이 추가되었으며 각 흐름은 OpenAPI 사양의 작업 중 하나에 대한 동사와 경로 조건을 지정합니다.
OpenID Connect ID 토큰을 전송하도록 대상 수정
백엔드 서비스는 인증된 액세스를 요구하도록 배포되므로 유효한 OpenID Connect ID 토큰이 없으면 서비스를 호출할 수 없습니다.
HTTPTargetConnection은 서비스의 백엔드 대상을 지정합니다.
-
프록시의 탐색기 메뉴에 있는 대상 엔드포인트 섹션에서 PreFlow를 클릭합니다.
-
다음 코드를 찾습니다(URL은 다를 수 있음).
<HTTPTargetConnection>
<URL>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</URL>
</HTTPTargetConnection>
참고: HTTPTargetConnection 섹션이 표시되지 않으면 프록시 엔드포인트 섹션이 아닌 대상 엔드포인트 섹션에서 PreFlow를 클릭했는지 확인하세요.
-
URL 아래에 다음과 같은 인증 섹션을 추가합니다.
<Authentication>
<GoogleIDToken>
<Audience>AUDIENCE</Audience>
</GoogleIDToken>
</Authentication>
-
AUDIENCE를 HTTPTargetConnection 섹션에 이미 있는 URL 값으로 바꿉니다. 이제 코드가 다음과 비슷하게 표시됩니다. 단, URL 및 대상 요소에는 사용자의 특정 URL이 표시됩니다.
<TargetEndpoint name="default">
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<Flows/>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<HTTPTargetConnection>
<URL>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</URL>
<Authentication>
<GoogleIDToken>
<Audience>https://simplebank-rest-zce6j3rjwq-uw.a.run.app</Audience>
</GoogleIDToken>
</Authentication>
</HTTPTargetConnection>
</TargetEndpoint>
-
저장을 클릭합니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
API 프록시 만들기
작업 2. API 프록시에 OAuth 추가
이 작업에서는 API 프록시에 OAuthV2 정책을 추가합니다. VerifyJWTAccessToken 작업을 사용하는 OAuthV2 정책은 런타임 시 액세스 토큰 검증을 시행하여 유효한 OAuth 액세스 토큰이 있는 애플리케이션만 API에 액세스할 수 있게 합니다.
OAuthV2 정책은 불투명 토큰과 JSON 웹 토큰(JWT)을 모두 만들고 확인할 수 있습니다. 이 API 프록시는 액세스 토큰에 JWT를 사용합니다.
속성 집합은 JWT 생성 및 확인에 사용되는 서명 보안 비밀을 저장하는 데 사용됩니다.
속성 집합에서 서명 보안 비밀 만들기
JWT는 해시 기반 메시지 인증 코드(HMAC)를 통해 서명됩니다. 이 유형의 암호화 서명을 사용하려면 보안 비밀이 필요합니다.
-
프록시의 탐색기 메뉴에서 리소스 옆에 있는 +를 클릭합니다.
-
리소스 유형 드롭다운에서 속성 집합을 선택합니다.
-
리소스 이름에 oauth.properties를 지정한 후 추가를 클릭합니다.
-
oauth.properties 코드 창에서 다음 속성을 추가합니다.
secret=thisisnotagoodsecret,useabettersecretinproduction
흐름 변수 propertyset.oauth.secret을 사용하면 코드에서 이 값에 액세스할 수 있습니다.
참고:
속성 집합 값은 일반 텍스트로 저장됩니다. 프로덕션 환경에서는 HMAC 보안 비밀이 암호화된 위치에 저장될 가능성이 높으므로 더 안전한(무작위) 보안 비밀을 사용해야 합니다.
AssignMessage 정책을 추가하여 속성 집합 값 가져오기
서명 보안 비밀은 비공개 변수로 OAuth 정책에 제공되어야 하지만 propertyset.oauth.secret 변수는 비공개가 아닙니다. 이 AssignMessage 정책은 속성 집합 변수에서 비공개 변수를 만듭니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 기본값에서 PreFlow를 클릭합니다.
기본 프록시 엔드포인트의 요청 PreFlow는 요청이 API 프록시에 들어올 때 실행되는 첫 번째 흐름입니다.
OAuthV2 정책을 시행하려면 보안 비밀이 필요하며 이 정책은 API 프록시에서 매우 일찍 실행됩니다.
-
흐름 창에서 요청 흐름의 PreFlow 바로 옆에 있는 + 버튼을 클릭합니다.
-
새 정책 만들기를 선택하고 정책 선택 드롭다운의 미디에이션 섹션에서 메시지 할당을 선택한 후 표시 이름과 이름을 AM-GetSecret으로 설정합니다.
-
추가를 클릭합니다. 탐색기 메뉴의 정책에서 AM-GetSecret을 클릭합니다.
AssignMessage 정책 구성이 코드 창에 표시됩니다.
-
정책 구성을 다음과 같이 변경합니다.
<AssignMessage name="AM-GetSecret">
<AssignVariable>
<Name>private.secretkey</Name>
<Ref>propertyset.oauth.secret</Ref>
</AssignVariable>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>
AssignVariable 설정은 propertyset.oauth.secret 변수를 private.secretkey 변수에 복사합니다.
IgnoreUnresolvedVariables 설정으로 인해 propertyset.oauth.secret을 확인할 수 없으면 AssignMessage 정책에서 오류가 발생합니다.
OAuthV2 정책을 추가하여 토큰 확인
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 기본값에서 PreFlow를 클릭합니다.
OAuthV2 정책은 AssignMessage 정책 다음에 실행되어야 합니다.
-
흐름 창에서 요청 흐름의 PreFlow 바로 옆에 있는 + 버튼을 클릭합니다.
-
새 정책 만들기를 선택하고 정책 선택 드롭다운의 보안 섹션에서 OAuth v2.0을 선택한 후 표시 이름과 이름을 OA-VerifyToken으로 설정합니다.
-
추가를 클릭한 후 탐색기 메뉴의 정책에서 OA-VerifyToken을 클릭합니다.
OAuthV2 정책 구성이 코드 창에 표시됩니다.
-
OAuthV2 정책 구성을 다음과 같이 변경합니다.
<OAuthV2 name="OA-VerifyToken">
<Operation>VerifyJWTAccessToken</Operation>
<Algorithm>HS256</Algorithm>
<SecretKey>
<Value ref="private.secretkey"/>
</SecretKey>
</OAuthV2>
구성에서는 AssignMessage 정책에서 생성된 비공개 변수를 보안 비밀 키로 사용하여 JWT 액세스 토큰이 HS256(HMAC-SHA256) 알고리즘을 사용하도록 지정합니다.
-
저장을 클릭합니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
정책을 추가하여 토큰 확인
작업 3. 정책을 추가하여 토큰 생성
JWT 토큰을 만들 수 있도록 별도의 프록시 엔드포인트도 API 프록시에 추가됩니다.
토큰 작업에 사용할 새 프록시 엔드포인트 추가
프로덕션 환경에서는 일반적으로 토큰 생성에 사용할 수 있는 별도의 프록시가 생성됩니다. 이 실습에서는 같은 API 프록시 내 별도의 프록시 엔드포인트에서 토큰 생성 흐름을 만듭니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 행에서 + 버튼을 클릭합니다.
참고:
'기본값' 옆에 있는 '+' 버튼을 클릭하지 마세요.
클릭하면 새 JWT를 만들 때 사용할 새 프록시 엔드포인트가 생성됩니다.
-
이름에 token을 지정한 후 추가를 클릭합니다.
token이라는 새 프록시 엔드포인트가 코드 창에 표시됩니다.
-
다음 전체 token 흐름 구성을 변경합니다.
<ProxyEndpoint name="token">
.
.
.
</ProxyEndpoint>
다음과 같이 변경합니다.
<ProxyEndpoint name="token">
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<Flows/>
<HTTPProxyConnection>
<BasePath>/token</BasePath>
</HTTPProxyConnection>
<RouteRule name="noTarget"/>
</ProxyEndpoint>
-
저장을 클릭합니다.
이 업데이트된 구성으로 인해 다음과 같은 2가지 변경사항이 발생합니다.
-
BasePath가
/token으로 설정됩니다. 토큰을 만들 때 사용되는 기본 경로입니다.
-
RouteRule에서 더 이상 대상 엔드포인트를 참조하지 않습니다. API 프록시에서 백엔드 서비스를 호출하지 않고 토큰을 만듭니다.
토큰 생성 흐름 만들기
-
프록시의 흐름에서 프록시 엔드포인트: 토큰 섹션의 /token 바로 옆에 있는 +를 클릭합니다.
-
새 조건부 흐름의 경우 다음 값을 지정합니다.
| 속성 |
값 |
| 흐름 이름 |
generateToken |
| 조건 유형 |
Custom 선택 |
-
조건에 다음 값을 지정합니다.
(proxy.pathsuffix MatchesPath "/") and (request.verb = "POST") and (request.formparam.grant_type = "client_credentials")
유효한 클라이언트 사용자 인증 정보 토큰 요청만 허용됩니다.
-
추가를 클릭합니다.
AssignMessage 정책을 연결하여 속성 집합 값 가져오기
토큰을 생성하는 OAuthV2 정책에도 private.secretkey 변수에 대한 액세스 권한이 필요합니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 토큰에서 generateToken을 클릭합니다.
-
흐름 창에서 요청 흐름의 generateToken 바로 옆에 있는 + 버튼을 클릭합니다.
-
정책 선택에서 기존 정책 선택을 선택한 후 AM-GetSecret을 클릭합니다.
-
추가를 클릭합니다.
같은 AssignMessage 정책이 토큰 프록시 엔드포인트 PreFlow에 연결됩니다.
OAuthV2 정책을 추가하여 토큰 생성
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 토큰에서 generateToken을 클릭합니다.
-
흐름 창에서 요청 흐름의 generateToken 바로 옆에 있는 + 버튼을 클릭합니다.
-
정책 선택에서 새 정책 만들기를 선택하고 보안 섹션에서 OAuth v2.0을 선택한 후 표시 이름과 이름을 OA-GenerateToken으로 설정합니다.
-
추가를 클릭한 후 정책에서 OA-GenerateToken을 클릭합니다.
OAuthV2 정책 구성이 코드 창에 표시됩니다.
-
OAuthV2 정책 구성을 다음과 같이 변경합니다.
<OAuthV2 name="OA-GenerateToken">
<Operation>GenerateJWTAccessToken</Operation>
<Algorithm>HS256</Algorithm>
<SecretKey>
<Value ref="private.secretkey"/>
</SecretKey>
<SupportedGrantTypes>
<!-- pass client_id and client_secret via basic auth header -->
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<!-- 1800000 ms = 1800 s = 30 min -->
<ExpiresIn>1800000</ExpiresIn>
<GenerateResponse enabled="true"/>
<RFCCompliantRequestResponse>true</RFCCompliantRequestResponse>
</OAuthV2>
이 구성을 사용하면 30분 후에 만료되는 JWT OAuth 토큰을 만들 수 있습니다.
잘못된 토큰 요청에 대한 오류 발생
-
프록시의 흐름에서 프록시 엔드포인트: 토큰 섹션의 /token 바로 옆에 있는 +를 클릭합니다.
-
새 조건부 흐름의 경우 다음 값을 지정합니다.
| 속성 |
값 |
| 흐름 이름 |
invalidRequest |
| 조건 유형 |
Custom 선택 |
| 조건 |
DELETETHIS |
유효하지 않은 generateToken 요청이 이 흐름을 거쳐야 하므로 흐름이 추가되면 조건이 삭제됩니다.
-
추가를 클릭합니다.
-
invalidRequest 흐름에서 다음 줄을 삭제합니다.
<Condition>DELETETHIS</Condition>
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 토큰에서 invalidRequest를 클릭합니다.
-
흐름 창에서 요청 흐름의 invalidRequest 바로 옆에 있는 + 버튼을 클릭합니다.
-
새 정책 만들기를 선택하고 미디에이션 섹션에서 오류 발생을 선택한 후 표시 이름과 이름을 RF-InvalidTokenRequest로 설정합니다.
-
추가를 클릭한 후 정책에서 RF-InvalidTokenRequest를 클릭합니다.
RaiseFault 정책 구성이 코드 창에 표시됩니다.
-
RaiseFault 정책 구성을 다음과 같이 변경합니다.
<RaiseFault name="RF-InvalidTokenRequest">
<FaultResponse>
<Set>
<StatusCode>400</StatusCode>
<ReasonPhrase>Bad Request</ReasonPhrase>
<Payload contentType="application/json">{
"error":"Bad request: use POST /token"
}</Payload>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>
요청이 잘못되면 400 잘못된 요청 응답이 생성됩니다.
-
저장을 클릭합니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
정책을 추가하여 토큰 생성
작업 4. OAuth 프록시 배포
이 작업에서는 API 프록시를 배포하고 액세스하는 데 OAuth 토큰이 필요한지 확인합니다.
런타임 인스턴스를 사용할 수 있는지 확인
-
Cloud Shell에서 다음 명령어 집합을 붙여넣고 실행합니다.
export INSTANCE_NAME=eval-instance; export ENV_NAME=eval; export PREV_INSTANCE_STATE=; echo "waiting for runtime instance ${INSTANCE_NAME} to be active"; while : ; do export INSTANCE_STATE=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${GOOGLE_CLOUD_PROJECT}/instances/${INSTANCE_NAME}" | jq "select(.state != null) | .state" --raw-output); [[ "${INSTANCE_STATE}" == "${PREV_INSTANCE_STATE}" ]] || (echo; echo "INSTANCE_STATE=${INSTANCE_STATE}"); export PREV_INSTANCE_STATE=${INSTANCE_STATE}; [[ "${INSTANCE_STATE}" != "ACTIVE" ]] || break; echo -n "."; sleep 5; done; echo; echo "instance created, waiting for environment ${ENV_NAME} to be attached to instance"; while : ; do export ATTACHMENT_DONE=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${GOOGLE_CLOUD_PROJECT}/instances/${INSTANCE_NAME}/attachments" | jq "select(.attachments != null) | .attachments[] | select(.environment == \"${ENV_NAME}\") | .environment" --join-output); [[ "${ATTACHMENT_DONE}" != "${ENV_NAME}" ]] || break; echo -n "."; sleep 5; done; echo "***ORG IS READY TO USE***";
이 명령어 시리즈는 Apigee API를 사용하여 Apigee 런타임 인스턴스가 생성되고 eval 환경이 연결된 시점을 확인합니다.
-
인스턴스가 준비될 때까지 기다립니다.
***ORG IS READY TO USE*** 텍스트가 표시되면 인스턴스를 사용할 수 있습니다. Apigee 조직(org)은 실습을 시작하기 전에 생성되었을 수 있으므로 인스턴스가 생성될 때까지 기다리지 않아도 됩니다.
조직이 준비될 때까지 기다리는 동안 OAuth, SpikeArrest 정책, 데이터 마스킹 및 숨기기, 불투명 토큰 및 JWT를 알아볼 수 있습니다.
API 프록시 배포
-
Cloud 콘솔에서 Apigee로 이동합니다.
-
왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택한 후 bank-v1을 클릭합니다.
-
개발 탭을 클릭합니다.
-
배포를 클릭하고 환경에서 eval을 선택합니다.
배포를 확인하라는 대화상자가 표시됩니다.
-
서비스 계정에 서비스 계정 이메일 주소를 지정합니다.
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
배포 및 확인을 클릭합니다.
-
개요 탭을 클릭하고 eval 배포 상태에 프록시가 배포되었음이 표시될 때까지 기다립니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
API 프록시 배포
API 프록시 테스트
호스트 이름 eval.example.com을 사용하여 Apigee 조직의 eval 환경을 호출할 수 있습니다. 이 호스트 이름의 DNS 항목은 프로젝트 내에 생성되었으며 Apigee 런타임 인스턴스 IP 주소로 확인됩니다. 이 DNS 항목은 비공개 영역에 생성되었으므로 내부 네트워크에서만 표시됩니다.
Cloud Shell은 내부 네트워크에 상주하지 않으므로 Cloud Shell 명령어는 이 DNS 항목을 확인할 수 없습니다. 조직 내 가상 머신(VM)에서 비공개 영역 DNS에 액세스할 수 있습니다. apigeex-test-vm이라는 가상 머신이 자동으로 생성되었습니다. 이 머신을 사용하여 API 프록시를 호출할 수 있습니다.
-
Cloud Shell에서 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
승인을 요청하는 메시지가 나타나면 승인을 클릭합니다.
-
Cloud Shell에서 묻는 질문마다 Enter 또는 Return을 클릭하여 기본 입력을 지정합니다.
로그인한 ID가 프로젝트 소유자이므로 이 머신에 대한 SSH가 허용됩니다.
이제 Cloud Shell 세션이 VM 내에서 실행됩니다.
-
eval 환경에서 배포된 bank-v1 API 프록시를 호출합니다.
curl -i -k -X GET "https://eval.example.com/bank/v1/customers"
-k 옵션은 curl에 TLS 인증서 확인을 건너뛰라고 지시합니다. 이 실습에서 Apigee 런타임은 신뢰할 수 있는 인증 기관(CA)에서 만든 인증서 대신 자체 서명 인증서를 사용합니다.
참고:
프로덕션 사용 사례의 인증서 확인을 우회하기 위해 -k 옵션을 사용하면 안 됩니다.
이 API에서 고객 목록을 가져오려고 시도합니다. 이제 다음과 비슷한 401 승인되지 않음 응답이 표시됩니다.
HTTP/2 401
content-type: application/json
www-authenticate: Bearer realm="null",error="invalid_token",error_description="oauth.v2.InvalidAccessToken: Invalid access token"
x-request-id: 99263881-d0f7-4495-b886-0253f28a2e05
content-length: 101
date: Tue, 11 Jan 2022 18:59:01 GMT
via: 1.1 google
{"fault":{"faultstring":"Invalid access token","detail":{"errorcode":"oauth.v2.InvalidAccessToken"}}}
이 응답은 액세스 토큰이 제공되지 않아 API 프록시가 백엔드 서비스에 대한 액세스를 차단했음을 나타냅니다.
-
exit 명령어를 입력하여 SSH 세션을 종료하고 Cloud Shell로 돌아갑니다.
작업 5. API 제품, 개발자, 애플리케이션 추가
이 작업에서는 API에 대한 액세스 권한을 제공하는 API 제품을 추가합니다. 또한 개발자를 만든 후 API 제품과 연결할 애플리케이션을 만듭니다.
API 제품 만들기
-
Cloud 콘솔에서 Apigee로 이동합니다.
-
왼쪽 탐색 메뉴에서 배포 > API 제품을 선택합니다.
-
새 API 제품을 만들려면 + 만들기를 클릭합니다.
-
제품 세부정보 창에서 다음을 지정합니다.
| 속성 |
값 |
| 이름 |
bank-readonly |
| 표시 이름 |
은행(읽기 액세스) |
| 환경 |
eval 선택
|
| 액세스 |
공개 선택
|
액세스 요청 자동 승인을 선택한 상태로 둡니다.
-
작업 섹션에서 + 작업 추가를 클릭합니다.
작업은 API 제품과 연결된 애플리케이션에 허용되는 API 프록시의 요청을 지정하는 데 사용됩니다.
참고:
버튼이 'GraphQL 작업' 섹션이 아닌 '작업' 섹션에 있는지 확인하세요.
-
다음 사항을 지정합니다.
| 속성 |
값 |
| API 프록시 |
bank-v1 API 프록시 선택 |
| 경로 |
/** |
| 메서드 |
GET 선택 |
경로 표현식 /\*\*은 기본 경로와 일치하는 모든 요청이 허용됨을 나타냅니다.
프로덕션 환경에서는 이 와일드카드 경로 표현식을 사용하는 대신 허용된 각 작업을 별도로 추가할 수 있습니다.
-
저장을 클릭하여 작업을 저장합니다.
-
API 제품을 저장하려면 제품 세부정보 페이지 상단에 있는 저장을 클릭합니다.
-
배포 > API 제품 페이지로 돌아갑니다.
API 제품이 나열됩니다.
앱 개발자 만들기
앱을 만들기 전에 앱 개발자를 만들어야 합니다.
-
왼쪽 탐색 메뉴에서 배포 > 개발자를 클릭합니다.
-
새 앱 개발자를 만들려면 + 만들기를 클릭합니다.
-
다음 사항을 지정합니다.
| 속성 |
값 |
| 이름 |
Joe |
| 성 |
Developer |
| 사용자 이름 |
joe |
| 이메일 |
joe@example.com |
-
추가를 클릭하여 앱 개발자를 만듭니다.
bank-v1 액세스 권한으로 앱 만들기
-
왼쪽 탐색 메뉴에서 배포 > 앱을 클릭합니다.
-
새 앱을 만들려면 + 만들기를 클릭합니다.
-
앱 세부정보 창에서 다음을 지정합니다.
| 속성 |
값 |
| 이름 |
readonly-app |
| 개발자 |
joe@example.com 선택 |
-
사용자 인증 정보 창에서 사용자 인증 정보 추가 > 제품 추가를 클릭하고 드롭다운에서 은행(읽기 액세스)을 선택한 후 추가를 클릭하여 추가합니다.
-
오른쪽 상단에 있는 만들기를 클릭하여 앱을 만듭니다.
이제 앱에 키와 보안 비밀이 구성됩니다.
-
키와 보안 비밀 옆에 있는 표시 아이콘을 클릭합니다.
이 API의 경우 OAuth 액세스 토큰이 필요합니다. 키와 보안 비밀은 앱의 사용자 인증 정보로 사용되므로 앱에서 OAuth 액세스 토큰을 만들 수 있습니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
API 제품 추가 및 앱 만들기
API 테스트
-
Cloud Shell에서 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
승인을 요청하는 메시지가 나타나면 승인을 클릭합니다.
이제 Cloud Shell 세션이 VM 내에서 실행됩니다.
-
애플리케이션의 고객 키와 보안 비밀을 가져오려면 다음 명령어를 실행합니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}"
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}"
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}"
첫 번째 명령어는 gcloud 구성을 읽어 현재 프로젝트를 가져옵니다. 두 번째 명령어와 세 번째 명령어는 Apigee API를 사용하여 고객 키와 보안 비밀을 가져옵니다. 로그인한 사용자의 권한이 있는 액세스 토큰을 전송하므로 요청이 승인됩니다.
OAuth 클라이언트 사용자 인증 정보 부여 유형의 경우 클라이언트 애플리케이션에서 액세스 토큰을 생성하려면 승인 헤더에 고객 키와 보안 비밀을 전송해야 합니다.
-
JWT 액세스 토큰을 생성하려면 다음 명령어를 실행합니다.
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE}
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"
첫 번째 명령어는 토큰 엔드포인트를 호출하고 응답을 저장합니다. 그러면 토큰이 JSON 응답에서 추출되어 JWT_TOKEN에 저장됩니다.
-
JWT 토큰을 사용하여 요청을 테스트하려면 다음 명령어를 사용합니다.
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"
이제 API 호출에서 고객 목록을 반환합니다.
참고:
'클라이언트에 요청된 URL에 대한 권한이 없습니다'라는 응답이 표시되면 작업 1에서 대상을 올바르게 설정했는지 확인하세요.
-
exit 명령어를 입력하여 SSH 세션을 종료하고 Cloud Shell로 돌아갑니다.
작업 6. 비율 제한 추가
이 작업에서는 API 제품 할당량 구성을 사용하여 API 호출 비율을 제한하는 SpikeArrest 정책을 추가합니다.
SpikeArrest 정책은 허용되는 최대 트래픽 비율을 지정할 수 있도록 하여 트래픽 급증으로부터 API와 백엔드를 보호합니다. 이 정책을 사용하면 백엔드가 처리할 수 없는 트래픽으로 인한 과부하가 발생하지 않도록 할 수 있습니다.
토큰 생성을 위한 SpikeArrest 정책 추가
이 SpikeArrest 정책은 /token API 호출 트래픽의 전체 비율 제한을 지정합니다.
-
Cloud 콘솔에서 Apigee로 이동합니다.
-
왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택한 후 bank-v1을 클릭합니다.
-
개발 탭을 클릭합니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 토큰에서 PreFlow를 클릭합니다.
SpikeArrest 정책은 조건부 흐름 정책 전에 실행되어야 합니다.
-
흐름 창에서 요청 흐름의 PreFlow 바로 옆에 있는 + 버튼을 클릭합니다.
-
새 정책 만들기를 선택하고 트래픽 관리 섹션에서 급증 저지를 선택한 후 표시 이름과 이름을 SA-LimitTokenRate로 설정합니다.
-
추가를 클릭한 후 정책 섹션에서 SA-LimitTokenRate를 클릭합니다.
SpikeArrest 정책 구성이 코드 창에 표시됩니다.
-
SpikeArrest 정책 구성을 다음과 같이 변경합니다.
<SpikeArrest name="SA-LimitTokenRate">
<Rate>5pm</Rate>
<UseEffectiveCount>false</UseEffectiveCount>
</SpikeArrest>
구성에서는 최대 허용 요청 비율을 분당 5개로 지정합니다. 모든 트래픽이 이 SpikeArrest 정책에 의해 제한됩니다.
참고:
테스트를 쉽게 진행하기 위해 분당 요청 5개가 사용됩니다. 일반적으로 이 실습의 SpikeArrest 제한은 실제 시나리오에서의 제한에 비해 너무 낮습니다.
UseEffectiveCount가 false로 설정되면 SpikeArrest 정책에서 토큰 버킷 알고리즘을 사용합니다. 비율을 더 작은 간격으로 나눠 트래픽을 원활하게 처리합니다. 분당 요청 5개는 1/5분당 요청 1개 또는 12초마다 요청 1개를 의미합니다. 이전 요청 후 12초 이내에 두 번째 요청이 메시지 프로세서에 들어오면 거부될 수 있습니다.
API 요청에 대한 SpikeArrest 정책 추가
이 SpikeArrest 정책은 /bank/v1 API 호출 트래픽의 비율 제한을 지정합니다. 비율은 애플리케이션별로 적용됩니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 기본값에서 PreFlow를 클릭합니다.
SpikeArrest 정책을 호출 초기에 실행해야 하지만 애플리케이션을 기반으로 비율을 제한하려면 OAuthV2 VerifyJWTAccessToken 정책 이후에 실행해야 합니다.
-
흐름 창에서 요청 흐름의 PreFlow 바로 옆에 있는 + 버튼을 클릭합니다.
-
새 정책 만들기를 선택하고 트래픽 관리 섹션에서 급증 저지를 선택한 후 표시 이름과 이름을 SA-LimitRateByApp으로 설정합니다.
-
추가를 클릭한 후 정책 섹션에서 SA-LimitRateByApp을 클릭합니다.
SpikeArrest 정책 구성이 코드 창에 표시됩니다.
-
SpikeArrest 정책 구성을 다음과 같이 변경합니다.
<SpikeArrest name="SA-LimitRateByApp">
<Rate>5pm</Rate>
<Identifier ref="client_id" />
<UseEffectiveCount>true</UseEffectiveCount>
</SpikeArrest>
이전 정책과 마찬가지로 구성에서는 최대 허용 요청 비율을 분당 5개로 지정합니다. 하지만 이 정책은 client_id마다 SpikeArrest 비율을 별도로 유지하는 식별자를 지정합니다. 클라이언트 ID는 OA-VerifyToken 정책에 의해 채워지며 개발자 애플리케이션마다 고유합니다.
UseEffectiveCount를 true로 설정하면 리전 내 모든 트래픽에 유지되는 비율 수를 지정합니다. 이 정책은 기간별로 수신된 요청 카운터를 유지합니다. 분당 요청 비율을 사용하는 경우 기간은 1분입니다. 비율 계산은 슬라이딩 기간을 기반으로 합니다.

위 예시에서는 분당 요청 50개 비율을 사용하고 있다고 가정합니다. 카운터는 1분 주기를 사용합니다. 하지만 초당 비율이 지정된 경우 카운터 주기는 1초가 됩니다. 화살표로 표시된 현재 분의 10초가 지났다고 가정해 보겠습니다. 이전 분에 요청이 48개 있었고 현재 기간에는 지금까지 요청 5개가 있었습니다.
다른 요청을 허용하려면 비율이 분당 요청 50개 미만이어야 합니다. 계산된 비율은 다음과 같습니다.
request_rate = (48 * (60-10)/60) + 6 = 46
현재 기간에서 60초 중 10초만 경과했으므로 나머지 50초는 이전 기간 비율을 통해 계산됩니다. 48의 5/6은 40입니다. 요청이 허용되면 현재 기간 수는 5 + 1, 즉 6이 됩니다. 요청 비율 계산 결과가 46이므로 요청이 허용됩니다. 요청 비율이 분당 요청 50개 미만이기 때문입니다.
-
저장 > 새 버전으로 저장을 선택합니다.
-
배포를 클릭한 후 환경에서 eval을 선택합니다.
-
서비스 계정에 서비스 계정 이메일 주소를 지정합니다.
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
배포 및 확인을 클릭합니다.
-
개요 탭을 클릭하고 eval 배포 상태에 프록시가 배포되었음이 표시될 때까지 기다립니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
SpikeArrest 정책 추가
비율 제한 테스트
-
Cloud Shell에서 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
승인을 요청하는 메시지가 나타나면 승인을 클릭합니다.
이제 Cloud Shell 세션이 VM 내에서 실행됩니다.
-
애플리케이션의 고객 키와 보안 비밀을 가져오려면 다음 명령어를 실행합니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}"
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}"
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}"
-
다음 명령어를 반복적으로 실행하여 액세스 토큰을 여러 개 생성합니다.
curl -i -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"
비율이 초과됐음을 나타내는 429 요청이 너무 많음 응답이 빠르게 표시됩니다. 이 정책의 경우 UseEffectiveCount가 false이므로 토큰 버킷 알고리즘을 통해 트래픽이 평활화됩니다. 5번째 요청 전에 급증 방지 위반이 발생할 수 있습니다.
-
JWT 액세스 토큰을 저장하려면 다음 명령어를 실행합니다.
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE}
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"
-
API 호출에 대한 SpikeArrest 정책을 테스트하려면 다음 명령어를 반복해서 전송합니다.
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers"
UseEffectiveCount가 true이므로 이 정책은 슬라이딩 기간 알고리즘을 사용합니다. 요청이 차단되기 전에 요청 5개를 성공적으로 가져올 수 있어야 합니다.
-
exit 명령어를 입력하여 SSH 세션을 종료하고 Cloud Shell로 돌아갑니다.
작업 7. 데이터 마스킹
이 작업에서는 디버그 세션이 특정 필드를 숨기는 데이터 마스크를 만듭니다.
디버그 세션 시작
디버그는 Apigee에서 실행되는 API 프록시 문제를 해결하고 모니터링할 수 있는 도구입니다. 디버그 도구를 사용하면 API 호출 중에 각 단계의 세부정보를 검사할 수 있습니다.
-
왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택한 후 bank-v1을 클릭합니다.
-
디버그 탭을 클릭합니다.
-
디버그 세션 시작 창에서 디버그 세션 시작을 클릭하고 환경 드롭다운에서 eval 환경을 선택합니다.
-
시작을 클릭합니다.
디버그 세션에서 요청 캡처를 시작하기까지 약간의 시간이 걸릴 수 있습니다.
참고:
화면 상단에 있는 빨간색 상자에 오류 메시지가 표시되고 '디버그 트랜잭션 가져오기 오류' 또는 '디버그 세션 트랜잭션 목록 오류'와 같은 설명이 표시되면 디버그 세션이 계속 올바르게 작동할 수 있습니다.
API 요청을 보낸 후 디버그 세션을 검사합니다.
요청 디버그
-
Cloud Shell에서 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
승인을 요청하는 메시지가 나타나면 승인을 클릭합니다.
이제 Cloud Shell 세션이 VM 내에서 실행됩니다.
-
애플리케이션의 토큰을 가져오려면 다음 명령어를 실행합니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null); echo "PROJECT_ID=${PROJECT_ID}"
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output); echo "CONSUMER_KEY=${CONSUMER_KEY}"
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output); echo "CONSUMER_SECRET=${CONSUMER_SECRET}"
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials"); echo ${TOKEN_RESPONSE}
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output); echo "JWT_TOKEN=${JWT_TOKEN}"
-
API에 다음 요청을 전송합니다.
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers/abe@example.org/accounts"
-
Apigee UI 페이지로 돌아갑니다.
디버그 페이지에 요청 2개가 표시됩니다. 하나는 POST(토큰 생성)이고 다른 하나는 GET(사용자 계정 가져오기)입니다.
-
GET 요청을 클릭합니다.
GET 요청 세부정보가 표시됩니다.
-
첫 번째 정책을 클릭합니다. 이 정책은 propertyset.oauth.secret 변수를 private.secretkey 변수에 복사하는 AM-GetSecret 정책입니다.

단계 세부정보에는 비공개 변수가 표시되지 않습니다. 'private.' 프리픽스가 추가된 변수는 디버그 세션에서 표시되지 않기 때문입니다. 하지만 속성 설정 변수는 같은 민감한 정보를 보유하고 있으므로 트래픽을 디버깅하는 사용자에게는 표시되지 않게 하는 것이 좋습니다.
-
팩토리 아이콘 왼쪽에 있는 원으로 표시된 백엔드의 응답을 클릭합니다.

응답에는 계정 잔액을 포함한 사용자 계정이 포함됩니다.
디버그 마스크 만들기
-
같은 브라우저 창에서 새 탭을 열고 Apigee API 참조로 이동합니다.
Apigee API 참조에서는 Apigee를 관리하는 데 사용할 수 있는 다양한 API 호출에 대한 세부정보를 제공하며 Apigee API를 호출하는 데도 사용될 수 있습니다. 이 페이지에는 organization.environments API 호출이 표시됩니다.
-
페이지 하단으로 스크롤하여 updateDebugmask를 클릭합니다.
이 API 호출은 환경의 디버그 마스크를 업데이트합니다.
-
API 사용해 보기 창에서 name 요청 파라미터에 다음을 사용합니다.
organizations/{{{ project_0.project_id | PROJECT }}}/environments/eval/debugmask
-
요청 본문에 다음 본문을 입력합니다.
{
"responseJSONPaths": [
"$[*].balance"
],
"variables": [
"propertyset.oauth.secret"
]
}
이 페이로드는 propertyset.oauth.secret 변수를 마스킹하고 응답 페이로드의 객체 배열에 있는 각 잔액 필드도 마스크합니다.
-
실행을 클릭합니다.
팝업 상자에서 계정을 선택하라는 메시지가 표시되면 학생 계정을 선택합니다.
-
허용을 클릭하여 페이지에서 학생 사용자 인증 정보를 사용하도록 허용합니다.
디버그 마스크 테스트
-
Apigee UI의 왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택한 후 bank-v1을 클릭합니다.
-
디버그 탭을 클릭합니다.
-
디버그 세션 시작 창의 환경 드롭다운에서 eval을 선택합니다.
-
시작을 클릭합니다.
-
Cloud Shell에서 SSH 연결이 닫힌 경우 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
-
토큰을 가져와 API 요청을 다시 실행합니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output)
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output)
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials")
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output)
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/customers/abe@example.org/accounts"
-
Apigee UI의 디버그 페이지로 돌아가서 GET 요청을 클릭합니다.
-
AM-GetSecret 정책을 클릭합니다.
propertyset.oauth.secret 변수가 마스킹됩니다.

-
백엔드 응답의 경우 프록시 응답 흐름 시작됨을 클릭합니다.
각 잔액 필드는 마스킹됩니다.

작업 8. 오류 처리
이 작업에서는 특정 백엔드 리소스에 대한 호출을 제한하는 기본 조건부 흐름을 만들고 백엔드 오류 메시지를 다시 작성합니다.
API 테스트
-
Cloud Shell에서 SSH 연결이 닫힌 경우 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
-
Y를 입력하여 계속 진행하고 ENTER 키를 두 번 눌러 암호를 비워둡니다.
-
토큰을 가져와 /users에 GET 요청을 보냅니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output)
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output)
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials")
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output)
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"
백엔드 서비스에서 GET /users 요청을 인식하지 못하므로 다음과 비슷한 404 응답이 반환됩니다.
HTTP/2 404
x-powered-by: Express
content-security-policy: default-src 'none'
x-content-type-options: nosniff
content-type: text/html; charset=utf-8
x-cloud-trace-context: 7e96528757cc5053ba4fc8853037b02d;o=1
date: Wed, 19 Jan 2022 01:49:53 GMT
server: Google Frontend
content-length: 144
x-request-id: 2d8c8002-3152-4fc2-a60b-1729dd5483d8
via: 1.1 google
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /users</pre>
</body>
</html>
응답에서 HTML 페이로드를 반환하며 이는 RF-InvalidTokenRequest 페이로드 형식과 일치하지 않습니다. 또한 백엔드 응답에 민감한 정보가 포함될 수 있습니다. 따라서 백엔드 서비스의 오류 응답을 다시 작성하는 것이 좋습니다.
404 Not Found 오류 다시 작성
오류 규칙을 사용하여 오류를 감지하고 오류 메시지를 다시 작성할 수 있습니다.
RaiseFault 정책은 새 응답을 설정하는 데 사용됩니다.
-
Cloud 콘솔에서 Apigee로 이동합니다.
-
왼쪽 탐색 메뉴에서 프록시 개발 > API 프록시를 선택한 후 bank-v1을 클릭합니다.
-
개발 탭을 클릭합니다.
-
프록시의 탐색기 메뉴에서 정책 옆에 있는 +를 클릭합니다.
-
미디에이션 섹션에서 오류 발생을 선택한 후 표시 이름과 이름을 RF-404NotFound로 설정합니다.
-
만들기를 클릭합니다. 정책 섹션에서 RF-404NotFound를 클릭합니다.
-
RaiseFault 정책 구성을 다음과 같이 변경합니다.
<RaiseFault name="RF-404NotFound">
<FaultResponse>
<Remove>
<Headers/>
</Remove>
<Set>
<StatusCode>404</StatusCode>
<ReasonPhrase>Not Found</ReasonPhrase>
<Headers>
<Header name="FaultName">{fault.name}</Header>
</Headers>
<Payload contentType="application/json">{
"error": "{request.verb} {proxy.pathsuffix} not found"
}</Payload>
</Set>
</FaultResponse>
<AssignTo createNew="true" type="response"/>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>
삭제 섹션은 먼저 백엔드 서비스에서 제공되었을 수 있는 모든 헤더를 삭제한 후 설정 섹션에서 응답을 만듭니다. 오류가 발생할 때 fault.name 변수 값을 표시하기 위해 FaultName 헤더가 추가되었습니다. fault.name 변수는 오류 이름을 지정합니다.
FaultRule 만들기
-
프록시의 탐색기 메뉴에 있는 대상 엔드포인트 섹션에서 기본값을 클릭합니다.
기본 대상 엔드포인트에는 404 응답을 반환하는 백엔드 대상 호출이 포함되어 있습니다. 404는 오류 코드로 취급됩니다. 엔드포인트에서 오류가 발생하며 대상 엔드포인트에 지정된 FaultRules를 사용하여 API 응답을 다시 작성할 수 있습니다.
-
TargetEndpoint 구성의 TargetEndpoint 태그 바로 아래에 다음 FaultRules 섹션을 추가합니다.
<FaultRules>
<FaultRule name="404">
<Step>
<Name>RF-404NotFound</Name>
</Step>
<Condition>response.status.code == 404</Condition>
</FaultRule>
</FaultRules>
이제 TargetEndpoint 시작 부분이 다음과 같이 표시됩니다.
<TargetEndpoint name="default">
<FaultRules>
<FaultRule name="404">
<Step>
<Name>RF-404NotFound</Name>
</Step>
<Condition>response.status.code == 404</Condition>
</FaultRule>
</FaultRules>
-
저장 > 새 버전으로 저장을 선택합니다.
-
배포를 클릭하고 환경에서 eval을 선택합니다.
-
서비스 계정에 서비스 계정 이메일 주소를 지정합니다.
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
배포를 클릭한 후 확인을 클릭합니다.
-
개요 탭을 클릭하고 eval 배포 상태에 프록시가 배포되었음이 표시될 때까지 기다립니다.
엔드포인트 응답 오류 테스트
-
Cloud Shell에서 SSH 연결이 닫힌 경우 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
-
토큰을 가져와 /users에 GET 요청을 보냅니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output)
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output)
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials")
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output)
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"
대답이 다시 작성되어 다음과 비슷하게 표시됩니다.
HTTP/2 404
faultname: ErrorResponseCode
content-type: application/json
x-request-id: 8d9db301-b3c7-4957-816d-93e796306dfb
content-length: 39
date: Tue, 18 Jan 2022 06:42:23 GMT
via: 1.1 google
{
"error": "GET /users not found"
}
이제 응답에서 JSON을 사용합니다. faultname 헤더 값은 ErrorResponseCode입니다. 이는 대상에서 실패 코드를 반환할 때 지정된 fault.name 변수의 값입니다. 백엔드 서비스에서 404 응답이 반환되자마자 오류가 발생하고 대상 엔드포인트 오류 규칙이 평가되었습니다. 그런 다음 404 오류 규칙에서 응답을 다시 작성했습니다.
404 조건부 흐름 추가
예상치 못한 요청이 전송될 때 백엔드에서 응답을 반환하는 대신 프록시 엔드포인트 조건부 흐름 끝에 새로운 조건부 흐름을 추가하여 다른 조건부 흐름이 조건과 일치하지 않을 때 오류를 발생시킬 수 있습니다. 이렇게 하면 조건부 흐름에 나열된 작업만 백엔드로 전달됩니다. 이 패턴을 사용하면 백엔드 서비스 리소스의 일부에만 액세스할 수 있습니다.
-
프록시의 탐색기 메뉴에서 프록시 엔드포인트: 기본값으로 이동한 후 흐름 섹션에서 /bank/v1 옆에 있는 +를 클릭합니다.
-
새 조건부 흐름의 경우 다음 값을 지정합니다.
| 속성 |
값 |
| 흐름 이름 |
404NotFound |
| 조건 유형 |
Custom 선택 |
| 조건 |
DELETETHIS |
-
추가를 클릭합니다.
-
404NotFound 흐름에서 다음 줄을 삭제합니다.
<Condition>DELETETHIS</Condition>
이전의 모든 조건부 흐름 조건이 일치하지 않으면 404NotFound 흐름이 실행됩니다.
-
프록시의 탐색기 메뉴에 있는 프록시 엔드포인트 섹션의 기본값에서 404NotFound를 클릭합니다.
-
흐름 창에서 404NotFound 요청 흐름 바로 옆에 있는 + 버튼을 클릭합니다.
-
정책 선택에서 기존 정책 선택을 선택한 후 RF-404NotFound를 클릭합니다.
-
추가를 클릭합니다.
-
저장 > 새 버전으로 저장을 선택합니다.
-
배포를 클릭한 후 환경에서 eval을 선택합니다.
-
서비스 계정에 서비스 계정 이메일 주소를 지정합니다.
apigee-internal-access@{{{ project_0.project_id | PROJECT }}}.iam.gserviceaccount.com
-
배포를 클릭한 후 확인을 클릭합니다.
-
개요 탭을 클릭하고 eval 배포 상태에 프록시가 배포되었음이 표시될 때까지 기다립니다.
내 진행 상황 확인하기를 클릭하여 목표를 확인합니다.
오류 처리 추가
404 조건부 흐름 테스트
-
Cloud Shell에서 SSH 연결이 닫힌 경우 테스트 VM에 대한 SSH 연결을 엽니다.
TEST_VM_ZONE=$(gcloud compute instances list --filter="name=('apigeex-test-vm')" --format "value(zone)")
gcloud compute ssh apigeex-test-vm --zone=${TEST_VM_ZONE} --force-key-file-overwrite
-
토큰을 가져와 /users에 GET 요청을 보냅니다.
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
export CONSUMER_KEY=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerKey" --raw-output)
export CONSUMER_SECRET=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -X GET "https://apigee.googleapis.com/v1/organizations/${PROJECT_ID}/developers/joe@example.com/apps/readonly-app" | jq ".credentials[0].consumerSecret" --raw-output)
export TOKEN_RESPONSE=$(curl -k -u "${CONSUMER_KEY}:${CONSUMER_SECRET}" -X POST "https://eval.example.com/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials")
export JWT_TOKEN=$(echo ${TOKEN_RESPONSE} | jq ".access_token" --raw-output)
curl -i -k -H "Authorization: Bearer ${JWT_TOKEN}" -X GET "https://eval.example.com/bank/v1/users"
대답이 다시 작성되어 다음과 비슷하게 표시됩니다.
HTTP/2 404
faultname: RaiseFault
content-type: application/json
x-request-id: d6bbd48f-65bd-4551-9236-636fad03a609
content-length: 39
date: Tue, 18 Jan 2022 07:07:58 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{
"error": "GET /users not found"
}
이제 faultname 헤더 값은 RaiseFault입니다. 이는 RaiseFault 정책으로 인해 오류가 발생했을 때 사용되는 fault.name 값입니다. 404NotFound 조건부 흐름의 RaiseFault 정책에서 응답을 생성했습니다.
수고하셨습니다
이 실습에서는 JWT OAuth 토큰을 요구하여 API를 보호했습니다. SpikeArrest 정책을 추가하여 트래픽을 제한했습니다. 비공개 변수와 데이터 마스킹을 사용하여 디버그 세션에서 민감한 정보를 숨겼습니다. 또한 백엔드 오류 메시지를 다시 작성하고 404 조건부 흐름을 사용하여 백엔드 호출을 특정 리소스로 제한했습니다.
다음 단계/더 학습하기
설명서 최종 업데이트: 2025년 8월 6일
실습 최종 테스트: 2025년 8월 6일
Copyright 2026 Google LLC. All rights reserved. Google 및 Google 로고는 Google LLC의 상표입니다. 기타 모든 회사명 및 제품명은 해당 업체의 상표일 수 있습니다.