本页面适用于 Apigee,但不适用于 Apigee Hybrid。
查看 Apigee Edge 文档。
本页面介绍了如何使用 Apigee APIM Operator for Kubernetes 将 Apigee 运行时政策和 Google 令牌注入政策添加到 Google Kubernetes Engine (GKE) 网关。 通过将一组可用的政策添加到网关,您可以将网关的功能扩展到 API 产品实施范围之外,以包含其他安全和业务规则。
Apigee APIM Operator for Kubernetes 可用于向网关添加以下政策:
- SpikeArrest 政策
- JavaScript 政策
- Google 令牌注入政策
- GenerateJWT 政策
- KVM 政策
- OASValidation 政策
- ServiceCallout 政策
- OAuthv2 政策
- ResponseCache 政策
- VerifyAPIKey 政策
概览
以下各部分介绍如何执行以下操作:
准备工作
如需使用本指南中用作示例的完整的政策集修改 GKE 网关,您必须拥有一个服务账号,并具有在 Apigee 中创建令牌以及部署代理和扩展程序所需的角色。如果您选择不创建 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"
- 为
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 网关,以扩展其功能。本示例演示将 yaml
文件应用于网关,该文件包含两项 Apigee 政策和一项 Google 令牌注入政策的规范。
使用以下 yaml
文件向网关应用的每项政策在评估发送到网关的请求时都会发挥不同的作用:
- SpikeArrest 政策通过定义单位时间内允许的请求数上限来控制峰值消息速率。在此示例中,速率上限设置为每分钟 5 个。如需详细了解如何使用 SpikeArrest 政策来平滑流量的突然激增,请参阅 SpikeArrest 政策。
- 借助 JavaScript 政策,您可以将自定义 JavaScript 代码添加到网关请求。在此示例中,该政策用于将自定义标头添加到请求。如需详细了解如何使用 JavaScript 政策添加自定义代码,请参阅 JavaScript 政策。
- Google 令牌注入政策用于使用 AssignMessage 政策将 Google 身份验证访问令牌注入到网关请求中。 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
创建 TemplateRule 作为 SharedFlow 模板
在此步骤中,您将创建一个 TemplateRule
以实施您已添加到网关的政策。
模板规则是组织管理员为 SharedFlow 创建的规则,以确保服务开发者仅将已获批准的政策应用于网关流量。模板规则可确保开发者了解哪些政策可供他们使用、哪些政策是特定应用场景所必需的,以及服务开发者无法使用哪些政策。
创建模板规则
创建一个模板规则,以强制使用 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 网关政策
在此步骤中,您将向网关应用一个包含 ApigeeGatewayPolicy
规范的新文件。
此政策用于将 Apigee 模板部署到网关。
部署 Apigee 网关政策:
- 在
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
。
部署新的网关政策后,请等待两分钟,然后再向网关发送请求,以便政策传播到集群。
验证政策实施情况
如需确认 Apigee 网关政策按预期正常生效,请按照以下部分中的说明向网关发送请求。
AssignMessage 政策强制执行
如需确认 {company_name} 令牌已使用 AssignMessage 政策注入到请求中,请使用以下命令向网关发送请求:
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 政策强制执行
您可以在 1 分钟内向网关发送 10 次请求,以测试 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
是网关的HTTPRoute
中定义的主机名。API_KEY
是在测试设置中获取的 API 密钥值。
响应将类似如下所示:
"fault":{"faultstring":"Spike arrest violation. Allowed rate : MessageRate{capacity=5, period=Minutes}","detail":{"errorcode":"policies.ratelimit.SpikeArrestViolation"}}}
JavaScript 政策强制执行
如需确认 JavaScript 政策按预期正常生效,请使用以下命令向网关发送请求:
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
是网关的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
是网关的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
是网关的HTTPRoute
中定义的主机名。API_KEY
是在测试设置中获取的 API 密钥值。
ServiceCallout 政策强制执行
您可以打开调试会话并向代理发送一些有效请求,以验证 ServiceCallout 政策的强制执行情况。
如需打开调试会话,请按照以下步骤操作:
- 在 Google Cloud 控制台中,前往 API 代理页面。
- 选择您部署到为 Apigee APIM Operator for Kubernetes 创建的环境中的
global-ext-lb1-apim-policy
代理。 - 点击调试标签页。
- 在调试会话窗口中,点击启动调试会话。
- 在调试会话窗格中,进行以下选择:
- 环境:从可用环境列表中选择您为 APIM Operator 创建的环境。
- 过滤条件:选择无(所有事务)。
- 点击开始。
会话开始后,您可以向代理发送有效请求:
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
是网关的HTTPRoute
中定义的主机名。API_KEY
是在测试设置中获取的 API 密钥值。
请求和响应事务会显示在事务窗格中。从列表中选择一笔成功交易,以显示相应流程。您应该能够看到 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
是网关的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" } }
您可以看到,KVM 政策已成功执行,因为
mykvm
标头的值已更新为请求标头mykvm
的值。 - 再发送一个请求:
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 网关添加政策时遇到问题,请参阅排查 APIM Operator 问题,以了解常见错误的解决方案。
后续步骤
- 详细了解 SpikeArrest 政策。
- 详细了解 JavaScript 政策。