Como configurar a Autenticação entre Bitbucket e AWS com OpenID Connect (OIDC)
Table of contents
- Introdução
- O que é OpenID Connect (OIDC)
- Escopo do Tutorial
- Visão Geral e Vantagens
- Pré-Requisitos
- Tutorial
- Cenário
- Etapa 1 - Criando o Bucket S3
- Etapa 2 - Fazendo Upload do index.html no Bucket S3
- Etapa 3 - Habilitando o Site Estático no Bucket S3
- Etapa 4 - Tornando o Site Público
- Etapa 5 - Criando o Registro DNS no Route 53
- Etapa 6 - Verificando o Site Funcionando
- Etapa 7 - Criando um Identity Provider (IdP) na AWS
- Etapa 8 - Criando Política de Acesso para o Bucket S3
- Etapa 9 - Criando Política de Conexão
- Etapa 10 - Criando uma Role de Permissão
- Etapa 11 - Configurando seu Computador
- Etapa 12 - Habilitando o Pipelines no Bitbucket
- Etapa 13 - Criando Variáveis de Ambiente no Bitbucket
- Etapa 14 - Fazendo comandos Git
- Etapa 15 - Verificando o Funcionamento do Pipeline
- Bônus
- Conclusã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:
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:
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
(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 AWS → Bucket 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
<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 AWS → Route 53 → Hosted 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 Bitbucket → configurações do repositório → OpenID 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 AWS → IAM → Identity Providers → Create 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 AWS → IAM → Policies → Create Policy → cole o conteúdo
<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 AWS → IAM → Role → Create 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 Relationships → Edit → e altere para a política abaixo:
<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
paraStringLike
Mudamos
aud
parasub
Adicionamos um
wildcard (*)
ao final do endpoint do repositório
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:
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 Bitbucket → Repositório → Configurações do Repositório → Settings → Enable Pipelines
Etapa 13 - Criando Variáveis de Ambiente no Bitbucket
1- Acesse o Bitbucket → Repositório → Configurações do Repositório → Deployments → 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 issoAWS_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 AWSS3_BUCKET
: insira o nome do bucket que criou
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:
<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:
<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:
<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 Bitbucket → Pipelines e deve ter agora um pipeline em andamento
3- Aguarde sua conclusão e abra os detalhes do pipeline
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:
Bitbucket se comunica com o provedor de identidade AWS através da Role OIDC
A AWS retorna as credenciais temporárias para o Bitbucket
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:
Bitbucket se comunica com o provedor de identidade AWS através da Role OIDC
AWS retorna as credenciais temporárias para o Bitbucket
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
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
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 deoidc-bitbucket-role
que não possui nenhuma política anexada além deoidc_bitbucket_policy
AWS_DEPLOY_ROLE_ARN
: esse é o ARN da Role de Deploy que criamos, ou seja em nosso exemplo seria o ARN demyapp-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 é:
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 ambienteO segundo trecho
aws_sts_assume_role
está assumindo a Rolemyapp-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.