Como configurar a Autenticação entre Bitbucket e AWS com OpenID Connect (OIDC)

Como configurar a Autenticação entre Bitbucket e AWS com OpenID Connect (OIDC)

Este é um artigo completo e extenso, mostrarei um passo a passo de um exemplo prático. Se preferir você pode pular as informações iniciais e ir diretamente para a prática, embora recomendo a leitura completa para obter um melhor contexto e uma melhor compreensão.

Introdução

No cenário atual de desenvolvimento de software, a integração entre diferentes plataformas é crucial para promover eficiência e colaboração. Nesse contexto, o OpenID Connect (OIDC) emerge como um protocolo de autenticação poderoso e amplamente utilizado, desempenhando um papel fundamental na segurança e na interoperabilidade entre sistemas.

A automatização de todos os processos de test, build e deploy garante que os produtos que são desenvolvidos sejam produzidos mais rapidamente, com melhor qualidade e menos erros. Há várias ferramentas disponíveis para automatizar esses processos manuais. Mas quando você automatiza tudo, não se esqueça de uma coisa: Segurança!

Então você criou um app incrível e chegou a hora de fazer o deploy para AWS, você configura um pipeline de CI/CD para automatizar muitas coisas, nesse momento você percebe que precisa realizar a autenticação do seu pipeline com sua conta AWS e começa a se preocupar com a segurança em torno disso. Se você chegou até aqui procurando uma solução para essa sua preocupação e necessidade, eu também já a tive e compartilho como cobri esse tema e o que tem funcionado para mim.


O que é OpenID Connect (OIDC)

O OIDC é uma extensão do OAuth 2.0, focado na autenticação de identidades. Sua principal finalidade é permitir que aplicativos e serviços validem a identidade de usuários de maneira segura e eficiente. Ao fornecer uma camada adicional sobre o OAuth 2.0, o OIDC adiciona recursos específicos para autenticação, possibilitando a obtenção de informações sobre o usuário autenticado de maneira padronizada.

O funcionamento do OIDC baseia-se em um fluxo de comunicação seguro entre partes envolvidas, conhecidas como provedor de identidade (IdP) e cliente. No contexto do nosso artigo, o Bitbucket atuará como cliente, enquanto a AWS será configurada como o provedor de identidade.

O processo começa com o cliente (Bitbucket) solicitando a autenticação ao provedor de identidade (AWS). O provedor de identidade (AWS), por sua vez, autentica o usuário, retornando um token de identificação ao cliente (Bitbucket), que pode ser usado para acessar informações sobre o usuário autenticado.

Ao configurar o OpenID Connect (OIDC) entre o Bitbucket e a AWS, estaremos estabelecendo uma ponte segura para a autenticação de usuários, fortalecendo a segurança e simplificando a gestão de identidades em ambientes interconectados.

Nos próximos passos deste artigo, exploraremos detalhadamente como realizar essa configuração, garantindo uma integração eficiente e confiável entre essas duas poderosas plataformas.


Escopo do Tutorial

Antes de começarmos, vamos definir o escopo das ferramentas mencionadas neste artigo. Em primeiro lugar, devemos considerar:

O conceito do OpenID Connect (OIDC) é sempre o mesmo para diferentes ferramentas, mas ela pode ter configurações diferentes para ferramentas como GitLab, Azure Pipelines, GitHub, etc. Este artigo tem o escopo de explicar somente a configuração do OIDC entre o Bitbucket e AWS.
  • Bitbucket da Atlassian: uma potente solução Git que agiliza os fluxos de trabalho de implantação e reforça as medidas de segurança focadas em equipes de desenvolvimento profissionais. Porém, neste caso específico, estamos mais interessados ​​no Bitbucket Pipelines.

  • Bitbucket Pipelines: é uma solução de integração contínua e entrega contínua (CI/CD) fornecida pela plataforma Bitbucket. Ele permite que os desenvolvedores automatizem os processos de teste, build e deploy de seus códigos diretamente com o repositório Bitbucket. Com a integração Bitbucket CI/CD, você pode implantar perfeitamente sua infraestrutura e aplicativos na nuvem AWS.


Visão Geral e Vantagens

Se quisermos fazer o deploy de um aplicativo na AWS, ela nos permite criar credenciais de segurança (chaves de acesso programáticas) mais conhecidas como Access Key e Secret Access Key e passá-las para o pipeline de implantação por meio de variáveis ​​de ambiente, por exemplo:

Deploying to AWS Using Bitbucket Pipelines - Intelligent Pathways

Este tipo de processo de implantação é muito mais comum do que deveria, mas existem vários potenciais problemas nesta abordagem, destacando:

  • Quando há erros de script, há risco de vazamento das chaves de acesso no código

  • Quando as chaves de acesso mudam ou precisam ser alternados, você deve atualizá-los manualmente no Bitbucket

  • Você deve garantir que eles não foram expostos acidentalmente

  • Você deve mantê-los com segurança

  • Pode ser um problema de conformidade em setores altamente regulamentados

Nesses casos, o OpenID Connect (OIDC) vem em nossa ajuda. Embora a maioria dos desenvolvedores que enfrentam a necessidade de implantar na AWS com Bitbucket usem a chave de acesso secreta, o OIDC pode nos ajudar a evitar o uso de chaves e simplificar significativamente implantações futuras.

Além disso, existem vários motivos pelos quais o uso do OIDC é melhor para os desenvolvedores em comparação ao uso de chaves de acesso:

  • Mais seguro: se suas chaves secretas vazarem, usuários não autorizados poderão usar suas chaves de acesso para obter acesso aos seus recursos da AWS. OpenID depende de seu Role ARN da AWS que, mesmo se vazado, não dá acesso aos seus recursos da AWS, as credenciais também são temporárias e expiram limitando o uso indesejado.

  • Mais fácil de gerenciar: para gerenciar o risco de segurança, quando os administradores de nuvem geram chaves secretas para os usuários, eles concedem permissões granulares com base nas necessidades do usuário. Isso significa ter que criar muitos pares de chaves de usuário. As permissões baseadas em funções no OpenID ainda se beneficiam de permissões granulares, mas são menos restritivas. Os administradores têm menos níveis de permissão para gerenciar.

  • Não são necessárias atualizações: quando você precisa alterar sua chave secreta ou quando a AWS desabilita uma chave devido à inatividade, você não precisa atualizar suas chaves em seus aplicativos ou no Bitbucket porque o OpenID não depende de chaves de acesso.


Pré-Requisitos

Para usar o OpenID Connect (OIDC) em Bitbucket Pipelines relacionados à AWS, você precisa configurar o Bitbucket Pipelines como um provedor de identidade da web (IdP) na AWS e criar uma função AWS Identity and Access Management (IAM).

Então como premissa você precisa ter uma conta do Bitbucket e outra da AWS, como nosso exemplo prático será um site estático com domínio personalizado, assumimos como premissa também que você já tenha seu domínio no Route 53 da AWS, pois não abordaremos essa configuração para não deixar o artigo mais extenso do que já é.


Tutorial

Cenário

Para demonstrar melhor todas as configurações, vamos criar um site estático no Bucket S3 com domínio personalizado, configurar o OIDC entre o repositório do Bitbucket e AWS e realizar um deploy automático alterando o número da versão da página deste site.


Etapa 1 - Criando o Bucket S3

1- Acesse o console AWS → S3 → Create Bucket

2-

  • Escolha a região

  • Selecione a opção General Purpose

  • Defina um nome (no nosso exemplo o nome é:

    tutorial-bitbucket-oidc-aws.simplescloud.io

O importante aqui é o nome do seu bucket S3 ser um domínio totalmente qualificado (FQDN), por exemplo se seu domínio é example.com - crie seu bucket como mytutorial.example.com ao invés de somente mytutorial
  • Desabilite o ACLs

  • Desabilite o bloqueio público

  • Desabilite o versionamento

  • Deixe todas as outras opções padrões

  • Clique em criar seu bucket S3


Etapa 2 - Fazendo Upload do index.html no Bucket S3

1- Em seu computador, abra seu editor de texto predileto e crie um arquivo chamado index.html, cole este conteúdo e salve o arquivo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tutorial OpenID Connect (OIDC)</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&display=swap">
    <style>
        body {
            font-family: 'Nunito', sans-serif;
            background: linear-gradient(45deg, #3498db, #2c3e50);
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            color: #fff;
        }

        h1, h2 {
            text-align: center;
            margin: 0;
            padding: 10px;
        }

        h1 {
            font-size: 2.5rem;
            margin-top: 20px;
        }

        h2 {
            font-size: 1.8rem;
            font-weight: 400;
        }
    </style>
</head>
<body>
    <h1>Tutorial OpenID Connect (OIDC)</h1>
    <h2>Between Bitbucket and AWS</h2>
    <h2>Version 1</h2>
</body>
</html>

2- Agora arraste para o bucket S3 ou clique no botão Upload, ao final você deve ver uma tela parecida com:


Etapa 3 - Habilitando o Site Estático no Bucket S3

1- No console AWSBucket S3 → acesse o bucket recém criado e navegue até a aba Properties → role a página para baixo até encontrar a opção Static Website Hosting → clique em Editar

2-

  • Clique em Enable

  • Escolha a opção Host a static website

  • Defina o nome do documento como index.html


Etapa 4 - Tornando o Site Público

1- Agora alterne para a aba Permissions → em Bucket Policy clique no botão Edit

2- Insira a política abaixo e salve

Lembre-se de alterar <your-bucket-name> pelo nome real do bucket S3 que você criou.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<your-bucket-name>/*"
        }
    ]
}


Etapa 5 - Criando o Registro DNS no Route 53

1- Acesse o console AWSRoute 53Hosted Zone → Crie um novo registro DNS:

  • Nome igual ao do bucket S3

  • Tipo A

  • Alias habilitado

  • Selecione o bucket S3


Etapa 6 - Verificando o Site Funcionando

1- Abra seu navegador → acesse o domínio personalizado que criou, em nosso exemplo isso é tutorial-bitbucket-oidc-aws.simplescloud.io, mas obviamente lembre-se de trocar para o valor real que você utilizou


Etapa 7 - Criando um Identity Provider (IdP) na AWS

1- Acesse sua conta Bitbucketconfigurações do repositórioOpenID Connect → copie e anote:

  • Identity Provider URL

  • Audience

  • Repository UUID

Que nós vamos precisar dessas informações mais para frente.

2- Agora acesse o console AWSIAMIdentity ProvidersCreate Identity Provider:

  • Selecione a opção OpenID Connect

  • No campo Provider URL cole o que você copiou do campo Identity Provider URL do Bitbucket

  • No campo Audience cole o que você copiou do campo Audience do Bitbucket

  • Clique no botão Get thumbprint

  • Por fim, clique no botão Add Provider


Etapa 8 - Criando Política de Acesso para o Bucket S3

1- Acesse o console AWSIAMPoliciesCreate Policy → cole o conteúdo

Lembre-se de alterar <your-bucket-name> para o nome real do bucket S3 que você criou.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::<your-bucket-name>",
                "arn:aws:s3:::<your-bucket-name>/*"
            ]
        }
    ]
}

2- Defina um nome e descrição de sua preferência, por exemplo:

  • Nome:s3-bucket-tutorial-bitbucket-oidc-aws.simplescloud.io-policy

  • Descrição:Policy with permissions required to access the bucket named tutorial-bitbucket-oidc-aws.simplescloud.io


Etapa 9 - Criando Política de Conexão

Repita os passos da Etapa 8, mas agora defina um outro nome e descrição de sua preferência, por exemplo:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "sts:GetCallerIdentity"
            ],
            "Resource": "*"
        }
    ]
}
  • Nome:oidc_bitbucket_policy

  • Descrição:Policy that allows OpenID Connect between Atlassian Bitbucket and AWS


Etapa 10 - Criando uma Role de Permissão

1- Acesse o console AWSIAMRoleCreate Role

  • Selecione a opção Web Identity

  • Selecione em Identity Provider a identidade de provedor que criamos anteriormente

  • Selecione em Audience a audiência de provedor que criamos anteriormente

2- Defina um nome e descrição de sua preferência, por exemplo:

  • Nome:deploy-tutorial-bitbucket-oidc-aws.simplescloud.io-role-prod

  • Descrição:Role with necessary permissions to deploy to the bucket called tutorial-bitbucket-oidc-aws.simplescloud.io in the production environment

  • Observe a estrutura da política de confiança, nós vamos altera-la em breve, por enquanto apenas clique em Next

3- Depois de criado → selecione a aba Trust RelationshipsEdit → e altere para a política abaixo:

Lembre-se de alterar <your-account-id> pelo número de ID real da sua conta AWS (você pode obter ela clicando no seu nome no menu superior direito), também lembre-se de alterar <your-bitbucket-workspace> pelo nome real do seu workspace do Bitbucket e por fim lembre-se de alterar <your-bitbucket-repo-uuid> pelo código que você copiou em uma das etapas anteriores.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<your-account-id>:oidc-provider/api.bitbucket.org/2.0/workspaces/<your-bitbucket-workspace>/pipelines-config/identity/oidc"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "api.bitbucket.org/2.0/workspaces/<your-bitbucket-workspace>/pipelines-config/identity/oidc:sub": "{<your-bitbucket-repo-uuid>}:*"
                }
            }
        }
    ]
}

É uma mudança sútil entre a política padrão para essa que editamos, em resumo as alterações são:

  • Mudamos de StringEquals para StringLike

  • Mudamos aud para sub

  • Adicionamos um wildcard (*) ao final do endpoint do repositório

Esse passo é muito importante, pois mudamos a política de relação de confiança limitando o acesso para apenas este repositório como uma boa prática de segurança. Em resumo o OIDC irá gerar tokens temporários e de qualquer forma ele poderá se conectar somente para este repositório tornando um nível maior de segurança.

4- Agora sua Role de Permissão deve estar devidamente criada e configurada, ela deve se parecer com isso, e não se esqueça de copiar o ARN, pois usaremos essa informação mais para frente


Etapa 11 - Configurando seu Computador

1- Em seu computador crie um pasta de sua preferência, por exemplo estou usando:

~/home/projects/bitbucket-openid-connect-aws

2- Crie novamente o arquivo index.html das etapas iniciais dentro dessa pasta

3- Agora crie um outro arquivo chamado bitbucket-pipelines.yml → cole este conteúdo:

Não se preocupe ainda se o arquivo abaixo se parecer confuso ou até mesmo se você não entendê-lo. O objetivo deste artigo não é explicar como criar um Pipeline em si, é apenas usar um Pipeline para demonstrar o uso do OIDC. Então novamente não se preocupe, a única coisa que você precisa olhar com atenção é a parte oidc: true que está habilitando o uso do OpenID Connect.
# Deploy to S3 Bucket

definitions:

  build_step: &build_step
    name: Build Artifact
    image: atlassian/default-image:4
    script:
      - mkdir artifact
      - cp index.html artifact/
    artifacts:
         - artifact/**

  deploy_step: &deploy_step
    name: Deploy to AWS S3
    oidc: true
    script:
      # Upload to S3 Bucket   
      - pipe: atlassian/aws-s3-deploy:1.6.0
        variables:
          AWS_OIDC_ROLE_ARN: $AWS_OIDC_ROLE_ARN
          AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
          S3_BUCKET: $S3_BUCKET
          LOCAL_PATH: "artifact"
          ACL: "bucket-owner-full-control"
          DELETE_FLAG: "true"

pipelines:

  branches:

    feature/*:
     - stage:
         name: Dev 
         deployment: dev
         steps:
          - step: *build_step
          - step: *deploy_step

    bugfix/*:
     - stage:
         name: Dev
         deployment: dev
         steps:
          - step: *build_step
          - step: *deploy_step

    release/*:
     - stage:
         name: Staging
         deployment: staging
         steps:
          - step: *build_step
          - step: *deploy_step

    # =======================================================
    # Write-protected main branch, 
    # pipeline runs only on merge of a pull request approved
    # by specific people
    # -------------------------------------------------------
    # Branch restrictions
    # Write Access: none
    # Merge via pull requests: specific people
    # =======================================================

    # main:
    main:
     - stage:
         name: Production 
         deployment: production
         steps:
          - step: *build_step
          - step: *deploy_step

Então ao final, você deve ter uma pasta com dois arquivos:

  • index.html

  • bitbucket-pipelines.yml

No meu exemplo, isso se parece com:


Etapa 12 - Habilitando o Pipelines no Bitbucket

1- Acesse o BitbucketRepositórioConfigurações do RepositórioSettingsEnable Pipelines


Etapa 13 - Criando Variáveis de Ambiente no Bitbucket

1- Acesse o BitbucketRepositórioConfigurações do RepositórioDeployments → crie as seguintes variáveis de ambiente em Production:

  • AWS_OIDC_ROLE_ARN: cole o ARN da Role que você criou em uma das etapas anteriores. Certifique-se de deixar Secured marcado para isso

  • AWS_DEFAULT_REGION: insira a região que seu bucket S3 foi criado, no nosso exemplo foi em Norte da Virgínia, então essa região é us-east-1. Você pode ver todos os nomes das regiões clicando no menu superior direito do console AWS

  • S3_BUCKET: insira o nome do bucket que criou

Atente-se para criar os nomes das variáveis com todas as letras maiúsculas
E observe que em nenhum momento estamos inserindo as chaves de acesso


Etapa 14 - Fazendo comandos Git

1- Acesse o terminal do seu computador e acesse a pasta que contém os 2 arquivos (index.html e bitbucket-pipelines.yml) das etapas anteriores

2- Inicie o Git nessa pasta

git init

3- Configure o git com o email da sua conta Bitbucket:

Lembre-se de alterar <your-bitbucket-email> para o valor real que você usa.
git config user.email "<your-bitbucket-email>"

4- Configure o git com o nome de usuário da sua conta Bitbucket:

Lembre-se de alterar <your-bitbucket-username> para o valor real que você usa.
git config user.name "<your-bitbucket-username>"

5- Adicione o repositório remoto nessa pasta:

Lembre-se de alterar <your-bitbucket-git> para o valor real que você usa.
git remote add origin git@<your-bitbucket-git>

6- Crie uma branch chamada local:

git checkout -b local


Etapa 15 - Verificando o Funcionamento do Pipeline

1- Envie um push local para o Bitbucket:

git add . && \
git commit -m "Deploy Pipeline with Open ID Connect on AWS" && \
git push origin local:main

2- Verifique o BitbucketPipelines e deve ter agora um pipeline em andamento

3- Aguarde sua conclusão e abra os detalhes do pipeline

Esse é o objetivo principal deste artigo, observe que a autenticação entre Bitbucket com a AWS através do OpenID Connect (OIDC) aconteceu com sucesso, lembre-se que nós não definimos em nenhum momento as chaves de acesso, somente o ARN da Role que tem uma relação de confiança e as políticas com permissões necessárias para esse deploy.

Pronto! Podemos verificar que o Bitbucket foi capaz de se autenticar na AWS com tokens temporários do OpenID Connect. Novamente reforço para você observar que em nenhum momento definimos as chaves de acesso e não expomos essas informações, aumentando assim a segurança.

4- Volte para seu editor de texto novamente e altere agora o número da versão de 1 para 2 do arquivo index.html

5- Envie um novo push local para o Bitbucket:

git add . && \
git commit -m "Change index.html version" && \
git push origin local:main

6- Aguarde o Pipeline funcionar novamente, lembrando que ele está se autenticando com OpenID Connect corretamente entre Bitbucket e AWS

E pronto! Acessando novamente o bucket S3 através do seu domínio customizado, vemos o deploy realizado com sucesso.


Bônus

Restrição por Código de Repositório

Sim, nós já aplicamos isso no nosso passo a passo quando editamos a política de relação de confiança, mas inseri novamente aqui para reforçar a estrutura para você.


Restrição por Endereço IP

Para aumentar a segurança, podemos restringir um pouco mais o acesso à função permitindo apenas endereços IP do Bitbucket Pipelines e determinados UUIDs de repositório. Desta forma, outros repositórios não podem acessar essa função, exceto os repositórios especificados dos IPs descritos:


Melhore suas permissões com Assume Role

Vimos até aqui tudo funcionando, mas se observamos com um pouco mais de atenção, vamos notar que as permissões estão anexadas diretamente a Role OIDC que criamos:

Em nosso exemplo prático isso significa que as políticas:

  • oidc_bitbucket_policy

  • s3-bucket-tutorial-bitbucket-oidc-aws.simplescloud.io-policy

Foram anexadas diretamente na role

  • deploy-tutorial-bitbucket-oidc-aws.simplescloud.io-role-prod

O fluxo se parece com:

  1. Bitbucket se comunica com o provedor de identidade AWS através da Role OIDC

  2. A AWS retorna as credenciais temporárias para o Bitbucket

  3. O Bitbucket Pipelines agora obtém as permissões das políticas anexadas diretamente da Role OIDC e pode acessar seus respectivos recursos

Embora isso já seja uma grande melhoria, ainda há uma boa prática de segurança que seria não anexar as políticas de permissões diretamente em um usuário ou em uma role, mas sim criar uma role para o ambiente de deploy do aplicativo e anexar as permissões nessa role, então quando for de fato fazer essa implantação, acontecerá o seguinte fluxo:

  1. Bitbucket se comunica com o provedor de identidade AWS através da Role OIDC

  2. AWS retorna as credenciais temporárias para o Bitbucket

  3. O Bitbucket Pipelines agora não tem as permissões para acessar os respectivos recursos, pois nenhuma política foi anexada diretamente nesta Role OIDC

  4. Mas esta Role OIDC tem permissão para assumir uma segunda role de deploy que contém as permissões de acesso aos respectivos recursos

  5. A Role OIDC assume a Role de deploy e obtém as permissões para os respectivos recursos

Desta forma, note que foi criada uma camada adicional de segurança, pois as permissões estão em uma segunda role assumida.

Não vou me estender mais nesse assunto para não tornar o artigo maior do que já é, mas se tiver dúvidas, talvez seja interessante dar uma olhada em nesta explicação aqui:

Com isso compreendido, imagine agora que não estamos mais fazendo um deploy para um site estático no bucket S3 como nosso exemplo prático, mas imagine então que agora queremos fazer um deploy para um container do Lightsail, para aplicar isso então poderíamos ter por exemplo:

  • Uma Role para o OpenID Connect (OIDC) chamada oidc-bitbucket-role

    • E anexar a política oidc_bitbucket_policy

    •         {
                  "Version": "2012-10-17",
                  "Statement": [
                      {
                          "Sid": "VisualEditor0",
                          "Effect": "Allow",
                          "Action": [
                              "sts:AssumeRole",
                              "sts:GetCallerIdentity",
                              "sts:AssumeRoleWithWebIdentity"
                          ],
                          "Resource": "*"
                      }
                  ]
              }
      

      E lembrando novamente para editar a aba Trust Relationships com seus valores reais da sua conta AWS e Bitbucket

    •         {
                  "Version": "2012-10-17",
                  "Statement": [
                      {
                          "Effect": "Allow",
                          "Principal": {
                              "Federated": "arn:aws:iam::<your-account-id>:oidc-provider/api.bitbucket.org/2.0/workspaces/<your-bitbucket-workspace>/pipelines-config/identity/oidc"
                          },
                          "Action": "sts:AssumeRoleWithWebIdentity",
                          "Condition": {
                              "StringLike": {
                                  "api.bitbucket.org/2.0/workspaces/<your-bitbucket-workspace>/pipelines-config/identity/oidc:sub": "{<your-bitbucket-repo-uuid>}:*"
                              }
                          }
                      }
                  ]
              }
      

  • Criar uma outra Role para o Deploy chamada myapp-deploy-prod-role

    • E anexar a política com acesso ao respectivo recurso, por exemplo uma política que permite ações no Lightsail

    • A dica aqui é editar a aba Trust Relationships permitindo a Role OIDC a assumir essa Role e obter as permissões anexadas a ela, no nosso exemplo permissões para o Lightsail. (Lembre-se de alterar para os valores reais da sua conta AWS)

    •         {
                  "Version": "2012-10-17",
                  "Statement": [
                      {
                          "Sid": "",
                          "Effect": "Allow",
                          "Principal": {
                              "AWS": "arn:aws:iam::<your-account-id>:role/oidc-bitbucket-role"
                          },
                          "Action": "sts:AssumeRole"
                      }
                  ]
              }
      

Pronto! Agora poderíamos criar um arquivo bitbucket-pipelines.yml que faz deploy com o processo do OpenID Connect e do Assume Role, veja como ficaria isso com esse trecho abaixo:

definitions:

  scripts:

    # Commands to install AWS CLI V2
    install_aws_cli: &install_aws_cli
      echo "========== Install AWS CLI V2 ==========" &&
      curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" &&
      unzip awscliv2.zip &&
      ./aws/install &&
      aws --version

    # Commands to install the Lightsail plugin in AWS CLI V2
    install_lightsail_cli_plugin: &install_lightsail_cli_plugin
      echo "===== Install AWS Lightsail CLI Plugin =====" &&
      curl https://s3.us-west-2.amazonaws.com/lightsailctl/latest/linux-amd64/lightsailctl -o /usr/local/bin/lightsailctl &&
      chmod +x /usr/local/bin/lightsailctl

    # Commands to obtain temporary access keys for the 
    # aws role that authenticates through OpenID Connect
    auth_oidc: &auth_oidc
      echo "========== Bitbucket OIDC Assume Role ==========" && 
      export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role-with-web-identity --role-arn "$AWS_OIDC_ROLE_ARN" --role-session-name "Bitbucket-OIDC-$BITBUCKET_DEPLOYMENT_ENVIRONMENT-$BITBUCKET_BUILD_NUMBER" --web-identity-token "$BITBUCKET_STEP_OIDC_TOKEN" --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text))

    # Commands to assume another deploy role with 
    # permissions and obtain your temporary credentials
    aws_sts_assume_role: &aws_sts_assume_role
      echo "========== AWS CLI Assume Role ==========" &&
      STS_TEMP_CREDS=$(aws sts assume-role --region "$AWS_REGION" --role-arn "$AWS_DEPLOY_ROLE_ARN" --role-session-name "Bitbucket-Deploy-$BITBUCKET_DEPLOYMENT_ENVIRONMENT-$BITBUCKET_BUILD_NUMBER") &&
      export AWS_ACCESS_KEY_ID=$(echo $STS_TEMP_CREDS | jq -r .Credentials.AccessKeyId) &&
      export AWS_SECRET_ACCESS_KEY=$(echo $STS_TEMP_CREDS | jq -r .Credentials.SecretAccessKey) &&
      export AWS_SESSION_TOKEN=$(echo $STS_TEMP_CREDS | jq -r .Credentials.SessionToken) &&
      export AWS_SESSION_EXPIRATION=$(echo $STS_TEMP_CREDS | jq -r .Credentials.Expiration) &&
      aws sts get-caller-identity

Novamente não se preocupe senão entender esse arquivo ou os comandos, esse não é o foco deste artigo, a única coisa importante para observar é que há duas variáveis de ambiente importantes:

  • AWS_OIDC_ROLE_ARN: esse é o ARN da Role OpenID Connect (OIDC) que criamos, ou seja em nosso exemplo seria o ARN de oidc-bitbucket-role que não possui nenhuma política anexada além de oidc_bitbucket_policy

  • AWS_DEPLOY_ROLE_ARN: esse é o ARN da Role de Deploy que criamos, ou seja em nosso exemplo seria o ARN de myapp-deploy-prod-role e este sim possui a política que permite acesso aos recursos do Lightsail no nosso exemplo

Então o fluxo que está acontecendo é:

  1. O primeiro trecho auth_oidc está solicitando ao provedor de identidade AWS através do OpenID Connect (OIDC), retornando as credenciais de acesso temporário para o Bitbucket e exportando esses valores em variáveis de ambiente

  2. O segundo trecho aws_sts_assume_role está assumindo a Role myapp-deploy-prod-role e obtendo suas próprias credenciais de acesso temporário

E voltando os olhos para o Bitbucket Pipelines, podemos verificar ele executado com sucesso:


Conclusão

Vimos neste artigo um tutorial completo sobre OpenID Connect (OIDC) entre o Bitbucket e AWS, passamos pelas vantagens e demonstramos um exemplo prático.

O exemplo passou por várias etapas, em resumo nós criamos um provedor de identidade (IdP) na AWS para o Bitbucket, depois nós criamos políticas de permissões restritas aos recursos que usamos, então criamos uma role e anexamos essas políticas, ainda em roles editamos a relação de confiança para o número de id do repositório do Bitbucket, em geral essas são as etapas principais e em resumo o OIDC é configurado mesmo entre as etapas 7 a 10, porém todas as outras etapas foram escritas para exemplificar melhor.

O exemplo prático apresentado ainda pode ter muitas melhorias, como por exemplo adicionar uma distribuição Cloudfront para obter um HTTPS e adicionar no pipeline uma invalidação de cache por exemplo, embora os passos envolvam muitas coisas como comandos do git e arquivos de configuração de pipeline, o objetivo não era explicar isso, mas sim sobre o OIDC exclusivamente.

Uma vez que esse conceito e essa lógica foi entendida, o provedor de identidade (IdP) criado, a configuração do OIDC foi feita e a única coisa que você precisa fazer dai em diante é criar políticas e roles novas com a relação de confiança editada para o repositório, você não precisa criar um provedor de identidade (IdP) para cada projeto.

Por exemplo se você criar um novo repositório e quer fazer o deploy em um container do Fargate, você só precisaria criar uma política com permissões para o ECR e o ECS, por fim criar uma nova role com a relação de confiança editada para o UUID do repositório e com essas permissões anexadas, mas não precisaria criar novamente o provedor de identidade (IdP), pois ela já foi criada e precisa ser criada uma única vez.

Desta forma o Bitbucket poderá acessar sua variável de ambiente com o ARN da role criada e ela poderá obter chaves temporárias de acesso com sucesso com as permissões adequadas anexadas a ela.

Se preferir avançar ainda mais, você viu que é possível criar uma segunda role para o deploy e anexar as permissões nela, fazendo com que a role OIDC assuma as permissões da segunda role.

Lembre-se de excluir após o tutorial o Bucket S3, o registro DNS no Route 53, as políticas e a role para não obter cobranças indesejadas e manter sua conta AWS limpa e organizada.
Espero que essas informações tenham sido úteis para você.