Autenticação sem chaves com Workload Identity Federation

Joao Pedro Matias
gb.tech
Published in
8 min readSep 29, 2023
Photo by Towfiqu barbhuiya on Unsplash

Neste artigo discutiremos sobre o Workload Identity Federation com foco na identificação de cargas de trabalho externas no Google Cloud Platform.

Introdução

No desenvolvimento de sistemas é muito comum a necessidade de que dois ou mais serviços se comuniquem entre si. Por exemplo, um serviço precisa ler informações de algum banco de dados ou publicar mensagens em um sistema de mensageria. É fato que a computação em nuvem alavanca o desenvolvimento de tais serviços, principalmente no que diz respeito à praticidade e velocidade com que podemos hospedá-los nas infraestruturas de empresas como Amazon, Microsoft, Google, dentre outras que oferecem serviços de Cloud Computing. Com menos esforços sendo gastos no provisionamento de infraestrutura, a equipe de desenvolvimento tem mais tempo para aumentar o valor do produto, focando na implementação de novas funcionalidades ou na melhoria de funcionalidades existentes. Além disso, a equipe focada em infraestrutura pode direcionar seus esforços para a resolução de incidentes e aprimorar a escalabilidade do sistema, resultando em uma aplicação mais confiável e disponível.

As equipes de desenvolvimento de software podem aproveitar os melhores serviços dos diversos provedores de cloud para desenvolver seus produtos. Por exemplo, enquanto o serviço de CDN da Amazon possa ser o melhor em termos de custo / benefício, o serviço de Machine Learning do Google pode ser o mais robusto do mercado. Por que não desenvolver um produto integrando ambos? 🤔💡

Autenticação

Tudo parece ótimo até aqui, não é mesmo? Mas dentro desse contexto positivo surgem alguns desafios, sendo um deles a autenticação dessas cargas de trabalho dentro do contexto de um provedor de cloud externo. É necessário que esses serviços tenham mecanismos robustos e seguros de autenticação, de forma que estabeleçam uma relação de confiança entre si.

O método mais comum de autenticação de cargas de trabalho consiste na criação de service accounts (contas das quais a carga de trabalho assumirá a identidade e permissões) e no compartilhamento de suas chaves 🔑. As chaves da service account são enviadas nas requisições entre os serviços e a autenticação é efetuada.

A criação dessas chaves gera um risco de segurança, pois elas são sensíveis. Isso significa que se essas chaves forem expostas, qualquer pessoa poderá usar a identidade da service account que deveria pertencer apenas à determinada carga de trabalho ou usuário, recebendo assim todas as suas permissões.

Fazendo uma analogia, é como se as suas informações de login e senha de alguma rede social vazassem, possibilitando que qualquer pessoa se passasse por você naquela rede social. Nesse cenário, a rede social seria equivalente ao provedor de cloud, que deve permitir ou não o seu acesso à ela. Já o usuário em si é a carga de trabalho, que deve se identificar dentro daquele contexto digital para poder realizar ações como postar, comentar ou compartilhar posts.

Além do problema relacionado à segurança, essas chaves podem ter um tempo de expiração, exigindo com que a equipe de desenvolvimento realize manutenções periódicas dessas chaves, podendo levar à indisponibilidade do sistema em caso de falhas de manutenção.

O processo de autenticação portanto cria um desafio relacionado à gestão das chaves.

Workload Identity Federation: uma abordagem sem chaves sensíveis

Uma das alternativas recomendadas para mitigar esses problemas é a utilização de métodos mais modernos de autenticação, como o Workload Identity Federation.

Essa abordagem permite que uma carga de trabalho externa (hospedada em algum provedor de cloud ou em infraestrutura local) possa ser corretamente identificada sem envolver a troca de chaves sensíveis entre elas.

Para que esse modelo seja implementado, a carga de trabalho externa deve ter sua identidade definida por um serviço de IdP (Identity Provider). Serviços de IdP podem funcionar através da implementação do Open ID Connect (OIDC), que é uma camada adicional ao protocolo OAuth 2.0. O OIDC permite além da geração de Access Tokens (tokens que permitem acesso à recursos), a geração de ID Tokens, que fornecem informações sobre a identidade de um usuário ou de uma carga de trabalho.

Para deixar as ideias mais claras, vamos usar como exemplo o seguinte cenário:

Uma função executada no serviço AWS Lambda precisa consultar dados presentes no Google Big Query. Temos, assim, dois serviços hospedados em dois provedores de cloud distintos (Amazon e Google, respectivamente) que precisam estabelecer uma comunicação entre si. Neste contexto o AWS Security Token Service (AWS STS) atuará como IdP, fornecendo identidade à carga de trabalho do Lambda, e o Google Cloud Security Token Service (Google Cloud STS) será o responsável por avaliar tal identidade e permitir (ou restringir) o acesso do Lambda aos servidores do Big Query. Ao permitir o acesso, o Google STS envia à carga de trabalho do lambda um Access Token, que espelha temporariamente as permissões de uma service account.

Note que o acesso cedido pelo método de Workload Identity Federation é temporário, o que significa que mesmo que o Access Token gerado seja exposto, logo ele será obsoleto, mantendo assim a segurança do sistema.

A seguinte frase do Google consolida tudo isso:

"Workload Identity Federation enables applications to replace long-lived service account keys with short lived access tokens."

Passo a passo

A seguir, temos um passo a passo para realizar a autenticação do exemplo descrito acima.

  • Ativar as APIs "Identity and Access Management (IAM)", "Security Token Service API" e "IAM Service Account Credentials" no projeto do Google Cloud em questão, podendo ser realizado pelo painel do Google Cloud na aba "APIs e Serviços".
  • Criar uma service account. O objetivo da service account neste contexto é o espelhamento de suas permissões (em caráter temporário) à carga de trabalho externa. No exemplo em questão, a service account deve ter permissão para ler a tabela necessária no Big Query. O ideal é que sejam cedidas apenas as permissões de leitura na tabela, seguindo assim o Princípio do Privilégio Mínimo.
  • Criar uma Workload Identity Pool no painel de IAM do Google Cloud Platform.
  • Adicionar um Workload Identity Pool Provider à pool recém criada. A Identity Pool Provider deve ser configurada para que suas cargas de trabalho tenham origem na AWS. É necessário nomeá-la e fornecer a account ID da conta da AWS que hospedará as cargas de trabalhos a serem utilizadas por essa entidade.
Configuração do Workload Identity Pool Provider
  • Configurar o mapeamento de atributos, que são variáveis a serem armazenadas pelo Google com informações dinâmicas trazidas pelas cargas de trabalho da AWS, como account ID, ARN da identidade, nome do recurso, etc. O mapeamento de atributos para a AWS é pré-configurado (como mostrado a seguir) e assim será mantido.
Mapeamento de atributos
  • Configurar regras condicionais para determinar que apenas a carga de trabalho do lambda em questão será autenticada. Nesta etapa vamos usar como regra o ARN da carga de trabalho. Para obter tal valor, podemos rodar o seguinte snippet dentro da lambda function:
const { STSClient, GetCallerIdentityCommand } = require('@aws-sdk/client-sts')

exports.handler = async function () {
// ...

const stsClient = new STSClient({})
const command = new GetCallerIdentityCommand({})

// get identity information
const response = await stsClient.send(command)

// ...
}

Com as informações de identidade em mãos, podemos atribuir uma regra condicional que restringe a Workload Identity Federation a autenticar apenas a nossa lambda function. Fazemos isso através da inserção da regra que define que o atributo google.subject (que corresponde ao assertion.arn, como exibido na imagem acima) deva ser igual ao ARN da carga de trabalho. Como o ARN é único, a autenticação não funcionará para outras cargas de trabalho.

Regra condicional, onde os valores entre <> devem ser alterados para o seu contexto
  • Agora, é preciso permitir que a Workload Identity Pool receba as permissões da service account criada anteriormente. Esta etapa pode ser realizada no painel da Workload Identity Pool, selecionando a opção "Permitir Acesso". Temos a opção de inserir atributos condicionais usando a mesma lógica da etapa anterior, para que apenas algumas cargas de trabalho recebam as permissões daquela service account específica. É possível inserir diversas service accounts, onde cada uma delas terá o seu próprio arquivo JSON de credenciais.
Atrelamento de service account à Workload Identity Pool
  • Download do arquivo JSON, que é a credencial (não sensível 🙏) da service account dentro do contexto da Workload Identity Pool.
  • Finalmente estamos prontos para autenticar a carga de trabalho. Para isso, será usado o SDK do Google Big Query do NodeJs (a versão da biblioteca google-auth-library deve ser superior à 7.0.2). O método utilizado para que o SDK esteja devidamente autenticado será a configuração de uma variável de ambiente denominada GOOGLE_APPLICATION_CREDENTIALS, que deve receber o caminho para o arquivo de credencial recém obtido.
const { BigQuery } = require('@google-cloud/bigquery')
const path = require('path')

exports.handler = async function () {

// base variables
const projectId = '<project_id_here>'
const tableId = '<table_id_here>'

// authentication
const pathToCredentials = path.join(process.cwd(), 'gcp-credentials.json')
process.env.GOOGLE_APPLICATION_CREDENTIALS = pathToCredentials

// setup big query client
const bigQueryClient = new BigQuery({ projectId })

// query on Big Query
const response = await bigQueryClient.query({
useLegacySql: false,
query: `SELECT userId, SUM(score) AS points
FROM \`${tableId}\`
GROUP BY userId
ORDER BY points DESC`
})

return response
}
  • Pronto! Conseguimos autenticar uma carga de trabalho externa sem o uso de chaves sensíveis! 🎉

A cada requisição realizada com essas credencias, o Google Cloud STS checará os atributos da carga de trabalho e as condições de atributos definidas na Workload Identity Pool. Em caso de aprovação, o Google STS retorna um access token federado ao lambda, permitindo então que receba os acessos da service account de forma temporária e realize as operações necessárias no Big Query.

As credenciais geradas não são sensíveis, pois outras cargas de trabalho, ainda que hospedadas na AWS, não terão o mesmo ARN da carga de trabalho que federamos no passo a passo anterior. Portanto, elas não enviarão os atributos que foram permitidos na configuração da Workload Identity Federation, tendo assim sua autenticação rejeitada.

Mensagem de erro ao tentar acessar recursos com cargas de trabalho não federadas.

Detalhamos o processo de configuração para o uso de serviços do Google Cloud através do AWS Lambda Function, porém outros provedores de cloud também oferecem a possibilidade de uso dessa abordagem. As etapas de configuração, entretanto, são diferentes para cada provedor.

Conclusão

Com o uso de Workload Identity Federation, não precisamos nos preocupar com a gestão de chaves sensíveis. Isso traz dois ganhos principais que valem a pena serem destacados:

  • Aumento substancial na segurança do sistema.
  • Menos esforços gastos na gestão de chaves sensíveis, e portanto, mais tempo disponível para atuar em novas funcionalidades ou melhorias do produto.

Obrigado por chegar até aqui, espero que este conteúdo tenha sido útil para você de alguma forma!

Até a próxima 👋

--

--