Como usar assinaturas de push

O Cloud Pub/Sub é compatível com a entrega de mensagens por push e pull. Para ter uma visão geral e comparar assinaturas de pull e push, consulte esta página. Neste documento, você verá uma descrição da entrega por push. Acesse o guia do assinante de pull para saber mais sobre a entrega por pull.

Uma assinatura do Cloud Pub/Sub pode ser configurada para enviar todas as mensagens como solicitações HTTP POST para um webhook, um endpoint de push ou um URL. Em geral, o endpoint de push precisa ser um servidor HTTPS de acesso público, com um certificado SSL válido, assinado por uma autoridade de certificação e roteável por DNS. Também é necessário validar sua propriedade ou nível de acesso equivalente ao domínio do endpoint de push ou a um caminho de URL.

Além disso, as assinaturas de push podem ser configuradas para fornecer um cabeçalho de autenticação e permitir que os endpoints autorizem as solicitações. Mecanismos alternativos e mais simples de autenticação e autorização estão disponíveis para os endpoints do ambiente padrão do App Engine e do Cloud Functions hospedados no mesmo projeto da assinatura.

Como receber mensagens por push

Uma solicitação por push do Cloud Pub/Sub é semelhante ao exemplo abaixo. O campo message.data é codificado em base64.

    POST https://www.example.com/my-push-endpoint 

   {
     "message": {
       "attributes": {
         "key": "value"
       },
       "data": "SGVsbG8gQ2xvdWQgUHViL1N1YiEgSGVyZSBpcyBteSBtZXNzYWdlIQ==",
       "messageId": "136969346945"
     },
     "subscription": "projects/myproject/subscriptions/mysubscription"
   }
O endpoint de push gerencia as mensagens recebidas e envia um código de status HTTP para indicar sucesso ou falha. A resposta success indica que a mensagem foi confirmada. Os códigos de status de confirmação de mensagens pelo sistema Cloud Pub/Sub são: 200, 201, 202, 204 ou 102. Uma possível resposta de sucesso seria:

204 No Content

Se o webhook não retornar um código de sucesso, o Cloud Pub/Sub tentará fazer a entrega até que a mensagem expire, após o período de armazenamento de mensagem da assinatura. É possível configurar um prazo de confirmação padrão para assinaturas de push. Porém, ao contrário das assinaturas de pull, o prazo não pode ser estendido para mensagens individuais. Ele terá o tempo exato que o endpoint demora para responder à solicitação de push.

Autenticação e autorização

Como usar JSON Web Tokens (JWTs)

As assinaturas de push podem ser configuradas para associar uma identidade de conta de serviço às solicitações de push, permitindo que o endpoint de push as autentique. Quando a autenticação está habilitada em uma assinatura de push, as solicitações de push dessa assinatura incluem um JWT do OpenID Connect assinado no cabeçalho de autorização. O endpoint de push pode usar o token para confirmar que a solicitação foi emitida em nome da conta de serviço associada à assinatura e realizar a autorização ou não

O JWT do OpenIDConnect é um conjunto de três strings codificadas em base64 delimitadas por pontos. Elas são o cabeçalho, o conjunto de declarações e a assinatura. Veja um exemplo de cabeçalho de autorização:

"Authorization" : "Bearer
eyJhbGciOiJSUzI1NiIsImtpZCI6IjdkNjgwZDhjNzBkNDRlOTQ3MTMzY2JkNDk5ZWJjMWE2MWMzZDVh
YmMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tIiwiYXpwIjoiMTEzNzc0M
jY0NDYzMDM4MzIxOTY0IiwiZW1haWwiOiJnYWUtZ2NwQGFwcHNwb3QuZ3NlcnZpY2VhY2NvdW50LmNvb
SIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1NTAxODU5MzUsImlhdCI6MTU1MDE4MjMzNSwia
XNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTEzNzc0MjY0NDYzMDM4MzIxO
TY0In0.QVjyqpmadTyDZmlX2u3jWd1kJ68YkdwsRZDo-QxSPbxjug4ucLBwAs2QePrcgZ6hhkvdc4UHY
4YF3fz9g7XHULNVIzX5xh02qXEH8dK6PgGndIWcZQzjSYfgO-q-R2oo2hNM5HBBsQN4ARtGK_acG-NGG
WM3CQfahbEjZPAJe_B8M7HfIu_G5jOLZCw2EUcGo8BvEwGcLWB2WqEgRM0-xt5-UPzoa3-FpSPG7DHk7
z9zRUeq6eB__ldb-2o4RciJmjVwHgnYqn3VvlX9oVKEgXpNFhKuYA-mWh5o7BCwhujSMmFoBOh6mbIXF
cyf5UiVqKjpqEbqPGo_AvKvIQ9VTQ" 

O cabeçalho e o conjunto de declarações são strings JSON. Depois de decodificadas, elas assumem o seguinte formato:

{"alg":"RS256","kid":"7d680d8c70d44e947133cbd499ebc1a61c3d5abc","typ":"JWT"}

{
   "aud":"https://example.com",
   "azp":"113774264463038321964",
   "email":"gae-gcp@appspot.gserviceaccount.com",
   "sub":"113774264463038321964",
   "email_verified":true,
   "exp":1550185935,
   "iat":1550182335,
   "iss":"https://accounts.google.com"
  }

Os tokens têm uma vida útil de uma hora.

Como autenticar URLs do ambiente padrão do App Engine e do Cloud Functions

Um mecanismo alternativo e mais simples de proteção de URLs de push está disponível para webhooks que são aplicativos do ambiente padrão do App Engine ou do Cloud Functions no mesmo projeto da assinatura.

Nos aplicativos do App Engine, é possível usar o seguinte padrão para requisitar o login do administrador em solicitações de push direcionadas a URLs: /_ah/push-handlers/.*

Para isso, é necessário adicionar a opção login: admin ao app.yaml, como neste exemplo do Python 2, ou <security-constraint>, como neste exemplo do Java. A opção login: admin não funciona em aplicativos do Python 3. Será preciso implementar a lógica de autenticação ao código do seu aplicativo. Veja Noções básicas sobre controle de acesso para mais detalhes.

O mecanismo é semelhante para o Cloud Functions, mas não requer nenhum caminho específico.

Como configurar o Cloud Pub/Sub para autenticações por push

A configuração de autenticação para uma assinatura consiste em dois parâmetros:

  • Conta de serviço: a conta de serviço do GCP associada à assinatura de push
  • Público-alvo de token (opcional): uma única string, indiferente a maiúsculas, que pode ser usada pelo webhook para validar o público-alvo desse token.

Além de configurar esses campos, é importante conceder ao Cloud Pub/Sub as permissões necessárias para a criação de tokens para a conta de serviço. O Cloud Pub/Sub gera e mantém uma conta de serviço especial para seu projeto: service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com. Essa conta precisa do papel de criador de token da conta de serviço. Se você usar o Console do Cloud para configurar a assinatura para autenticação por push, o papel será concedido automaticamente. Caso contrário, será preciso conceder explicitamente o papel à conta.

O recurso será implementado gradualmente em projetos mais antigos. Portanto, a conta de serviço do Cloud Pub/Sub pode não aparecer para seu projeto logo após a implementação. Para projetos novos, ela estará disponível imediatamente. Entre em contato com cloud-pubsub@google.com caso precise instalar o recurso com urgência em um projeto específico.

LINHA DE COMANDO

# grant Cloud Pub/Sub the permission to create tokens
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
 --role='roles/iam.serviceAccountTokenCreator'

# configure the subscription push identity
gcloud beta pubsub subscriptions (create|update|modify-push-config) ${SUBSCRIPTION} \
 --topic=${TOPIC} \
 --push-endpoint=${PUSH_ENDPOINT_URI} \
 --push-auth-service-account=${SERVICE_ACCOUNT_EMAIL} \
 --push-auth-token-audience=${OPTIONAL_AUDIENCE_OVERRIDE}

console

  1. Acesse a página de tópicos do Cloud Pub/Sub.

    Acessar a página de tópicos

  2. Clique em um tópico.

  3. Crie ou atualize uma assinatura.

  4. Digite uma identidade e (opcionalmente) um público-alvo.

Autenticação e autorização pelo endpoint de push

Declarações

O JWT pode ser usado para validar que as declarações, incluindo as de email e aud, sejam assinadas pelo Google. Para mais informações sobre como as APIs do OAuth 2.0 do Google podem ser usadas para autenticação e autorização, consulte OpenID Connect.

Dois mecanismos tornam essas declarações significativas. Em primeiro lugar, o Cloud Pub/Sub exige que o usuário ou a conta de serviço usada para associar uma identidade de conta de serviço a uma assinatura de push tenha o papel usuário da conta de serviço para o projeto ou para a conta.

Em segundo lugar, o acesso aos certificados utilizados para assinar os tokens é rigidamente controlado. Para criar o token, o Cloud Pub/Sub precisa acessar um serviço interno do Google, utilizando uma identidade de conta de serviço de assinatura separada. É necessário que a conta de serviço de assinatura seja autorizada a criar tokens para a conta de serviço declarada ou para o projeto que contém a conta. Isso é feito com a permissão iam.serviceAccounts.getOpenIdToken ou um papel criador de token de conta de serviço.

Esse papel ou permissão pode ser concedido a qualquer conta. No entanto, é possível usar o serviço do Cloud IAM para garantir que a conta de assinatura do Cloud Pub/Sub seja a única com essa permissão. O Cloud Pub/Sub usa uma conta de serviço como esta:

service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com
  • {project_number}: o projeto do GCP que contém a assinatura.
  • gcp-sa-pubsub: o projeto do Google que contém a conta de serviço da assinatura.

Como validar tokens

O exemplo a seguir mostra como autenticar uma solicitação por push em um aplicativo do App Engine.

protocolo

Solicitação:

GET https://oauth2.googleapis.com/tokeninfo?id_token={BEARER_TOKEN}

Resposta:

200 OK
{
    "alg": "RS256",
    "aud": "example.com",
    "azp": "104176025330667568672",
    "email": "{SERVICE_ACCOUNT_NAME}@{YOUR_PROJECT_NAME}.iam.gserviceaccount.com",
    "email_verified": "true",
    "exp": "1555463097",
    "iat": "1555459497",
    "iss": "https://accounts.google.com",
    "kid": "3782d3f0bc89008d9d2c01730f765cfb19d3b70e",
    "sub": "104176025330667568672",
    "typ": "JWT"
}

Python

@app.route('/_ah/push-handlers/receive_messages', methods=['POST'])
def receive_messages_handler():
    # Verify that the request originates from the application.
    if (request.args.get('token', '') !=
            current_app.config['PUBSUB_VERIFICATION_TOKEN']):
        return 'Invalid request', 400

    # Verify that the push request originates from Cloud Pub/Sub.
    try:
        # Get the Cloud Pub/Sub-generated JWT in the "Authorization" header.
        bearer_token = request.headers.get('Authorization')
        token = bearer_token.split(' ')[1]
        TOKENS.append(token)

        # Verify and decode the JWT. `verify_oauth2_token` verifies
        # the JWT signature, the `aud` claim, and the `exp` claim.
        claim = id_token.verify_oauth2_token(token, requests.Request(),
                                             audience='example.com')
        # Must also verify the `iss` claim.
        if claim['iss'] not in [
            'accounts.google.com',
            'https://accounts.google.com'
        ]:
            raise ValueError('Wrong issuer.')
        CLAIMS.append(claim)
    except Exception as e:
        return 'Invalid token: {}\n'.format(e), 400

    envelope = json.loads(request.data.decode('utf-8'))
    payload = base64.b64decode(envelope['message']['data'])
    MESSAGES.append(payload)
    # Returning any 2xx status indicates successful receipt of the message.
    return 'OK', 200

Consulte o Guia do Google Sign-in for Websites e veja outros exemplos sobre como validar o JWT do portador. Para mais informações sobre os tokens do OpenID, acesse o Guia do OpenID Connect.

Cloud Run

O serviço Cloud Run autentica automaticamente as chamadas HTTP. O usuário precisa apenas garantir que os papéis necessários do IAM sejam concedidos à conta de chamada. É possível, por exemplo, conceder ou revogar a permissão para chamar um determinado endpoint do Cloud Run para uma conta.

Validação de propriedade de domínio

Para evitar tráfego indesejado, o Cloud Pub/Sub pede a verificação da propriedade do endpoint de push. As etapas a seguir são necessárias para todos os endpoints, exceto:

  • Cloud Functions
  • Cloud Run
  • Aplicativos do ambiente padrão do App Engine no mesmo projeto da assinatura

A. Verificar se você tem acesso administrativo ao domínio:

Faça o processo de verificação do site com o Search Console. Não esqueça de registrar a versão https:// do URL. Para mais detalhes, consulte a documentação de propriedade do site.

B. Conceder acesso ao projeto que contém a assinatura:

Para permitir que o projeto do GCP gere tráfego para o URL do domínio ou do endpoint, é preciso conceder acesso ao domínio ao projeto do GCP que contém a assinatura:

  1. Acesse a página Credenciais em APIs e Serviços no Console.
    Acessar a página "Credenciais" em APIs e Serviços no Console
  2. Selecione seu projeto, caso necessário.
  3. Selecione a guia Confirmação de domínio.
  4. Selecione Adicionar domínio.
  5. Digite o domínio e selecione Adicionar domínio.

O Console do GCP compara seu domínio com os que você verificou no Search Console. Se você tiver verificado o domínio corretamente, a página atualizada mostra uma nova lista de domínios permitidos.

Agora é possível usar qualquer um desses domínios para receber mensagens de push. Você só precisa configurá-los como endpoints ao criar uma assinatura do Cloud Pub/Sub. Consulte Como configurar assinaturas para mais detalhes.

Como interromper e retomar a entrega

Para interromper temporariamente o envio de solicitações do Cloud Pub/Sub para o endpoint de push, altere a assinatura para pull. Observe que pode levar vários minutos para que essa mudança entre em vigor.

Para retomar a entrega por push, defina o URL para um endpoint válido novamente. Caso queira interromper a entrega permanentemente, exclua a assinatura.

Cotas, limites e taxa de entrega

As assinaturas de push estão sujeitas a um conjunto de cotas e limites de recursos. Além disso, a taxa de entrega por push é ajustada automaticamente para maximizar a taxa de entrega sem sobrecarregar o endpoint de push. Isso é possível por meio de um algoritmo de início lento:

  • O sistema começa enviando uma única mensagem por vez.
  • A cada entrega bem-sucedida, o número de mensagens enviadas simultaneamente é dobrado.
  • A taxa de entrega de mensagens simultâneas continua a duplicar até que ocorra uma falha na entrega ou que o sistema atinja uma cota ou limite de recurso.
  • Para cada falha na entrega, o número de solicitações simultâneas para o endpoint cai pela metade, até que seja atingido o mínimo de uma solicitação por vez.

O algoritmo entende que há mensagens publicadas suficientes na fila para manter essa capacidade. Finalmente, a taxa de entrega de push é restrita pela taxa de publicação das mensagens.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Cloud Pub/Sub