Saiba como invocar funções do Cloud autenticadas

1. Introdução

Visão geral

O Cloud Functions é uma solução de computação leve para desenvolvedores. Ele cria funções autônomas e de finalidade única que podem ser acionadas usando HTTPS ou responder a CloudEvents sem a necessidade de gerenciar um servidor ou um ambiente de execução.

Há duas abordagens principais para controlar as invocações do Cloud Functions: proteger o acesso com base na identidade e proteger o acesso usando controles de acesso baseados em rede. Este codelab se concentra na primeira abordagem e orienta você em três cenários para proteger o acesso com base na identidade e invocar uma função:

  1. Use seu token de identidade da gcloud para invocar uma função para desenvolvimento local e fins de teste
  2. Representar uma conta de serviço ao desenvolver e testar localmente para usar as mesmas credenciais da produção
  3. Use bibliotecas de cliente do Google para lidar com a autenticação nas APIs do Google Cloud. Por exemplo: quando um serviço precisa invocar uma função

O que você vai aprender

  • Como configurar a autenticação em uma função do Cloud e verificar se ela foi configurada corretamente
  • Invocar uma função autenticada de um ambiente de desenvolvimento local fornecendo o token para sua identidade do gcloud
  • Como criar uma conta de serviço e conceder a ela o papel apropriado para invocar uma função
  • Como representar um serviço de um ambiente de desenvolvimento local que tenha os papéis apropriados para invocar uma função

2. Configuração e requisitos

Pré-requisitos

  • Você fez login no console do Cloud.
  • Você já implantou uma função do Cloud de 2a geração acionada por HTTP
  • (Opcional) No terceiro cenário, este codelab usa Node.js e NPM como exemplo, mas você pode usar qualquer ambiente de execução compatível com as bibliotecas de cliente do Google Auth.

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shell853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.

9c92662c6a846a5c.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

9f0e51b578fecce5.png

Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.

Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Criar e testar uma função autenticada do Cloud

Este codelab segue as mesmas instruções do Guia de início rápido do Console para Cloud Functions, com uma exceção importante: sua função exigirá autenticação.

Exigir autenticação significa que o princípio que invoca a função precisa ter os papéis Invocador do Cloud Functions (e Invocador do Cloud Run para 2a geração). Caso contrário, a função retornará um erro 403 Forbidden. Este codelab mostra como conceder os papéis do invocador apropriados a um princípio.

Criar a função autenticada

Siga estas etapas para usar o Console do Cloud:

  1. Acesse a página Visão geral do Cloud Functions e clique em Criar função.
  2. Na opção Ambiente, selecione 2a geração.
  3. Nomeie a função como my-authenticated-function.
  4. No campo "Autenticação", deixe o padrão como Autenticação necessária.

936eee0d5930d12b.png

  1. Clique em Próximo.
  2. Neste codelab, você pode escolher qualquer linguagem
  3. Depois clique em Implantar.

Leva aproximadamente 1 minuto para implantar a função.

Configure variáveis de ambiente locais para comandos simplificados da gcloud

Primeiro, você vai criar algumas variáveis de ambiente para melhorar a legibilidade dos comandos gcloud usados neste codelab.

Você vai querer especificar a região para sua função. Este exemplo usa us-central1.

REGION="us-central1"

e salvar o URL da função como uma variável de ambiente para usar depois.

PROJECT_ID=$(gcloud config get-value project)
FUNCTION_URL="$(gcloud functions describe my-authenticated-function --gen2 --region us-central1 --format='get(serviceConfig.uri)')"

Verifique se a função exige autenticação tentando invocar como autor da chamada anônimo

Você vai invocar a função sem autenticação para verificar se recebeu um erro 403 esperado.

Em uma linha de comando, execute o seguinte comando curl:

curl $FUNCTION_URL

O seguinte resultado será exibido:

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Your client does not have permission to get URL <code>/</code> from this server.</h2>
<h2></h2>
</body></html>

Agora está tudo pronto para você conhecer três cenários em que é possível invocar a função fornecendo autenticação.

4. Cenário 1: usar o token de identidade da gcloud

Como desenvolvedor, você vai querer uma maneira de testar sua função enquanto a desenvolve localmente. Nesta seção, você vai fazer um teste rápido para verificar se a função está autenticada corretamente usando sua própria identidade.

Execute o comando a seguir para verificar se você está autenticado usando gcloud:

gcloud auth list

Você verá um asterisco ao lado da sua identidade ativa, por exemplo:

Credentialed Accounts
ACTIVE  ACCOUNT

*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

Depois de confirmar que está usando a identidade correta, salve o e-mail da conta em uma variável de ambiente.

ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

Você encontra mais informações sobre como configurar o gcloud init e o gcloud auth login na documentação.

Em seguida, invoque a função e transmita o token de identidade a ela.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"

Agora você verá o resultado:

Hello World!

Solução de problemas

Se você receber um erro 403 Forbidden, verifique se sua identidade tem o papel Invocador do Cloud Functions ou o Papel Invocador do Cloud Run para funções de 2a geração. Use o Console do IAM para verificar os papéis atribuídos a um principal.

Embora usar seu próprio token de identidade seja uma maneira rápida de testar sua função durante o desenvolvimento, o autor da chamada da sua função autenticada precisará dos papéis apropriados. caso contrário, o autor da chamada receberá um erro 403 Forbidden.

Siga o princípio de privilégio mínimo limitando o número de identidades e contas de serviço com papéis para invocar a função.

criar uma nova conta de serviço e conceder a ela os papéis necessários.

5. Cenário 2: representar uma conta de serviço

Neste cenário, você vai representar (ou seja, assumir as permissões de) uma conta de serviço para invocar uma função ao desenvolver e testar localmente. Ao representar uma conta de serviço, você pode testar sua função com as mesmas credenciais que na produção.

Ao fazer isso, você não apenas vai verificar os papéis, mas também seguir o princípio de privilégio mínimo, porque não precisa conceder o papel Invocador de Função do Cloud a outras identidades apenas para testes locais.

Para os fins deste codelab, você criará uma nova conta de serviço com apenas papéis para invocar a função criada.

Criar uma nova conta de serviço

Primeiro, você criará mais algumas variáveis de ambiente para representar as contas de serviço usadas nos comandos gcloud.

SERVICE_ACCOUNT_NAME="invoke-functions-codelab"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com

Em seguida, crie a conta de serviço.

gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
  --display-name="Cloud Function Authentication codelab"

E conceder o papel de invocador da função do Cloud à conta de serviço

gcloud functions add-iam-policy-binding my-authenticated-function \
  --region=us-central1 --gen2 \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/cloudfunctions.invoker'

Invoque a função representando a conta de serviço

Para isso, você vai personificar a conta de serviço recém-criada obtendo o token de ID dela.

Adicionar papéis necessários para representação

Para representar uma conta de serviço, sua conta de usuário precisa ter o papel Criador de token da conta de serviço (roles/iam.serviceAccountTokenCreator) para gerar um token de ID para a conta de serviço.

gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS  \
  --member user:$ACCOUNT_EMAIL \
  --role='roles/iam.serviceAccountTokenCreator'

Usar o token de ID da conta de serviço

Agora você pode invocar a função transmitindo o token de ID da conta de serviço.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)" 

O seguinte será exibido:

WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com].
Hello World!

6. Cenário 3: usar bibliotecas de cliente do Google

Nesta última parte do codelab, você executará um pequeno serviço localmente para gerar um token de ID para uma conta de serviço e, em seguida, chamará a função programaticamente usando as bibliotecas de cliente do Google Auth e o Application Default Credentials (ADC). Saiba mais sobre as bibliotecas de cliente do Google na seção explicada sobre bibliotecas de clientes da documentação.

O uso do ADC é importante principalmente quando você quer escrever e testar sua função localmente (por exemplo, no seu laptop, no Cloud Shell etc.) enquanto interage com outros recursos do Google Cloud (por exemplo, Cloud Storage, API Vision etc.). Neste exemplo, você vai aprender a fazer com que um serviço invoque outra função que exija autenticação. Para mais informações sobre o ADC e o desenvolvimento local, consulte a postagem do blog Como desenvolver e testar o Cloud Functions localmente | Blog do Google Cloud

Execute o comando gcloud para representar uma conta de serviço

O ADC encontra credenciais automaticamente com base no ambiente do aplicativo e as usa para se autenticar nas APIs do Google Cloud. A flag –impersonate-service-account permite representar uma conta de serviço usando a identidade dela para autenticação nas APIs do Google Cloud.

Para representar uma conta de serviço, execute o seguinte comando:

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

Agora você está executando comandos gcloud como essa conta de serviço, em vez da sua identidade.

Criar e executar um serviço para invocar uma função autenticada

Cada ambiente de execução tem a própria biblioteca de cliente do Google Auth que você pode instalar. Este codelab ajuda você a criar e executar um app Node.js localmente.

Siga estas etapas para Node.js:

  1. Criar um novo app Node.js
npm init
  1. Instalar a biblioteca de cliente do Google Auth
npm install google-auth-library
  1. Criar um arquivo index.js
  2. Recupere o URL da função do Cloud, que você vai adicionar ao código na etapa a seguir.
echo $FUNCTION_URL
  1. Adicione o código a seguir ao index.js. Altere a variável targetAudience para o URL da função do Cloud.

index.js

// Cloud Functions uses your function's url as the `targetAudience` value

const targetAudience = '<YOUR-CLOUD-FUNCTION-URL>';

// For Cloud Functions, endpoint(`url`) and `targetAudience` should be equal

const url = targetAudience;

const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
    console.info(`request ${url} with target audience ${targetAudience}`);

    // this call retrieves the ID token for the impersonated service account
    const client = await auth.getIdTokenClient(targetAudience);

    const res = await client.request({ url });
    console.info(res.data);
}

request().catch(err => {
    console.error(err.message);
    process.exitCode = 1;
});
  1. Executar o app
node index.js

Aparecerá a mensagem "Hello World!"

Solução de problemas

Se a permissão "iam.serviceAccounts.getOpenIdToken" for exibida negado no recurso (ou pode não existir). Aguarde alguns minutos até que o papel de Criador de token da conta de serviço seja propagado.

Se você recebeu o erro "Não é possível buscar o token de ID neste ambiente", use o GCE ou defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como um arquivo JSON de credenciais da conta de serviço, talvez você tenha se esquecido de executar o comando

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

7. Parabéns!

Parabéns por concluir o codelab.

Recomendamos a análise da documentação sobre como proteger o Cloud Functions.

Também recomendamos esta postagem do blog sobre desenvolvimento local com o Cloud Functions para aprender a desenvolver e testar a função do Cloud no ambiente de desenvolvedor local.

O que vimos

  • Como configurar a autenticação em uma função do Cloud e verificar se ela foi configurada corretamente
  • Invocar uma função autenticada de um ambiente de desenvolvimento local fornecendo o token para sua identidade do gcloud
  • Como criar uma conta de serviço e conceder a ela o papel apropriado para invocar uma função
  • Como representar um serviço de um ambiente de desenvolvimento local que tenha os papéis apropriados para invocar uma função

8. Limpar

Para evitar cobranças acidentais (por exemplo, esta função do Cloud é invocada mais vezes do que sua alocação mensal de invocação de função do Cloud no nível sem custo financeiro), exclua a função do Cloud ou o projeto criado na etapa 2.

Para não representar mais a conta de serviço, você pode fazer login novamente usando sua identidade:

gcloud auth application-default login

Para excluir a função do Cloud, acesse o console do Cloud Functions em https://console.cloud.google.com/functions/. Verifique se o projeto que você criou na etapa 2 está selecionado.

Selecione a my-authenticated-function que você implantou anteriormente. Em seguida, clique em Excluir.

Se você optar por excluir o projeto inteiro, acesse https://console.cloud.google.com/cloud-resource-manager, selecione o projeto criado na etapa 2 e escolha "Excluir". Se você excluir o projeto, precisará alterar os projetos no SDK Cloud. Para conferir a lista de todos os projetos disponíveis, execute gcloud projects list.