本頁內容適用於 Apigee,但不適用於 Apigee Hybrid。
查看
Apigee Edge 說明文件。
本頁面說明如何使用適用於 Kubernetes 的 Apigee APIM 運算子,將 Apigee 執行階段政策和 Google 權杖插入政策 新增至 Google Kubernetes Engine (GKE) Gateway。在 Gateway 中新增一組可用的政策,即可將 Gateway 的功能擴展至 API 產品強制執行以外的範圍,納入額外的安全性和業務規則。
您可以使用 Kubernetes 適用的 Apigee APIM 運算子,將下列政策新增至 Gateway:
- SpikeArrest 政策
- JavaScript 政策
- Google 權杖插入政策
- GenerateJWT 政策
- KVM 政策
- OASValidation 政策
- 服務說明政策
- OAuthv2 政策
- ResponseCache 政策
- VerifyAPIKey 政策
總覽
以下各節將說明如何:
事前準備
如要使用本指南範例中的完整政策集修改 GKE Gateway,您必須擁有服務帳戶,並具備在 Apigee 中建立權杖,以及部署 Proxy 和擴充功能所需的角色。如果您選擇不建立 Google 權杖,就不必為服務帳戶新增其他角色,可以直接跳到下一節。
如何建立具備必要權限的服務帳戶:
- 如果您已在 Apigee APIM Operator for Kubernetes
安裝指南中建立名為
apigee-apim-gsa
的服務帳戶,可以略過這個步驟,直接前往下一個步驟。否則請建立服務帳戶:gcloud iam service-accounts create apigee-apim-gsa --project=$PROJECT_ID
- 授予服務帳戶建立權杖的必要角色:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \ --role "roles/iam.serviceAccountTokenCreator"
- 將部署 Proxy 和擴充功能所需的角色授予
apigee-apim-gsa
服務帳戶:gcloud projects add-iam-policy-binding $PROJECT_ID \ --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \ --role "roles/iam.serviceAccountUser"
透過政策修改 GKE 閘道
您可以選擇使用一或多項政策修改 GKE Gateway,擴充其功能。這個範例逐步說明如何將 yaml
檔案套用至 Gateway,其中包含兩項 Apigee 政策和 Google 權杖插入政策的規格。
使用下列 yaml
檔案套用至 Gateway 的每項政策,在評估傳送至 Gateway 的要求時,都會扮演不同的角色:
- SpikeArrest 政策會定義單位時間內允許的要求數上限,藉此控管訊息的尖峰速率。在本例中,上限設為每分鐘五次。如要進一步瞭解如何使用 SpikeArrest 政策,平緩流量突然暴增的情況,請參閱 SpikeArrest 政策。
- 您可以使用 JavaScript 政策,在閘道要求中加入自訂 JavaScript 程式碼。在本例中,這項政策用於在要求中新增自訂標頭。如要進一步瞭解如何使用 JavaScript 政策新增自訂程式碼,請參閱「JavaScript 政策」。
- Google 權杖插入政策會使用 AssignMessage 政策,將 Google 驗證存取權杖插入 Gateway 要求。Apigee 支援使用 Google OAuth 權杖或 OpenID Connect 權杖向 Google 服務進行驗證。如要進一步瞭解驗證權杖,請參閱「使用 Google 驗證」。
將政策新增至閘道:
- 在
apim
命名空間中,建立名為apigee-policies.yaml
的新檔案。 - 將下列檔案的內容複製到您建立的新檔案中:
# apigee-policies.yaml apiVersion: apim.googleapis.com/v1 kind: SpikeArrest metadata: name: spike-arrest namespace: apim spec: identifier: ref: request.header.name useEffectiveCount: true peakMessageRate: value: "5pm" --- apiVersion: apim.googleapis.com/v1 kind: Javascript metadata: name: js-add-headers namespace: apim spec: timeLimit: 2000 source: | var sum = 1+1; context.setVariable("request.header.first", 1); context.setVariable("request.header.second", 1); context.setVariable("request.header.sum", sum); --- apiVersion: apim.googleapis.com/v1 kind: AssignMessage metadata: name: google-token-policy namespace: apim spec: setActions: - authentication: googleAccessToken: scopes: - 'https://www.googleapis.com/auth/cloud-platform' AssignTo: createNew: false type: request --- apiVersion: apim.googleapis.com/v1 kind: KVM metadata: name: kvm-1 namespace: apim spec: delete: - keys: - value: mykey exclusiveCache: true expiryTimeInSecs: 3600 get: - assignTo: response.header.mykvm keys: - value: mykey initialEntries: - keys: - key1 values: - val1 - keys: - mykey values: - initvalue isEncrypted: false put: - keys: - value: mykey values: - value: request.header.mykvm scope: environment --- apiVersion: apim.googleapis.com/v1 kind: OASValidation metadata: name: oas-validation-1 namespace: apim spec: openApiSpec: | openapi: 3.0.4 info: title: Sample API description: Optional multi/single line description. version: 0.1.9 servers: - url: http://apigee-apim-operator-test.apigee.net description: Optional server description, our main host in httproute paths: /get: get: summary: just for test description: Optional extended description in CommonMark or HTML. parameters: - name: X-Request-Type in: header description: Must be 'internal' or 'external'. required: true schema: type: string enum: - internal - external responses: '200': # status code description: A JSON object content: application/json: schema: type: object properties: headers: type: object source: request --- apiVersion: apim.googleapis.com/v1 kind: ServiceCallout metadata: name: service-callout-1 namespace: apim spec: request: clearPayload: true variable: myRequest ignoreUnresolvedVariables: true removeActions: - payload: true - queryParams: - name: rq-param1 - name: rq-param2 copyActions: - version: true - verb: true addActions: - headers: - name: X-header1 value: value1 - name: X-header2 value: value2 - queryParams: - name: q-param1 value: value1 - name: q-param2 value: value2 setActions: - verb: PUT - formParams: - name: f-param1 value: value1 - name: f-param2 value: value2 response: calloutResponse timeout: 30000 httpTargetConnection: URL: https://httpbin.org/put properties: - name: success.codes value: 1xx,2xx,3xx,400 - name: supports.http11 value: "true"
- 使用下列指令將
yaml
檔案套用至閘道:kubectl -n apim apply -f apigee-policies.yaml
以 SharedFlow 範本的形式建立 TemplateRule
在本步驟中,您將建立 TemplateRule
,強制執行您新增至閘道的政策。
範本規則是機構管理員為 SharedFlows 建立的規則,可確保服務開發人員只會將核准的政策套用至閘道流量。範本規則可確保開發人員瞭解可用的政策、特定用途的必要政策,以及服務開發人員無法使用的政策。
建立範本規則
建立範本規則,強制執行 AssignMessage 政策的使用:
- 在
apim
命名空間中,建立名為template-rule.yaml
的新yaml
檔案。 - 將下列檔案的內容複製到您建立的新檔案中:
# template-rule.yaml apiVersion: apim.googleapis.com/v1 kind: ApimTemplateRule metadata: name: template-rule namespace: apim spec: allowList: [SpikeArrest, Javascript, GenerateJWT, KVM, OASValidation, OAuthv2, ServiceCallout] requiredList: [AssignMessage] denyList: []
在本範例中,範本規則會告知開發人員,說明 Google 權杖插入政策的 AssignMessage 政策為必要項目。此外,也告知開發人員可在 API 管理中使用 SpikeArrest、JavaScript、GenerateJWT、KVM、OASValidation、OAuthv2 和 ServiceCallout 政策。拒絕清單中未指定任何政策。
套用範本規則
使用下列指令套用範本規則:
kubectl apply -f template-rule.yaml
建立 Apigee 範本,以便使用範本規則
建立 Apigee 範本,加入您在前一節建立的範本規則:
- 在
apim
命名空間中,建立名為new-admin-template.yaml
的新yaml
檔案。 - 將下列檔案的內容複製到您建立的新檔案中:
# new-admin-template.yaml apiVersion: apim.googleapis.com/v1 kind: ApimTemplate metadata: name: new-admin-template namespace: apim spec: apimTemplateRule: group: apim.googleapis.com kind: ApimTemplateRule name: template-rule namespace: apim templates: - mode: REQUEST flows: - name: preflow policies: - group: apim.googleapis.com kind: OASValidation name: oas-validation-1 namespace: apim - group: apim.googleapis.com kind: SpikeArrest name: spike-arrest namespace: apim - name: ConditionalGetFlow policies: - group: apim.googleapis.com kind: Javascript name: js-add-headers namespace: apim condition: request.verb="GET" - name: postflow policies: - group: apim.googleapis.com kind: AssignMessage name: google-token-policy namespace: apim - group: apim.googleapis.com kind: ServiceCallout name: service-callout-1 namespace: apim - mode: RESPONSE flows: - name: postflow policies: - group: apim.googleapis.com kind: KVM name: kvm-1 namespace: apim
- 使用下列指令套用新範本:
kubectl apply -f new-admin-template.yaml
部署 Apigee Gateway 政策
在這個步驟中,您會將新檔案套用至 Gateway,其中包含 ApigeeGatewayPolicy
的規格。
這項政策用於將 Apigee 範本部署至閘道。
部署 Apigee Gateway 政策:
- 在
apim
命名空間中,建立名為apigee-gateway-policy-withSA.yaml
的新yaml
檔案。 - 將下列檔案的內容複製到您建立的新檔案中:
# apigee-gateway-policy-withSA.yaml apiVersion: apim.googleapis.com/v1 kind: ApigeeGatewayPolicy metadata: name: apim-template-injection namespace: apim spec: serviceAccount: apigee-apim-gsa@PROJECT_ID.iam.gserviceaccount.com ref: group: apim.googleapis.com kind: ApimTemplate name: new-admin-template namespace: apim targetRef: group: apim.googleapis.com kind: APIMExtensionPolicy name: global-ext-lb1-apim-policy namespace: apim
- 套用政策:
kubectl apply -f apigee-gateway-policy-withSA.yaml
- 確認新閘道政策的部署狀態:
kubectl -n apim get ApigeeGatewayPolicy
部署完成後,政策
STATUS
應會顯示CREATED
。
部署新的 Gateway 政策後,請等待兩分鐘再向 Gateway 傳送要求,讓政策傳播至叢集。
驗證政策強制執行
如要確認 Apigee Gateway 政策是否正常運作,請按照下列各節所述,將要求傳送至 Gateway。
AssignMessage 政策執行
如要確認 {company_name} 權杖是否已透過 AssignMessage 政策注入要求,請使用下列指令將要求傳送至 Gateway:
curl http://GATEWAY_IP_ADDRESS/get -H "Host: HOST_NAME" -H "x-api-key: API_KEY"
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址:kubectl get gateway GATEWAY_NAME
HOST_NAME
是主機名稱。API_KEY
是 API 金鑰值。
成功的回應應包含 Authorization
標頭和產生的承載權杖,類似於下列內容:
{ "args": {}, "headers": { "Accept": "*/*", "Authorization": "Bearer ya29.c.c0ASRK0Gbw03y9cfvxL11DxaRYBQUU18SmUP4Vu63OckHI5cX7wJ4DmGMG2vbDDS69HXJHqMj-lak4tcqOsJGmE65crn2gNuJLanXidwM8", "First": "1.0", "Host": "apigee-apim-operator-test.apigee.net", "Second": "1.0", "Sum": "2", "User-Agent": "curl/8.7.1", "X-Api-Key": "McYcHGR3PTSGLXExvKADwQ1JJeCjgPDUvAakCl0rJKCFaX0Y", "X-Cloud-Trace-Context": "0fd3dadc2a3c328fa968d5f5f1434c29/18300783092696918345" }, "origin": "34.54.108.129", "url": "apigee-apim-operator-test.apigee.net/get" }
強制執行 SpikeArrest 政策
如要測試 SpikeArrest 政策的強制執行情況,請在一分鐘內向閘道傳送十次要求。
您可以執行下列指令碼來產生要求:
#!/bin/sh for i in $(seq 1 11); do curl http://GATEWAY_IP_ADDRESS/get -H "Host: HOST_NAME" -H "x-api-key: API_KEY" sleep 1 done
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。
回覆內容應如下所示:
"fault":{"faultstring":"Spike arrest violation. Allowed rate : MessageRate{capacity=5, period=Minutes}","detail":{"errorcode":"policies.ratelimit.SpikeArrestViolation"}}}
JavaScript 政策執行
如要確認 JavaScript 政策是否正常運作,請使用下列指令向 Gateway 傳送要求:
curl http://GATEWAY_IP_ADDRESS/get \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。
JavaScript 政策會設定三個要求標頭:First
、Second
和 Sum
,如回應所示:
HTTP/1.1 200 OK ... { "args": {}, "headers": { ... "First": "1.0", ... "Second": "1.0", "Sum": "2", ... }, ... }
強制執行 OASValidation 政策
如要確認 OASValidation 政策是否正常運作,請使用下列指令將要求傳送至閘道:
curl "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: badvalue"
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。
指令包含 X-Request-Type
標頭的無效值。要求會失敗,並傳回類似以下的回應:
{"fault":{"faultstring":"OASValidation oas-validation-1 with resource \"oas:\/\/oas-validation-1.yaml\": failed with reason: \"[ERROR - Instance value (\"badvalue\") not found in enum (possible values: [\"internal\",\"external\"]): []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}
只要為 X-Request-Type
標頭傳送有效值,就能成功傳送相同要求。例如:
curl "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。
強制執行 ServiceCallout 政策
如要驗證 ServiceCallout 政策的強制執行情況,請開啟偵錯工作階段,並傳送幾個有效要求至 Proxy。
如要開啟偵錯工作階段,請按照下列步驟操作:
- 前往 Google Cloud 控制台的「API Proxies」頁面。
- 選取您部署至 Apigee APIM Operator for Kubernetes 所建立環境的
global-ext-lb1-apim-policy
Proxy。 - 按一下「Debug」分頁標籤。
- 在「Debug session」視窗中,按一下「Start Debug Session」。
- 在「Debug session」(偵錯工作階段) 窗格中,選取下列項目:
- 環境:從可用環境清單中,選取您為 APIM 運算子建立的環境。
- 篩選:選取「無 (所有交易)」。
- 按一下「啟動」。
工作階段開始後,您就可以將有效要求傳送至 Proxy:
curl "GATEWAY_IP_ADDRESSget" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateway GATEWAY_NAME
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。
「Transactions」(交易) 窗格會顯示要求和回應交易。從清單中選取一筆成功交易,即可顯示流程。您應該會看到 ServiceCallout
政策執行成功的訊息。
強制執行 KVM 政策
KVM 政策順利執行後,會使用金鑰 mykey
的起始值初始化 KVM。
如果存在回應交易,KVM 政策會擷取 mykey
的值,並儲存在回應標頭 mykvm
中。
KVM 政策再次執行時,會插入從要求標頭 mykvm
取得的 mykey
新值。
您可以檢查每筆交易的標頭,確認政策是否在一筆交易中將值儲存在 KVM,並在下一筆交易中擷取相同的值,如下例所示。
測試 KVM 政策:
- 將要求傳送至閘道:
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" \ -H "KVM_NAME: next-value1" -i
其中:
GATEWAY_IP_ADDRESS
是閘道的 IP 位址。您可以使用下列指令擷取閘道 IP 位址,其中GATEWAY_NAME
是閘道的名稱:kubectl get gateway GATEWAY_NAME
HOST_NAME
是在 Gateway 的HTTPRoute
中定義的主機名稱。API_KEY
是在「測試設定」中取得的 API 金鑰值。KVM_NAME
是 KVM 的名稱。
- 檢查回應標頭,確認 KVM 政策已順利執行,且已為
mykvm
儲存初始值。回應應如下所示:HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: initvalue via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get" } }
- 向閘道傳送另一項要求:
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "mykvm: next"X-Request-Type: external" -H "mykvm: next-value2" -i
回覆應類似如下:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: next-value2 via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get?rq-param2=rq-val1&x-param1=xval1" } }
您可以看到
mykvm
標頭的值已更新為要求標頭mykvm
的值,因此 KVM 政策已成功執行。 - 再傳送一項要求:
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -H "mykvm: next-value3" -i
回覆應類似如下:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: next-value2 via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get?rq-param2=rq-val1&x-param1=xval1" } }
mykvm
標頭的值再次更新,顯示回應中顯示的值是先前交易中儲存的值。
疑難排解
如果在 GKE Gateway 中新增政策時遇到問題,請參閱「排解 APIM 運算子問題」,瞭解如何解決常見錯誤。
後續步驟
- 進一步瞭解 SpikeArrest 政策。
- 進一步瞭解 JavaScript 政策。