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

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">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.</div>
</div>

---

## 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706553053724/f70b641a-cf2a-4a7d-ab1d-515fece8f918.png align="center")

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:

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">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. <strong>Este artigo tem o escopo de explicar somente a configuração do OIDC entre o Bitbucket e AWS.</strong></div>
</div>

* **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](https://intelligentpathways.com.au/wp-content/uploads/2022/01/pipelines_secrets.png align="left")

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`
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">O importante aqui é o nome do seu bucket S3 ser um domínio totalmente qualificado <code>(FQDN)</code>, por exemplo se seu domínio é <code>example.com</code> - crie seu bucket como <code>mytutorial.example.com</code> ao invés de somente <code>mytutorial</code></div>
</div>

* 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
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706535449930/df756d6f-6190-4d07-80e7-857e90c71761.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706535472137/b6cdd00e-a43e-4c7d-a9fd-6230c888070f.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706535567601/ff2bc752-c273-4b8c-b249-89e78ab7d6ca.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706535578252/f2aa0fe3-702c-40ec-ae4e-4bede50e4579.png align="center")

---

### 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:

```xml
<!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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706535802730/05662f62-aa78-47a7-8d28-74b24a54cda2.png align="center")

---

### 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**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536120297/3989bc4f-9d3c-43db-9991-0923d084e8ac.png align="center")

2-

* Clique em **Enable**
    
* Escolha a opção **Host a static website**
    
* Defina o nome do documento como **index.html**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536185621/a154ec70-c355-4b1e-9ae9-0f41f823d79a.png align="center")

---

### Etapa 4 - Tornando o Site Público

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536361330/85b7bec1-e0b2-41f7-82e5-39172b813681.png align="center")

2- Insira a política abaixo e salve

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-bucket-name&gt;</code> pelo nome real do bucket S3 que você criou.</div>
</div>

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<your-bucket-name>/*"
        }
    ]
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536492152/1d788e56-8982-4209-ae37-94c05aa9704e.png align="center")

---

### 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
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536646495/6db4acb1-ace3-418d-b737-a401fed6fae7.png align="center")

---

### 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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706536783475/2df5caf8-3c10-4e34-834a-7f62a6a6b4ea.png align="center")

---

### 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706537057617/3c1695e8-7e04-4344-bbff-7a41922ea98c.png align="center")

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**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706537232376/b487ce09-fa51-491f-b2d1-768af4093cd2.png align="center")

---

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

1- Acesse o console **AWS** → **IAM** → **Policies** → **Create Policy** → cole o conteúdo

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-bucket-name&gt;</code> para o nome real do bucket S3 que você criou.</div>
</div>

```json
{
    "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>/*"
            ]
        }
    ]
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706537514807/242e8407-3ed5-4e23-9d27-9386b12c00e1.png align="center")

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`
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706537621345/297a4773-12c1-47b1-a495-e67d93a6cf3a.png align="center")

---

### 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:

```json
{
    "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`
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706537748045/4a2a338f-298c-442c-a087-9dbef0fb9680.png align="center")

---

### 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
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706538120940/ff1d82f9-5208-4288-a4f9-0c3c2afd7b01.png align="center")

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**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706538286889/263c9bcc-c530-4cf0-8cbc-ea5f4e91670e.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706538307047/d383faa5-eab5-4734-b3c7-b88e6593fe0f.png align="center")

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

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-account-id&gt;</code> 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 <code>&lt;your-bitbucket-workspace&gt;</code> pelo nome real do seu workspace do Bitbucket e por fim lembre-se de alterar <code>&lt;your-bitbucket-repo-uuid&gt;</code> pelo código que você copiou em uma das etapas anteriores.</div>
</div>

```json
{
    "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
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text"><strong>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.</strong></div>
</div>

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706539231794/3b9ec54b-4d85-4dbb-a1d4-c0f7617c47e8.png align="center")

---

### 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`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541022175/9a6c0f71-ea12-41d6-838c-917c11568d48.png align="center")

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706540112469/c14372d4-20b4-475b-97e1-fc1ce90e52be.png align="center")

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

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">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 <code>oidc: true</code> que está habilitando o uso do OpenID Connect.</div>
</div>

```yaml
# 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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706540409931/45b66bcf-b502-4425-9c64-b8556d7d7d26.png align="center")

---

### Etapa 12 - Habilitando o Pipelines no Bitbucket

1- Acesse o **Bitbucket** → **Repositório** → **Configurações do Repositório** → **Settings** → **Enable Pipelines**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706540506895/85d8b90d-7a7a-4041-ad80-0b0a3a2bd325.png align="center")

---

### 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 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
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Atente-se para criar os nomes das variáveis com todas as letras maiúsculas</div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">☑</div>
<div data-node-type="callout-text">E observe que em nenhum momento estamos inserindo as chaves de acesso</div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706540852124/d7a6db85-8218-4c62-98b1-32cdf0353553.png align="center")

---

### 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

```bash
git init
```

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

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-bitbucket-email&gt;</code> para o valor real que você usa.</div>
</div>

```bash
git config user.email "<your-bitbucket-email>"
```

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

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-bitbucket-username&gt;</code> para o valor real que você usa.</div>
</div>

```bash
git config user.name "<your-bitbucket-username>"
```

5- Adicione o repositório remoto nessa pasta:

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">Lembre-se de alterar <code>&lt;your-bitbucket-git&gt;</code> para o valor real que você usa.</div>
</div>

```bash
git remote add origin git@<your-bitbucket-git>
```

6- Crie uma branch chamada local:

```bash
git checkout -b local
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541414270/97bca142-1495-4400-9bcd-18e9ef82a981.png align="center")

---

### Etapa 15 - Verificando o Funcionamento do Pipeline

1- Envie um push local para o Bitbucket:

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706542031066/8c2336d8-0e37-41ee-a35d-2e60c5ac64a9.png align="center")

2- Verifique o **Bitbucket** → **Pipelines** e deve ter agora um pipeline em andamento

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541679131/c7cc3e8a-8719-45a3-9871-7d402adca10b.png align="center")

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

<div data-node-type="callout">
<div data-node-type="callout-emoji">✅</div>
<div data-node-type="callout-text"><strong>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.</strong></div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541749160/50584d56-9b4a-4cf4-8f07-e94c8af55843.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text"><strong>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.</strong></div>
</div>

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`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541891813/10bea709-0374-49b7-97f6-e3f5fc717304.png align="center")

5- Envie um novo push local para o Bitbucket:

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706541952430/b75f4461-10f1-40b6-a1be-e86061c54530.png align="center")

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706542124105/20abe090-105a-456c-a3b9-95df9e2983f8.png align="center")

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706542188981/4eb0044a-f4d0-459a-b916-c171a78b2ab9.png align="center")

---

## 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ê.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706907725554/5e3f8c8f-3b67-4b07-99a2-d54fe888a04d.png align="center")

---

### 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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706907706355/5c8f2571-8338-4b29-8d43-496a1f19ccbf.png align="center")

---

### 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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706907652639/18762351-489e-48d3-bb08-f5b3dcac7ce5.png align="center")

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:

* 👉 [Assume Role - Assumindo Permissões](https://simplescloud.io/aws-cli-instalacao-e-configuracao#heading-assume-role-assumindo-permissoes)
    

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`
        
    * ```json
              {
                  "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
        
    * ```json
              {
                  "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>}:*"
                              }
                          }
                      }
                  ]
              }
        ```
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706904995294/2f59dcf7-cb54-46a9-9e4e-9066250e468e.png align="center")
        
* 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)
        
    * ```json
              {
                  "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:

```yaml
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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1706906979660/b731df57-a9b8-4537-a94e-f2789b743c01.png align="center")

---

## 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.

<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">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.</div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">✅</div>
<div data-node-type="callout-text">Espero que essas informações tenham sido úteis para você.</div>
</div>
