Extensões do OpenAPI 2.0 no gateway de API

O API Gateway aceita um conjunto de extensões específicas do Google para a especificação OpenAPI que configuram os comportamentos do gateway. Nesta página, descrevemos extensões personalizadas específicas do Google para a especificação OpenAPI 2.0 (em inglês) usadas para configurar comportamentos do gateway de API, como roteamento de back-end, autenticação e recursos de gerenciamento de API.

Os exemplos abaixo estão no formato YAML, mas o formato JSON também é aceito.

Convenção de nomenclatura

Os nomes das extensões da OpenAPI do Google começam com o prefixo x-google-.

x-google-allow

x-google-allow: [configured | all]

Essa extensão é usada no nível superior de uma especificação OpenAPI para indicar quais caminhos do URL precisam ser autorizados pelo gateway de API.

Os valores possíveis são configured e all.

O valor padrão é configured, o que significa que apenas os métodos da API listados na especificação OpenAPI são veiculados pelo gateway de API.

Ao usar all, as chamadas não configuradas, com ou sem uma chave de API ou autenticação de usuário, passarão pelo gateway de API para a API.

A API Gateway processa chamadas para sua API com diferenciação de maiúsculas e minúsculas. Por exemplo, o gateway de API considera /widgets e /Widgets como métodos de API diferentes.

Ao usar all, é preciso ter maior cuidado em duas áreas:

  • Chaves de API ou regras de autenticação
  • o roteamento do caminho do back-end no serviço

Como prática recomendada, o ideal é configurar a API para usar o roteamento de caminho com diferenciação de maiúsculas e minúsculas. Assim, a API retorna um código de status HTTP 404 quando o método solicitado na URL não corresponde ao nome do método de API listado na especificação OpenAPI. Os frameworks de aplicativos da Web, como o Node.js Express, têm uma configuração para ativar ou desativar o roteamento com diferenciação de maiúsculas e minúsculas. O comportamento padrão depende da biblioteca utilizada. Convém rever as configurações na biblioteca para ter certeza de que o roteamento com diferenciação de maiúsculas e minúsculas está ativado. Essa recomendação coincide com o v2.0 da especificação OpenAPI, que afirma: "Todos os nomes de campo na especificação diferenciam maiúsculas de minúsculas".

Exemplo

Suponha que:

  • x-google-allow está definida como all;
  • o método widgets da API está listado na especificação OpenAPI, mas o Widgets, não;
  • a especificação OpenAPI foi configurada para exigir uma chave de API.

Como widgets está listado na especificação OpenAPI, o gateway de API bloqueia a solicitação a seguir porque ela não tem uma chave de API:

https://my-project-id.appspot.com/widgets

Como Widgets não está listado na especificação OpenAPI, o API Gateway transmite a solicitação a seguir para o serviço sem uma chave de API:

https://my-project-id.appspot.com/Widgets/

Se a API usar roteamento com diferenciação de maiúsculas e minúsculas, e você não tiver roteado chamadas a "Widgets" para qualquer código, o back-end da API retornará 404. Caso contrário, o back-end da API roteará essa chamada para "widgets".

Frameworks e linguagens diferentes têm métodos distintos para controlar o roteamento e a diferenciação de maiúsculas e minúsculas. Para mais detalhes, consulte a documentação do framework.

x-google-backend

A extensão x-google-backend especifica como rotear solicitações para back-ends remotos. A extensão pode ser especificada no nível superior, no nível de operação ou em ambos os níveis de uma especificação OpenAPI.

A extensão x-google-backend também pode definir outras configurações para back-ends remotos, como autenticação e tempo limite. Todas essas configurações podem ser aplicadas por operação.

A extensão x-google-backend contém os seguintes campos:

address

address: URL

Obrigatório. O URL do back-end de destino. O esquema do endereço precisa ser http ou https.

Ao rotear para back-ends remotos (sem servidor), o endereço precisa ser definido e a parte do esquema precisa ser https.

jwt_audience | disable_auth

Defina apenas uma dessas duas propriedades.

Se uma operação usar x-google-backend, mas não especificar jwt_audience ou disable_auth, o gateway de API adotará automaticamente o jwt_audience como padrão para corresponder ao address. Se address não estiver definido, o API Gateway vai definir automaticamente disable_auth como true.

jwt_audience

jwt_audience: string

Opcional. O público do JWT especificado quando o API Gateway obtém um token de ID da instância, que é usado ao fazer a solicitação de back-end de destino.

Ao configurar o API Gateway para sem servidor, o back-end remoto precisa ser protegido para permitir somente o tráfego do API Gateway. A API Gateway anexa um token do ID de instância ao cabeçalho Authorization ao representar solicitações por proxy. O token de ID de instância representa a conta de serviço do ambiente de execução usada para implantar o gateway de API. O back-end remoto pode verificar se a solicitação é do gateway de API com base nesse token anexado.

Por exemplo, um back-end remoto implantado no Cloud Run pode usar o Identity and Access Management (IAM) para:

  1. Para restringir invocações não autenticadas, revogue roles/run.invoker do principal allUsers especial.
  2. Permitir que apenas o gateway de API invoque o back-end concedendo o papel roles/run.invoker à conta de serviço do ambiente de execução do gateway de API.

Por padrão, o gateway de API cria o token de ID da instância com um público-alvo do JWT que corresponde ao campo address. Especificar jwt_audience manualmente é necessário somente quando o back-end de destino usa autenticação com base no JWT, e o público esperado é diferente do valor especificado no campo address. Para back-ends remotos implantados no App Engine ou com o Identity-Aware Proxy (IAP), modifique o público-alvo do JWT. O App Engine e o IAP usam o ID do cliente OAuth como público esperado.

Quando esse recurso está ativado, o API Gateway altera os cabeçalhos nas solicitações. Se uma solicitação tiver o cabeçalho Authorization já definido, o gateway de API:

  1. Copia o valor original para um novo cabeçalho X-Forwarded-Authorization.
  2. Substitui o cabeçalho Authorization pelo token do ID da instância.

Portanto, se um cliente da API definir o cabeçalho Authorization, um back-end executado por trás do API Gateway deverá usar o cabeçalho X-Forwarded-Authorization para recuperar todo o JWT. O back-end precisa verificar o JWT nesse cabeçalho, já que o gateway de API não vai realizar a verificação quando os métodos de autenticação não estiverem configurados.

Para exemplos de configuração, consulte Como criar uma configuração de API.

disable_auth

disable_auth: bool

Opcional. Essa propriedade determina se o API Gateway deve impedir o recebimento de um token de ID da instância. Além disso, também impede que ele seja anexado à solicitação.

Ao configurar o back-end de destino, talvez você não queira usar o IAP ou o IAM para autenticar solicitações do API Gateway se uma destas condições for aplicável:

  1. O back-end permite invocações não autenticadas.
  2. O back-end requer o cabeçalho Authorization original do cliente da API e não pode usar X-Forwarded-Authorization (descrito na seção jwt_audience).

Nesse caso, defina esse campo como true.

path_translation

path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]

Opcional. Define a estratégia de conversão de caminho usada pelo API Gateway ao enviar solicitações de proxy para o back-end de destino.

Para mais detalhes sobre a tradução de caminho, consulte a seção Entender a conversão de caminho.

Quando x-google-backend é usado no nível superior da especificação OpenAPI, path_translation assume como padrão APPEND_PATH_TO_ADDRESS e quando x-google-backend é usado no nível operacional da especificação OpenAPI, path_translation assume como padrão CONSTANT_ADDRESS. Se o campo address estiver ausente, path_translation vai continuar não especificado e não vai ocorrer.

deadline

deadline: double

Opcional. O número de segundos de espera para uma resposta completa de uma solicitação. As respostas que demoram mais do que o prazo configurado expirarão. O prazo padrão é de 15.0 segundos.

Valores não positivos não serão respeitados. O gateway de API usará automaticamente o valor padrão nesses casos.

O prazo não pode ser desativado, mas pode ser definido como um número alto, por exemplo, 600 segundos (o prazo máximo).

protocol

protocol: [ http/1.1 | h2 ]

Opcional. O protocolo usado para enviar uma solicitação ao back-end. Os valores compatíveis são http/1.1 e h2.

O valor padrão é http/1.1 para back-ends HTTP e HTTPS.

Para back-ends HTTP seguros (https://) compatíveis com HTTP/2, defina o campo como h2 para melhorar o desempenho. Essa é a opção recomendada para back-ends sem servidor do Google Cloud .

Entender a conversão de caminho

Como o gateway de API lida com solicitações, ele pega o caminho da solicitação original e o converte antes de fazer uma solicitação ao back-end de destino. Como isso acontece exatamente depende da estratégia de conversão de caminho sendo usada. Há duas estratégias de conversão:

  • APPEND_PATH_TO_ADDRESS: o caminho da solicitação de back-end de destino é calculado ao anexar o caminho da solicitação original ao URL do address da extensão x-google-backend.
  • CONSTANT_ADDRESS: o caminho da solicitação de destino é constante, como definido pelo URL do address da extensão x-google-backend. Se o caminho da OpenAPI correspondente tiver parâmetros, o nome e os valores deles se tornam os parâmetros da consulta.

Exemplos:

  • APPEND_PATH_TO_ADDRESS
    • address: https://my-project-id.appspot.com/BASE_PATH
    • Com parâmetros de caminho da OpenAPI
      • Caminho da OpenAPI: /hello/{name}
      • Caminho da solicitação: /hello/world
      • URL de solicitação de destino: https://my-project-id.appspot.com/BASE_PATH/hello/world
    • Sem parâmetros de caminho da OpenAPI
      • Caminho da OpenAPI: /hello
      • Caminho da solicitação: /hello
      • URL de solicitação de destino: https://my-project-id.appspot.com/BASE_PATH/hello
  • CONSTANT_ADDRESS
    • address: https://us-central1-my-project-id.cloudfunctions.net/helloGET
    • Com parâmetros de caminho da OpenAPI
      • Caminho da OpenAPI: /hello/{name}
      • Caminho da solicitação: /hello/world
      • URL de solicitação de destino: https://us-central1-my-project-id.cloudfunctions.net/helloGET?name=world
    • Sem parâmetros de caminho da OpenAPI
      • Caminho da OpenAPI: /hello
      • Caminho da solicitação: /hello
      • URL de solicitação de destino: https://us-central1-my-project-id.cloudfunctions.net/helloGET

x-google-endpoints

Nesta seção, você verá a descrição dos usos da extensão x-google-endpoints.

Configurar o API Gateway para permitir solicitações de CORS

Se a API for chamada de um aplicativo da Web de origem diferente, ela precisará oferecer suporte ao compartilhamento de recursos de origem cruzada (CORS, na sigla em inglês). Para informações sobre como configurar o API Gateway para ser compatível com o CORS, consulte Como adicionar suporte CORS ao API Gateway.

Se precisar implementar suporte CORS personalizado no código de back-end, defina allowCors: True para que o API Gateway transmita todas as solicitações de CORS ao código de back-end:

x-google-endpoints:
- name: "API_NAME.endpoints.PROJECT_ID.cloud.goog"
  allowCors: True

Adicione a extensão x-google-endpoints no nível superior do documento da OpenAPI sem recuo ou aninhamento. Por exemplo:

swagger: "2.0"
host: "my-cool-api.endpoints.my-project-id.cloud.goog"
x-google-endpoints:
- name: "my-cool-api.endpoints.my-project-id.cloud.goog"
  allowCors: True

x-google-issuer

x-google-issuer: URI | EMAIL_ADDRESS

Essa extensão é usada na seção securityDefinitions da OpenAPI para especificar o emissor de uma credencial. Os valores podem assumir a forma de um nome de host ou endereço de e-mail.

x-google-jwks_uri

x-google-jwks_uri: URI

O URI de chave pública do provedor definido para validar a assinatura do JSON Web Token.

O campo x-google-jwks_uri (OpenAPI 2.0) ou jwksUri (OpenAPI 3.x) é obrigatório. O gateway de API é compatível com dois formatos de chave pública assimétrica definidos por essa extensão OpenAPI:

  • formato de conjunto JWK. Exemplo:

    OpenAPI 2.0

    x-google-jwks_uri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
    

    OpenAPI 3.x

    jwksUri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
    
  • X509. Exemplo:

    OpenAPI 2.0

    x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
    

    OpenAPI 3.x

    jwksUri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
    

Se você estiver usando um formato de chave simétrica, defina x-google-jwks_uri (OpenAPI 2.0) ou jwksUri (OpenAPI 3.x) como o URI de um arquivo que contenha a string de chave codificada por base64url.

x-google-jwt-locations

Por padrão, um JWT é transmitido nos cabeçalhos Authorization (prefixado por "Bearer "), X-Goog-Iap-Jwt-Assertion ou no parâmetro de consulta access_token.

Também é possível usar a extensão x-google-jwt-locations na seção securityDefinitions da OpenAPI para fornecer os locais personalizados em que será extraído o token JWT.

A extensão x-google-jwt-locations aceita uma lista de locais do JWT. Cada local do JWT contém os seguintes campos:

Elemento Descrição
header/query Obrigatório. O nome do cabeçalho que contém o JWT ou o nome do parâmetro de consulta com o JWT.
value_prefix Opcional. Somente para cabeçalho. Quando o value_prefix é definido, o valor dele precisa corresponder ao prefixo do valor do cabeçalho que contém o JWT.

Exemplo:

x-google-jwt-locations:
  # Expect header "Authorization": "MyBearerToken <TOKEN>"
  - header: "Authorization"
    value_prefix: "MyBearerToken "
  # expect header "jwt-header-foo": "jwt-prefix-foo<TOKEN>"
  - header: "jwt-header-foo"
    value_prefix: "jwt-prefix-foo"
  # expect header "jwt-header-bar": "<TOKEN>"
  - header: "jwt-header-bar"
  # expect query parameter "jwt_query_bar=<TOKEN>"
  - query: "jwt_query_bar"

Se você quiser aceitar apenas um subconjunto dos locais padrão do JWT, liste-os explicitamente na extensão x-google-jwt-locations. Por exemplo, para incluir apenas para o cabeçalho Authorization com o prefixo "Bearer ", use este comando:

  x-google-jwt-locations:
    # Support the default header "Authorization": "Bearer <TOKEN>"
    - header: "Authorization"
      value_prefix: "Bearer "

x-google-audiences

x-google-audiences: STRING

Essa extensão é usada na seção securityDefinitions da OpenAPI para fornecer uma lista de públicos que o campo aud do JWT precisa corresponder durante a autenticação do JWT. A extensão aceita uma única string com valores separados por vírgula. Não são permitidos espaços entre os públicos. Quando não especificado, o campo aud do JWT precisa corresponder ao campo host no documento da OpenAPI.

securityDefinitions:
  google_id_token:
    type: oauth2
    authorizationUrl: ""
    flow: implicit
    x-google-issuer: "https://accounts.google.com"
    x-google-jwks_uri: "https://www.googleapis.com/oauth2/v1/certs"
    x-google-audiences: "848149964201.apps.googleusercontent.com,841077041629.apps.googleusercontent.com"

x-google-management

A extensão x-google-management controla diferentes aspectos do gerenciamento da API e contém os campos descritos nesta seção.

metrics

Use metrics em conjunto com a cota e x-google-quota para configurar uma cota para a API. Com ela, é possível controlar a taxa que os aplicativos podem chamar os métodos na API. Por exemplo:

x-google-management:
  metrics:
    - name: read-requests
      displayName: Read requests
      valueType: INT64
      metricKind: DELTA

O campo metrics contém uma lista com os pares de chave-valor a seguir:

Elemento Descrição
name Obrigatório. O nome dessa métrica. Normalmente, é o tipo de solicitação, como "solicitações de leitura" ou "solicitações de gravação", que identifica exclusivamente a cota.
displayName

Opcional, mas recomendado. O texto exibido para identificar a métrica na guia Cotas da página Endpoints > Serviços noGoogle Cloud console. Esse texto também é exibido para os consumidores da API nas páginas Cotas em IAM e administrador e APIs e serviços. O nome de exibição precisa ter no máximo 40 caracteres.

Para fins de legibilidade, a unidade do limite de cotas associadas é automaticamente anexada ao nome de exibição no console doGoogle Cloud . Por exemplo, se você especificar "Solicitações de leitura" no nome de exibição, as "Solicitações de leitura por minuto por projeto" serão exibidas no console doGoogle Cloud . Se não for especificado, o texto "cota sem rótulo" será exibido aos consumidores da API nas páginas Cotas em IAM e administrador e APIs e serviços.

Para manter a consistência dos nomes de exibição dos serviços do Google listados na página Cotas, vistos pelos consumidores da API, observe o seguinte:

  • Use "Solicitações" quando tiver apenas uma métrica.
  • Se tiver várias métricas, cada uma precisa descrever o tipo de solicitação e conter a palavra "solicitações". Por exemplo, "Solicitações de leitura" ou "Solicitações de gravação".
  • Use "unidades de cota" em vez de "solicitações" quando qualquer um dos custos associados a essa métrica for maior que 1.
valueType Obrigatório. Precisa ser INT64
metricKind Obrigatório. Precisa ser DELTA

quota

Especifique o limite de cota para uma métrica definida na seção quota. Por exemplo:

quota:
  limits:
    - name: read-requests-limit
      metric: read-requests
      unit: 1/min/{project}
      values:
        STANDARD: 5000

O campo quota.limits contém uma lista com os pares de chave-valor a seguir:

Elemento Descrição
name Obrigatório. Nome do limite que precisa ser exclusivo no serviço. O nome pode conter letras maiúsculas e minúsculas, números e "-" (o caractere "traço") e não pode ter mais de 64 caracteres.
metric Obrigatório. O nome da métrica a que este limite se aplica. O nome precisa corresponder ao texto especificado no nome de uma métrica. Se o texto especificado não corresponder a um nome de métrica, você receberá um erro ao implantar o documento do OpenAPI.
unit Obrigatório. A unidade do limite. Atualmente, apenas "1/min/{project}" é aceito, o que significa que o limite é aplicado por projeto e o uso é reiniciado a cada minuto.
values Obrigatório. O limite para a métrica. É preciso especificar esse valor como um par de chave-valor no seguinte formato:
STANDARD: YOUR-LIMIT-FOR-THE-METRIC
Substitua YOUR-LIMIT-FOR-THE-METRIC por um valor inteiro que seja o número máximo de solicitações permitidas para a unidade especificada (atualmente, apenas por minuto e por projeto). Por exemplo:
values:
  STANDARD: 5000

x-google-quota

A extensão x-google-quota é usada na seção paths da OpenAPI para associar um método na API a uma métrica. Não são aplicados limites de cota aos métodos sem x-google-quota definida. Por exemplo:

x-google-quota:
  metricCosts:
    read-requests: 1

A extensão x-google-quota contém o item a seguir:

Elemento Descrição
metricCosts Um par de chave-valor definido pelo usuário: "YOUR-METRIC-NAME": METRIC-COST.
  • "YOUR-METRIC-NAME": o texto de "YOUR-METRIC-NAME" precisa corresponder a um nome de métrica definido.
  • METRIC-COST: um valor inteiro que define o custo de cada solicitação. Ao fazer uma solicitação, a métrica associada é incrementada pelo custo especificado. Com esse custo, os métodos podem consumir taxas diferentes da mesma métrica. Por exemplo, se a métrica tiver um limite de cota de 1.000 e um custo de 1, o aplicativo de chamada poderá fazer 1.000 solicitações por minuto antes de exceder o limite. Com um custo de 2 para a mesma métrica, o aplicativo de chamada poderá fazer apenas 500 pedidos por minuto antes de exceder o limite.

Exemplos de cota

No exemplo a seguir, veja como adicionar uma métrica e um limite de solicitações de leitura e gravação.

x-google-management:
  metrics:
    # Define a metric for read requests.
    - name: "read-requests"
      displayName: "Read requests"
      valueType: INT64
      metricKind: DELTA
    # Define a metric for write requests.
    - name: "write-requests"
      displayName: "Write requests"
      valueType: INT64
      metricKind: DELTA
  quota:
    limits:
      # Rate limit for read requests.
      - name: "read-requests-limit"
        metric: "read-requests"
        unit: "1/min/{project}"
        values:
          STANDARD: 5000
      # Rate limit for write requests.
      - name: "write-request-limit"
        metric: "write-requests"
        unit: "1/min/{project}"
        values:
          STANDARD: 5000

paths:
  "/echo":
    post:
      description: "Echo back a given message."
      operationId: "echo"
      produces:
      - "application/json"
      responses:
        200:
          description: "Echo"
          schema:
            $ref: "#/definitions/echoMessage"
      parameters:
      - description: "Message to echo"
        in: body
        name: message
        required: true
        schema:
          $ref: "#/definitions/echoMessage"
      x-google-quota:
        metricCosts:
          read-requests: 1
      security:
      - api_key: []

x-google-api-name

Quando o serviço contém apenas uma API, o nome dela é o mesmo que o do serviço do API Gateway. O gateway de API usa o nome especificado no campo host do documento da OpenAPI como o nome do serviço. Quando o serviço contém mais de uma API, especifique os nomes da API adicionando a extensão x-google-api-name ao documento da OpenAPI. A extensão x-google-api-name permite nomear explicitamente APIs individuais e estabelecer o controle de versões independente de cada uma.

Por exemplo, é possível configurar um serviço chamado api.example.com com duas APIs, producer e consumer, com os fragmentos de documento da OpenAPI mostrados aqui:

  • API Producer em producer.yaml:

    swagger: 2.0
    host: api.example.com
    x-google-api-name: producer
    info:
      version: 1.0.3
    

  • API Consumer em consumer.yaml:

    swagger: 2.0
    host: api.example.com
    x-google-api-name: consumer
    info:
      version: 1.1.0
    

É possível implantar os dois documentos da OpenAPI com:

gcloud api-gateway api-configs create API_CONFIG_ID \
  --api=my-api \
  --openapi-spec="producer.yaml,consumer.yaml" \
  --project=my-project-id