Agrega políticas a la puerta de enlace de GKE

Esta página se aplica a Apigee, pero no a Apigee Hybrid.

Consulta la documentación de Apigee Edge.

En esta página, se describe cómo agregar políticas de tiempo de ejecución de Apigee y una política de inserción de tokens Google al Gateway de Google Kubernetes Engine (GKE) con el operador de APIM de Apigee para Kubernetes. Agregar un conjunto de políticas disponibles a la puerta de enlace te permite extender su funcionalidad más allá de la aplicación de productos de API para incluir reglas comerciales y de seguridad adicionales.

El operador de APIM de Apigee para Kubernetes se puede usar para agregar las siguientes políticas a la puerta de enlace:

Descripción general

En las secciones que aparecen a continuación, se describe cómo realizar las siguientes tareas:

Antes de comenzar

Para modificar tu puerta de enlace de GKE con el conjunto completo de políticas que se usan como ejemplo en esta guía, debes tener una cuenta de servicio con los roles necesarios para crear tokens en Apigee y, luego, implementar proxies y extensiones. Si eliges no crear tokens de Google , no es necesario que agregues los roles adicionales a tu cuenta de servicio y puedes pasar a la siguiente sección.

Para crear una cuenta de servicio con los permisos requeridos, sigue estos pasos:

  1. Si creaste una cuenta de servicio llamada apigee-apim-gsa en la guía de instalación del operador de APIM de Apigee para Kubernetes, puedes omitir este paso y continuar con el siguiente. De lo contrario, crea la cuenta de servicio:
    gcloud iam service-accounts create apigee-apim-gsa --project=$PROJECT_ID
  2. Otorga a la cuenta de servicio el rol necesario para crear tokens:
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/iam.serviceAccountTokenCreator"
  3. Otorga a la cuenta de servicio apigee-apim-gsa el rol necesario para implementar proxies y extensiones:
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/iam.serviceAccountUser"

Modifica tu puerta de enlace de GKE con políticas

Puedes optar por modificar tu GKE Gateway con una o más políticas para extender su funcionalidad. En este ejemplo, se aplica un archivo yaml a la puerta de enlace que incluye las especificaciones de dos políticas de Apigee y una política de inserción de tokens de Google .

Cada una de las políticas aplicadas a la puerta de enlace con el siguiente archivo yaml cumple un rol diferente cuando se evalúan las solicitudes enviadas a la puerta de enlace:

  • La política de SpikeArrest controla la tasa máxima de mensajes definiendo una tasa máxima de solicitudes permitidas durante una unidad de tiempo. En este ejemplo, la frecuencia máxima se establece en cinco por minuto. Para obtener más información sobre cómo se usa la política SpikeArrest para suavizar los aumentos repentinos en el tráfico, consulta la política SpikeArrest.
  • La política de JavaScript te permite agregar código JavaScript personalizado a las solicitudes de Gateway. En este ejemplo, la política se usa para agregar un encabezado personalizado a la solicitud. Para obtener más información sobre cómo se usa la política de JavaScript para agregar código personalizado, consulta la política de JavaScript.
  • La política de inserción de tokens Google se usa para insertar un token de acceso de autenticación Google en las solicitudes de la puerta de enlace, mediante la política AssignMessage. Apigee admite el uso de Google tokens de OAuth o tokens de OpenID Connect para autenticarse con Google servicios. Para obtener más información sobre los tokens de autenticación, consulta Usa la autenticación de Google.

Agrega las políticas a la puerta de enlace:

  1. Crea un archivo nuevo llamado apigee-policies.yaml en el espacio de nombres apim.
  2. Copia el contenido del siguiente archivo en el archivo nuevo que creaste:
    # 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"
  3. Aplica el archivo yaml a la puerta de enlace con el siguiente comando:
    kubectl -n apim apply -f apigee-policies.yaml

Crea un TemplateRule como plantilla de SharedFlow

En este paso, crearás un objeto TemplateRule para aplicar las políticas que agregaste a la puerta de enlace. Una regla de plantilla es una regla para SharedFlows creada por los administradores de la organización para garantizar que los desarrolladores de servicios solo apliquen políticas aprobadas al tráfico de la puerta de enlace. Una regla de plantilla garantiza que los desarrolladores comprendan qué políticas están disponibles para ellos, qué políticas son obligatorias para casos de uso específicos y qué políticas no pueden usar los desarrolladores de servicios.

Crea una regla de plantilla

Crea una regla de plantilla para aplicar el uso de la política AssignMessage:

  1. Crea un archivo yaml nuevo llamado template-rule.yaml en el espacio de nombres apim.
  2. Copia el contenido del siguiente archivo en el archivo nuevo que creaste:
    # 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: []

    En este ejemplo, la regla de plantilla les indica a los desarrolladores que se requiere la política de AssignMessage que describe la política de inserción de tokens Google . También les indica a los desarrolladores que pueden usar las políticas SpikeArrest, JavaScript, GenerateJWT, KVM, OASValidation, OAuthv2 y ServiceCallout en su administración de APIs. No se especificaron políticas en la lista de bloqueo.

Aplica la regla de plantilla

Aplica la regla de plantilla con el siguiente comando:

kubectl apply -f template-rule.yaml

Crea una plantilla de Apigee para usar la regla de plantilla

Crea una plantilla de Apigee para incluir la regla de plantilla que creaste en la sección anterior:

  1. Crea un archivo yaml nuevo llamado new-admin-template.yaml en el espacio de nombres apim.
  2. Copia el contenido del siguiente archivo en el archivo nuevo que creaste:
    # 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
  3. Aplica la nueva plantilla con el siguiente comando:
    kubectl apply -f new-admin-template.yaml

Implementa la política de Apigee Gateway

En este paso, aplicarás un archivo nuevo a tu puerta de enlace que incluye las especificaciones para un ApigeeGatewayPolicy. Esta política se usa para implementar la plantilla de Apigee en la puerta de enlace.

Implementa la política de Apigee Gateway:

  1. Crea un archivo yaml nuevo llamado apigee-gateway-policy-withSA.yaml en el espacio de nombres apim.
  2. Copia el contenido del siguiente archivo en el archivo nuevo que creaste:
    # 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
  3. Aplica la política:
    kubectl apply -f apigee-gateway-policy-withSA.yaml
  4. Verifica el estado de implementación de la nueva política de Gateway:
    kubectl -n apim get ApigeeGatewayPolicy

    Una vez implementada, la política STATUS debería mostrar CREATED.

Después de que se implemente la nueva política de Gateway, espera dos minutos antes de enviar una solicitud a la puerta de enlace para permitir que la política se propague al clúster.

Valida la aplicación de la política

Para confirmar que las políticas de Apigee Gateway funcionan según lo previsto, envía solicitudes a la Gateway como se describe en las siguientes secciones.

Aplicación de la política AssignMessage

Para confirmar que el token {company_name} se inserta en la solicitud con la política AssignMessage, envía una solicitud a la puerta de enlace con el siguiente comando:

curl http://GATEWAY_IP_ADDRESS/get -H "Host: HOST_NAME" -H "x-api-key: API_KEY"

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando:
    kubectl get gateway GATEWAY_NAME
  • HOST_NAME es el nombre del host.
  • API_KEY es el valor de la clave de API.

Una respuesta correcta debe incluir un encabezado Authorization con el token de portador generado, similar al siguiente:

{
  "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"
}

Aplicación de la política de SpikeArrest

Puedes probar la aplicación de la política de SpikeArrest enviando una solicitud a la puerta de enlace diez veces en el lapso de un minuto.

Puedes ejecutar la siguiente secuencia de comandos para generar las solicitudes:

#!/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

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
    kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
  • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
  • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.

La respuesta se verá similar a la siguiente:

"fault":{"faultstring":"Spike arrest violation. Allowed rate : MessageRate{capacity=5, period=Minutes}","detail":{"errorcode":"policies.ratelimit.SpikeArrestViolation"}}}

Aplicación de la política de JavaScript

Para confirmar que la política de JavaScript funciona según lo esperado, envía una solicitud a la puerta de enlace con el siguiente comando:

curl http://GATEWAY_IP_ADDRESS/get \
  -H "Host: HOST_NAME" \
  -H "x-api-key: API_KEY" \
  -H "X-Request-Type: external" -i

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
    kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
  • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
  • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.

La política de JavaScript establece tres encabezados de solicitud: First, Second y Sum, como se muestra en la respuesta:

HTTP/1.1 200 OK
...
{
  "args": {},
  "headers": {
    ...
    "First": "1.0",
    ...
    "Second": "1.0",
    "Sum": "2",
    ...
  },
  ...
}

Aplicación de la política OASValidation

Para confirmar que la política de OASValidation funciona según lo esperado, envía una solicitud a la puerta de enlace con el siguiente comando:

curl "http://GATEWAY_IP_ADDRESS/get"  \
  -H "Host: HOST_NAME" \
  -H "x-api-key: API_KEY" \
  -H "X-Request-Type: badvalue"

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
    kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
  • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
  • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.

El comando incluye un valor no válido para el encabezado X-Request-Type. La solicitud fallará con una respuesta similar a la siguiente:

{"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"}}}

Si envías la misma solicitud con un valor válido para el encabezado X-Request-Type, se realizará correctamente. Por ejemplo:

curl "http://GATEWAY_IP_ADDRESS/get"  \
  -H "Host: HOST_NAME" \
  -H "x-api-key: API_KEY" \
  -H "X-Request-Type: external" -i

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
    kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
  • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
  • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.

Aplicación de la política de ServiceCallout

Para verificar la aplicación de la política ServiceCallout, abre una sesión de depuración y envía algunas solicitudes válidas al proxy.

Para abrir una sesión de depuración, sigue estos pasos:

  1. En la consola de Google Cloud , ve a la página API Proxies.

    Ir a Proxies de API

  2. Selecciona el proxy global-ext-lb1-apim-policy que implementaste en el entorno creado para el operador de APIM de Apigee para Kubernetes.
  3. Haz clic en la pestaña Depurar.
  4. En la ventana Sesión de depuración, haz clic en Iniciar sesión de depuración.
  5. En el panel Sesión de depuración, realiza las siguientes selecciones:
    • Entorno: Selecciona el entorno que creaste para el operador de APIM en la lista de entornos disponibles.
    • Filtro: Selecciona Ninguno (todas las transacciones).
  6. Haz clic en Iniciar.

Una vez que se inicia la sesión, puedes enviar solicitudes válidas al proxy:

curl "GATEWAY_IP_ADDRESSget"  \
  -H "Host: HOST_NAME" \
  -H "x-api-key: API_KEY" \
  -H "X-Request-Type: external" -i

Aquí:

  • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
    kubectl get gateway GATEWAY_NAME
  • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
  • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.

Las transacciones de solicitud y respuesta se muestran en el panel Transacciones. Selecciona una transacción exitosa de la lista para mostrar el flujo. Deberías poder ver que la política de ServiceCallout se ejecutó correctamente.

Aplicación de la política de KVM

Cuando la política de KVM se ejecuta correctamente, inicializa el KVM con un valor inicial para la clave mykey. Cuando hay una transacción de respuesta, la política de KVM recupera el valor de mykey y lo almacena en el encabezado de respuesta mykvm. Cuando la política de KVM se ejecuta de nuevo, inserta el valor nuevo para mykey que se obtuvo del encabezado de la solicitud mykvm.

Puedes verificar los encabezados de cada transacción para confirmar que la política almacena un valor en el KVM en una transacción y recupera el mismo valor en la siguiente, como se muestra en el siguiente ejemplo.

Prueba la política de KVM:

  1. Envía una solicitud a la puerta de enlace:
    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

    Aquí:

    • GATEWAY_IP_ADDRESS es la dirección IP de la puerta de enlace. Puedes recuperar la dirección IP de la puerta de enlace con el siguiente comando, en el que GATEWAY_NAME es el nombre de la puerta de enlace:
      kubectl get gateway GATEWAY_NAME
    • HOST_NAME es el nombre de host definido en el HTTPRoute de la puerta de enlace.
    • API_KEY es el valor de la clave de API que se obtuvo en Configuración de prueba.
    • KVM_NAME es el nombre del KVM.

  2. Revisa los encabezados de respuesta para confirmar que la política de KVM se ejecutó correctamente y que se almacenó un valor inicial para mykvm. La respuesta debería ser similar a la siguiente:
    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"
      }
    }
  3. Envía otra solicitud a la puerta de enlace:
    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

    La respuesta podría ser similar a la siguiente:

    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"
      }
    }

    Puedes ver que la política de KVM se ejecutó correctamente porque el valor del encabezado mykvm se actualizó al valor del encabezado de solicitud mykvm.

  4. Envía una solicitud más:
    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

    La respuesta podría ser similar a la siguiente:

    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"
      }
    }

    El valor del encabezado mykvm se vuelve a actualizar, lo que muestra que el valor que se muestra en la respuesta son los valores almacenados en la transacción anterior.

Solucionar problemas

Si tienes problemas para agregar políticas a GKE Gateway, consulta Soluciona problemas del operador de APIM para encontrar soluciones a errores comunes.

¿Qué sigue?