Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Assuma uma Role da AWS no Google Cloud sem usar chaves IAM

By Avi KeinanSep 30, 20206 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Com frequência, preciso acessar recursos da AWS, como S3, SQS etc., a partir de uma aplicação rodando no Google Cloud. Usar as access e secret keys é, com razão, considerado má prática, então acabei criando o Janus — uma pequena ferramenta que ajuda você a assumir uma Role da AWS a partir de uma instância do Google Cloud Compute Engine com uma service account.

Por que Janus? Porque, na mitologia romana, Janus, um deus de duas faces, era o deus dos portões e portas. Achei uma boa analogia para este caso ;-)

Afinal, o que é o Janus, exatamente? É um pequeno trecho de código que você pode rodar na sua própria instância do Google Cloud Compute Engine e que permite assumir uma Role da AWS sem precisar usar as chaves do AWS IAM.

Por que usar o Janus?

Imagine que você precise baixar um arquivo privado de um bucket S3 a partir de uma instância ou contêiner rodando no Google Cloud. Para baixar o arquivo, você vai precisar se autenticar no AWS IAM.

Existem algumas opções de autenticação. A mais segura é vincular uma IAM role a uma instância, mas isso só é possível em instâncias EC2 (instâncias que rodam na infraestrutura da AWS).

Já quando você tem uma instância no Google Cloud, as opções são limitadas, e a maioria das pessoas acaba gerando chaves de acesso do AWS IAM (geralmente com permissões mais amplas do que o necessário) e deixando-as hardcoded.

Isso cria um risco de segurança considerável: o vazamento da sua chave. Uma vez vazada, qualquer pessoa que tenha acesso a ela pode entrar na sua conta AWS. O resultado pode ser desde vazamento de dados até prejuízo financeiro para a sua empresa. O cenário mais "inocente" que já vi foi de hackers subindo servidores de mineração de criptomoedas, ou criptografando os dados e backups da conta e exigindo um resgate para devolvê-los.

Então, como estabelecer uma conexão segura do GCP para recursos da AWS sem chaves hardcoded?

O Janus ajuda a contornar essas limitações ao permitir que você assuma uma role usando uma Google Web Identity em uma máquina do GCP Compute Engine, de forma muito parecida com o uso de uma IAM role no EC2. O Janus solicita à AWS uma chave temporária com validade de 1 hora.

Como implementar o Janus

Como exemplo, vou demonstrar como conceder acesso a um bucket S3 da AWS com permissões somente leitura, que usarei na minha instância do Google Compute mais adiante.

  1. Faça login no console do GCP e escolha IAM & Admin no menu de navegação à esquerda. Em seguida, clique em Service Accounts e depois em +CREATE SERVICE ACCOUNT.

2. Dê um nome à sua service account e adicione uma descrição detalhada (sempre uma boa prática). Depois, clique no botão CREATE.

3. Em seguida, clique na caixa Role e selecione Service Account → Service Account Token Creator.

Um caminho mais rápido é digitar Token na caixa de busca Type to filter.

4. Será exibida a página "Grant users access to this service account (optional)". Quando ela aparecer, clique em DONE.

5. Clique no nome da service account e copie o Unique ID.

6. Faça login na sua conta AWS e vá até IAM console Roles → Create role.

7. Como trusted entity, selecione Web identity Google em Identity provider e cole o Unique ID da service account do GCP na caixa Audience. Em seguida, clique no botão Next: Permissions.

8. Conceda a permissão para a role. Para esta demonstração, vamos usar AmazonS3ReadOnlyAccess. Clique no botão Next: Tags.

9. A etapa de tags é opcional e vamos pulá-la nesta demonstração. Clique no botão Next: Review.

10. Dê um nome e uma descrição detalhada à role e clique em Create role.

11. A role está pronta para uso. Clique e copie o Role ARN, que será usado em uma etapa posterior.

12. Volte para o Console do GCP e crie uma nova instância de VM no Compute Engine.

Role um pouco para baixo, até a seção Identity and API access, e substitua a Compute Engine default service account pela service account que criamos na etapa 5.

13. Agora que tanto a AWS quanto o GCP estão configurados e já podemos assumir uma Role da AWS a partir do GCP, falta uma ferramenta ou trecho de código para executar o procedimento com a web identity do Google. Foi essa a motivação para criar o Janus.

O Janus retorna credenciais temporárias da AWS para todos os AWS SDKs e o AWS CLI suportados.

Para implementar o Janus, basta executar os comandos a seguir como root:

$ apt install python3-pip awscli
$ pip3 install boto3 requests
$ wget https://raw.githubusercontent.com/doitintl/janus/master/janus.py -O /usr/local/bin/janus
$ chmod 555 /usr/local/bin/janus

Para executar o Janus com a IAM role desejada, você vai precisar informar o nome do AWS Role ARN que copiamos na etapa 10.

/usr/local/bin/janus arn:aws:iam::123456789012:role/s3-ro-from-gcp

14. Crie um novo profile no seu arquivo /.aws/credentials ( é um atalho para o diretório home do usuário). O SDK da AWS usa os profiles (conforme definidos nesse arquivo) para concluir a autenticação com a AWS.

Se o arquivo ainda não existir, crie-o:

$ mkdir ~/.aws
$ touch ~/.aws/credentials

Edite o arquivo credentials e adicione um profile (o nome padrão é default). Você pode ter vários profiles e, para esta demonstração, vamos criar um novo profile default:

credential_process = /usr/local/bin/janus arn:aws:iam::123456789012:role/s3-ro-from-gcp

15. Pronto!!! Você já pode começar a usar a AWS a partir da sua instância no GCP.

Como exemplo, vou copiar um arquivo chamado hello.txt do meu bucket S3 da AWS usando o AWS CLI:

Como funciona?

  • Sempre que o AWS SDK ou o AWS CLI precisa acessar a AWS, ele busca o profile default em:

/.aws/credentials no Mac, Linux e Unix. ( é um atalho para o diretório home)

ou

C:\Users\USERNAME\.aws\credentials no Windows.

  • Em seguida, ele executa o Janus com o nome da Role da AWS que queremos assumir.
  • O Janus pede um token JWT ao metadata server do Compute Engine e, então, assume uma role na AWS usando o nome da Role da AWS.
  • A AWS valida se o token JWT bate com as configurações da Role e retorna uma chave de acesso temporária:

  • Com essa chave de acesso temporária, já podemos acessar a AWS e chamar APIs em nome da Role da AWS.

Como rastrear qual instância está acessando minha conta AWS?

Para fins de rastreamento, o Janus assume a role com um nome de sessão personalizado. O nome da sessão será project-id.instance-name.

Se você tiver o AWS CloudTrail habilitado na sua conta, dá para filtrar todos os eventos AssumeRoleWithWebIdentity e rastrear cada chamada de API realizada.

O evento traz:

  1. O IP de origem da máquina do GCP.
  2. username — o unique id da Service Account do GCP.
  3. O "session name" da role da sessão — Project id e instance name.
  4. O nome da role assumida.

Com a Access Key, podemos buscar todas as ações executadas pela instância.