No Cloud Endpoints, um conjunto de extensões específicas do Google é aceito para a especificação OpenAPI. Com elas, os comportamentos do Extensible Service Proxy (ESP), do Extensible Service Proxy V2 (ESPv2) e do Service Control são configurados. Esta página descreve extensões específicas do Google para a especificação OpenAPI.
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 ESP.
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 por meio do ESP.
Ao usar all
, as chamadas não configuradas, com ou sem uma chave de API ou autenticação de usuário, passarão pelo ESP para a API.
O processamento de chamadas para a API por parte do ESP diferencia maiúsculas de minúsculas.
Por exemplo, o ESP 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 comoall
;- o método
widgets
da API está listado na especificação OpenAPI, mas oWidgets
, não; - a especificação OpenAPI foi configurada para exigir uma chave de API.
Como widgets
está listado na especificação OpenAPI, o ESP 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 ESP 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 locais ou remotos. A extensão pode ser especificada no nível superior e/ou operacional de uma especificação OpenAPI.
Por padrão, o ESP é configurado para fazer o proxy de todo o tráfego para um único back-end local. O endereço de back-end local é especificado pela sinalização --backend
(o padrão é http://127.0.0.1:8081
). Use a extensão x-google-backend
para substituir esse comportamento padrão e especificar um ou mais back-ends locais ou remotos que possam receber solicitações.
A extensão x-google-backend
também pode definir outras configurações para back-ends locais e 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
Opcional. 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
.
Se uma operação usa x-google-backend
, mas não especifica address
, o ESPv2 encaminha as solicitações para o back-end local especificado pela sinalização --backend
.
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 ESPv2 adotará automaticamente o jwt_audience
como padrão para corresponder ao address
.
Se address
não estiver definido, o ESPv2 definirá automaticamente disable_auth
como true
.
jwt_audience
jwt_audience: string
Opcional. O público do JWT especificado quando o ESP obtém um token de ID da instância, que é usado ao fazer a solicitação de back-end de destino.
Ao configurar o Endpoints para sem servidor, o back-end remoto deve ser protegido para permitir somente o tráfego do ESPv2. O ESPv2 anexará 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 ESPv2. O back-end remoto pode verificar se a solicitação é do ESPv2 com base nesse token anexado.
Por exemplo, um back-end remoto implantado no Cloud Run pode usar o IAM para:
- Para restringir invocações não autenticadas, revogue
roles/run.invoker
do principalallUsers
especial. - Permitir que apenas o ESPv2 invoque o back-end concedendo o papel
roles/run.invoker
à conta de serviço do ambiente de execução do ESPv2.
Por padrão, o ESPv2 criará 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 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 ESPv2 altera os cabeçalhos nas solicitações.
Se uma solicitação tiver o cabeçalho Authorization
já definido, o ESPv2:
- Copia o valor original para um novo cabeçalho
X-Forwarded-Authorization
. - 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 ESPv2 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 ESPv2 não executará a verificação quando os métodos de autenticação não estiverem configurados.
disable_auth
disable_auth: bool
Opcional. Essa propriedade determina se o ESPv2 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 ESPv2 se uma destas condições for aplicável:
- O back-end permite invocações não autenticadas.
- O back-end requer o cabeçalho
Authorization
original do cliente da API e não pode usarX-Forwarded-Authorization
(descrito na seçãojwt_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 ESPv2 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 Como 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
continuará não especificado e não 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 ESPv2 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, 3600.0
por uma hora.
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.
Como ativar o suporte de back-ends no ESP
O ESPv2 detectará automaticamente quando x-google-backend
está configurado.
O ESP requer uma alteração de configuração manual para ativar esse recurso.
Ative o suporte x-google-backend
no ESP fornecendo o argumento --enable_backend_routing
ao executar o contêiner do ESP.
Para os ambientes de execução em que você não controla as opções de contêiner do ESP, essa opção já foi fornecida. Veja a seguir um exemplo de como ativar o suporte x-google-backend
ao implantar o contêiner do ESP no GKE. Ele foi criado com base no exemplo do Tutorial do Endpoints no GKE:
- name: esp image: gcr.io/endpoints-release/endpoints-runtime:1 args: [ "--http_port", "8081", "--service", "SERVICE_NAME", "--rollout_strategy", "managed", "--enable_backend_routing" ]
Noções básicas sobre a conversão de caminho
Como o ESP lida com solicitações, ele pegará o caminho da solicitação original e o converterá 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 doaddress
da extensãox-google-backend
.CONSTANT_ADDRESS
: o caminho da solicitação de destino é constante, como definido pelo URL doaddress
da extensãox-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
- Caminho da OpenAPI:
- 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
- Caminho da OpenAPI:
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
- Caminho da OpenAPI:
- 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
- Caminho da OpenAPI:
x-google-endpoints
Nesta seção, você verá a descrição dos usos da extensão x-google-endpoints
.
Como configurar o DNS no domínio cloud.goog
Caso tenha implantado o aplicativo no Compute Engine ou no Google Kubernetes Engine, será possível criar uma entrada DNS para o serviço do Endpoints no domínio cloud.goog
. Para isso, basta adicionar o seguinte ao documento da OpenAPI:
x-google-endpoints: - name: "API_NAME.endpoints.PROJECT_ID.cloud.goog" target: "IP_ADDRESS"
Adicione a extensão x-google-endpoints
no nível superior do documento da OpenAPI (sem recuo ou aninhamento). É preciso configurar o nome de domínio no formato: .endpoints.PROJECT_ID.cloud.goog
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" target: "192.0.2.1"
O domínio .cloud.goog
é gerenciado pelo Google e compartilhado pelos clientes do Google Cloud. Como os IDs do projeto do Google Cloud são únicos, um nome de domínio no formato .endpoints.PROJECT_ID.cloud.goog
é exclusivo para a API.
Para simplificar, configure os campos host
e x-google-endpoints.name
para que sejam iguais. Ao implantar o documento da OpenAPI, o Service Management cria:
- um serviço gerenciado com o nome especificado no campo
host
; - um registro A DNS que usa o nome e o endereço IP configurado na extensão
x-google-endpoints
.
Para APIs hospedadas no ambiente flexível do App Engine, use o domínio appspot.com
. Para mais informações, consulte Como configurar o Endpoints.
Como configurar o ESP 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 ESP para ser compatível com o CORS, consulte Como adicionar suporte CORS ao ESP.
Se precisar implementar suporte CORS personalizado no código de back-end, defina allowCors: True
para que o ESP 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 ESP suporta dois formatos de chave pública assimétrica definidos pela extensão x-google-jwks_uri
OpenAPI:
-
formato de conjunto JWK.
Exemplo:
x-google-jwks_uri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
-
X509. Exemplo:
x-google-jwks_uri: "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
como o URI de um arquivo que contenha a string de chave codificada por base64url.
Se você omitir x-google-jwks_uri
, o ESP seguirá o protocolo Descoberta do OpenID Connect para descobrir automaticamente o URI JWKS para o provedor OpenID fornecido.
O ESP fará uma solicitação para x-google-issuer/.well-known/openid-configuration
, analisará a resposta JSON e lerá o URI JWKS do campo de nível superior jwks_uri
.
Observe que a omissão de x-google-jwks_uri
resultará em tempos de inicialização a frio mais altos, já que o ESP precisará fazer uma chamada remota extra na inicialização.
Portanto, é recomendável omitir esse campo apenas se o URI de JWKS for alterado com frequência.
A maioria dos provedores OpenID certificados, como Google, Auth0 e Okta, tem URIs JWKS estáveis.
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
. Consulte Como fazer uma chamada autenticada à uma API do Endpoints para ver exemplos sobre como transmitir um JWT.
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.
Essa 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 for especificado, o campo aud
do JWT
precisa corresponder ao campo host
no documento da OpenAPI, a menos que a flag
--disable_jwt_audience_service_name_check
seja usada. Se a flag for usada e
x-google-audiences
não for especificado, o campo aud
do JWT não será verificado.
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 no Console do Google Cloud. Também é exibido aos 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 cota associado é automaticamente anexada ao nome de exibição no Console do Google 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 do Google 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:
|
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 YOUR-LIMIT-FOR-THE-METRIC por um valor inteiro, que é 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 .
|
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 Endpoints. Ele 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. Com a extensão x-google-api-name
, é possível 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 abaixo:
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 endpoints services deploy producer.yaml consumer.yaml