Developer → Feature Branch → Pull Request → Validação (CI) ↓ Merge na main ↓ Build & Push (CD) ↓ Deploy no ECS Fargate
Developer → Feature Branch → Pull Request → Validação (CI) ↓ Merge na main ↓ Build & Push (CD) ↓ Deploy no ECS Fargate
Developer → Feature Branch → Pull Request → Validação (CI) ↓ Merge na main ↓ Build & Push (CD) ↓ Deploy no ECS Fargate
AmazonECS_FullAccess
AmazonEC2ContainerRegistryFullAccess
AmazonVPCReadOnlyAccess
IAMFullAccess
CloudWatchLogsFullAccess
AmazonS3FullAccess
AmazonECS_FullAccess
AmazonEC2ContainerRegistryFullAccess
AmazonVPCReadOnlyAccess
IAMFullAccess
CloudWatchLogsFullAccess
AmazonS3FullAccess
AmazonECS_FullAccess
AmazonEC2ContainerRegistryFullAccess
AmazonVPCReadOnlyAccess
IAMFullAccess
CloudWatchLogsFullAccess
AmazonS3FullAccess
aws configure
aws configure
aws configure
AWS Access Key ID: AKIA...
AWS Secret Access Key: wJal...
Default region name: us-east-1
Default output format: json
AWS Access Key ID: AKIA...
AWS Secret Access Key: wJal...
Default region name: us-east-1
Default output format: json
AWS Access Key ID: AKIA...
AWS Secret Access Key: wJal...
Default region name: us-east-1
Default output format: json
# Provider AWS
provider "aws" { region = "us-east-1"
} # Repositório ECR para armazenar imagens Docker
resource "aws_ecr_repository" "app_repository" { name = "minha-app-repository"
} # Cluster ECS
resource "aws_ecs_cluster" "app_cluster" { name = "minha-app-cluster"
}
# Provider AWS
provider "aws" { region = "us-east-1"
} # Repositório ECR para armazenar imagens Docker
resource "aws_ecr_repository" "app_repository" { name = "minha-app-repository"
} # Cluster ECS
resource "aws_ecs_cluster" "app_cluster" { name = "minha-app-cluster"
}
# Provider AWS
provider "aws" { region = "us-east-1"
} # Repositório ECR para armazenar imagens Docker
resource "aws_ecr_repository" "app_repository" { name = "minha-app-repository"
} # Cluster ECS
resource "aws_ecs_cluster" "app_cluster" { name = "minha-app-cluster"
}
resource "aws_iam_role" "ecs_task_execution_role" { name = "ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } }] })
} resource "aws_iam_role_policy_attachment" "ecs_policy" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
resource "aws_iam_role" "ecs_task_execution_role" { name = "ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } }] })
} resource "aws_iam_role_policy_attachment" "ecs_policy" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
resource "aws_iam_role" "ecs_task_execution_role" { name = "ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } }] })
} resource "aws_iam_role_policy_attachment" "ecs_policy" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
resource "aws_ecs_task_definition" "app_task" { family = "minha-app-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = jsonencode([{ name = "app" image = "${aws_ecr_repository.app_repository.repository_url}:latest" portMappings = [{ containerPort = 8080 hostPort = 8080 }] logConfiguration = { logDriver = "awslogs" options = { "awslogs-group" = "/ecs/minha-app" "awslogs-region" = "us-east-1" "awslogs-stream-prefix" = "ecs" } } }])
}
resource "aws_ecs_task_definition" "app_task" { family = "minha-app-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = jsonencode([{ name = "app" image = "${aws_ecr_repository.app_repository.repository_url}:latest" portMappings = [{ containerPort = 8080 hostPort = 8080 }] logConfiguration = { logDriver = "awslogs" options = { "awslogs-group" = "/ecs/minha-app" "awslogs-region" = "us-east-1" "awslogs-stream-prefix" = "ecs" } } }])
}
resource "aws_ecs_task_definition" "app_task" { family = "minha-app-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = jsonencode([{ name = "app" image = "${aws_ecr_repository.app_repository.repository_url}:latest" portMappings = [{ containerPort = 8080 hostPort = 8080 }] logConfiguration = { logDriver = "awslogs" options = { "awslogs-group" = "/ecs/minha-app" "awslogs-region" = "us-east-1" "awslogs-stream-prefix" = "ecs" } } }])
}
resource "aws_ecs_service" "app_service" { name = "minha-app-service" cluster = aws_ecs_cluster.app_cluster.id task_definition = aws_ecs_task_definition.app_task.arn desired_count = 1 launch_type = "FARGATE" network_configuration { subnets = data.aws_subnets.default.ids security_groups = [aws_security_group.app_sg.id] assign_public_ip = true }
}
resource "aws_ecs_service" "app_service" { name = "minha-app-service" cluster = aws_ecs_cluster.app_cluster.id task_definition = aws_ecs_task_definition.app_task.arn desired_count = 1 launch_type = "FARGATE" network_configuration { subnets = data.aws_subnets.default.ids security_groups = [aws_security_group.app_sg.id] assign_public_ip = true }
}
resource "aws_ecs_service" "app_service" { name = "minha-app-service" cluster = aws_ecs_cluster.app_cluster.id task_definition = aws_ecs_task_definition.app_task.arn desired_count = 1 launch_type = "FARGATE" network_configuration { subnets = data.aws_subnets.default.ids security_groups = [aws_security_group.app_sg.id] assign_public_ip = true }
}
# Registra o GitHub como provedor OIDC na AWS
resource "aws_iam_openid_connect_provider" "github" { url = "https://token.actions.githubusercontent.com" client_id_list = ["sts.amazonaws.com"] thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"]
} # Role que o GitHub Actions vai assumir
resource "aws_iam_role" "github_actions_role" { name = "github-actions-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.github.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { "token.actions.githubusercontent.com:sub" = "repo:meu-usuario/meu-repo:ref:refs/heads/main" } } }] })
}
# Registra o GitHub como provedor OIDC na AWS
resource "aws_iam_openid_connect_provider" "github" { url = "https://token.actions.githubusercontent.com" client_id_list = ["sts.amazonaws.com"] thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"]
} # Role que o GitHub Actions vai assumir
resource "aws_iam_role" "github_actions_role" { name = "github-actions-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.github.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { "token.actions.githubusercontent.com:sub" = "repo:meu-usuario/meu-repo:ref:refs/heads/main" } } }] })
}
# Registra o GitHub como provedor OIDC na AWS
resource "aws_iam_openid_connect_provider" "github" { url = "https://token.actions.githubusercontent.com" client_id_list = ["sts.amazonaws.com"] thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"]
} # Role que o GitHub Actions vai assumir
resource "aws_iam_role" "github_actions_role" { name = "github-actions-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.github.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { "token.actions.githubusercontent.com:sub" = "repo:meu-usuario/meu-repo:ref:refs/heads/main" } } }] })
}
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["MeuProjeto/MeuProjeto.csproj", "MeuProjeto/"]
RUN dotnet restore "MeuProjeto/MeuProjeto.csproj"
COPY . .
WORKDIR "/src/MeuProjeto"
RUN dotnet build -c Release -o /app/build # Stage 2: Publish
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false # Stage 3: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
EXPOSE 8080
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MeuProjeto.dll"]
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["MeuProjeto/MeuProjeto.csproj", "MeuProjeto/"]
RUN dotnet restore "MeuProjeto/MeuProjeto.csproj"
COPY . .
WORKDIR "/src/MeuProjeto"
RUN dotnet build -c Release -o /app/build # Stage 2: Publish
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false # Stage 3: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
EXPOSE 8080
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MeuProjeto.dll"]
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["MeuProjeto/MeuProjeto.csproj", "MeuProjeto/"]
RUN dotnet restore "MeuProjeto/MeuProjeto.csproj"
COPY . .
WORKDIR "/src/MeuProjeto"
RUN dotnet build -c Release -o /app/build # Stage 2: Publish
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false # Stage 3: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
EXPOSE 8080
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MeuProjeto.dll"]
name: PR Validation on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Restore run: dotnet restore MinhaSolution.sln - name: Build run: dotnet build MinhaSolution.sln --no-restore -c Release test: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Run Tests with Coverage run: | dotnet test MinhaSolution.sln \ --collect:"XPlat Code Coverage" \ --results-directory ./coverage
name: PR Validation on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Restore run: dotnet restore MinhaSolution.sln - name: Build run: dotnet build MinhaSolution.sln --no-restore -c Release test: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Run Tests with Coverage run: | dotnet test MinhaSolution.sln \ --collect:"XPlat Code Coverage" \ --results-directory ./coverage
name: PR Validation on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Restore run: dotnet restore MinhaSolution.sln - name: Build run: dotnet build MinhaSolution.sln --no-restore -c Release test: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' - name: Run Tests with Coverage run: | dotnet test MinhaSolution.sln \ --collect:"XPlat Code Coverage" \ --results-directory ./coverage
aws ecr describe-repositories --repository-names minha-app-repository \ --query "repositories[0].repositoryUri" --output text
aws ecr describe-repositories --repository-names minha-app-repository \ --query "repositories[0].repositoryUri" --output text
aws ecr describe-repositories --repository-names minha-app-repository \ --query "repositories[0].repositoryUri" --output text
aws iam get-role --role-name github-actions-role \ --query "Role.Arn" --output text
aws iam get-role --role-name github-actions-role \ --query "Role.Arn" --output text
aws iam get-role --role-name github-actions-role \ --query "Role.Arn" --output text
name: Build and Deploy on: push: branches: [main] permissions: #permissões necessárias para autenticação OIDC id-token: write contents: read env: AWS_REGION: us-east-1 jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure AWS Credentials (OIDC) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v2 - name: Build Docker Image run: docker build -t minha-app . - name: Tag Image run: docker tag minha-app:latest ${{ secrets.ECR_REPOSITORY }}:latest - name: Push to ECR run: docker push ${{ secrets.ECR_REPOSITORY }}:latest - name: Deploy to ECS run: | aws ecs update-service \ --cluster minha-app-cluster \ --service minha-app-service \ --force-new-deployment
name: Build and Deploy on: push: branches: [main] permissions: #permissões necessárias para autenticação OIDC id-token: write contents: read env: AWS_REGION: us-east-1 jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure AWS Credentials (OIDC) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v2 - name: Build Docker Image run: docker build -t minha-app . - name: Tag Image run: docker tag minha-app:latest ${{ secrets.ECR_REPOSITORY }}:latest - name: Push to ECR run: docker push ${{ secrets.ECR_REPOSITORY }}:latest - name: Deploy to ECS run: | aws ecs update-service \ --cluster minha-app-cluster \ --service minha-app-service \ --force-new-deployment
name: Build and Deploy on: push: branches: [main] permissions: #permissões necessárias para autenticação OIDC id-token: write contents: read env: AWS_REGION: us-east-1 jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure AWS Credentials (OIDC) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v2 - name: Build Docker Image run: docker build -t minha-app . - name: Tag Image run: docker tag minha-app:latest ${{ secrets.ECR_REPOSITORY }}:latest - name: Push to ECR run: docker push ${{ secrets.ECR_REPOSITORY }}:latest - name: Deploy to ECS run: | aws ecs update-service \ --cluster minha-app-cluster \ --service minha-app-service \ --force-new-deployment
# 1. Obtenha o ARN da task em execução
TASK_ARN=$(aws ecs list-tasks \ --cluster minha-app-cluster \ --service-name minha-app-service \ --query "taskArns[0]" --output text) # 2. Obtenha o ID da interface de rede (ENI)
ENI_ID=$(aws ecs describe-tasks \ --cluster minha-app-cluster \ --tasks $TASK_ARN \ --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" \ --output text) # 3. Obtenha o IP público
aws ec2 describe-network-interfaces \ --network-interface-ids $ENI_ID \ --query "NetworkInterfaces[0].Association.PublicIp" \ --output text
# 1. Obtenha o ARN da task em execução
TASK_ARN=$(aws ecs list-tasks \ --cluster minha-app-cluster \ --service-name minha-app-service \ --query "taskArns[0]" --output text) # 2. Obtenha o ID da interface de rede (ENI)
ENI_ID=$(aws ecs describe-tasks \ --cluster minha-app-cluster \ --tasks $TASK_ARN \ --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" \ --output text) # 3. Obtenha o IP público
aws ec2 describe-network-interfaces \ --network-interface-ids $ENI_ID \ --query "NetworkInterfaces[0].Association.PublicIp" \ --output text
# 1. Obtenha o ARN da task em execução
TASK_ARN=$(aws ecs list-tasks \ --cluster minha-app-cluster \ --service-name minha-app-service \ --query "taskArns[0]" --output text) # 2. Obtenha o ID da interface de rede (ENI)
ENI_ID=$(aws ecs describe-tasks \ --cluster minha-app-cluster \ --tasks $TASK_ARN \ --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" \ --output text) # 3. Obtenha o IP público
aws ec2 describe-network-interfaces \ --network-interface-ids $ENI_ID \ --query "NetworkInterfaces[0].Association.PublicIp" \ --output text
❌ Modelo Tradicional: GitHub Secrets → AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - Credenciais estáticas que nunca expiram - Se vazadas, acesso total até serem rotacionadas manualmente
❌ Modelo Tradicional: GitHub Secrets → AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - Credenciais estáticas que nunca expiram - Se vazadas, acesso total até serem rotacionadas manualmente
❌ Modelo Tradicional: GitHub Secrets → AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - Credenciais estáticas que nunca expiram - Se vazadas, acesso total até serem rotacionadas manualmente
✅ Modelo OIDC: GitHub Actions → JWT Token → AWS STS → Credenciais Temporárias - Credenciais expiram automaticamente - Escopo restrito: apenas uma branch de um repositório específico - Sem segredos de longa duração armazenados
✅ Modelo OIDC: GitHub Actions → JWT Token → AWS STS → Credenciais Temporárias - Credenciais expiram automaticamente - Escopo restrito: apenas uma branch de um repositório específico - Sem segredos de longa duração armazenados
✅ Modelo OIDC: GitHub Actions → JWT Token → AWS STS → Credenciais Temporárias - Credenciais expiram automaticamente - Escopo restrito: apenas uma branch de um repositório específico - Sem segredos de longa duração armazenados
1. git checkout -b feature/minha-feature
2. # Desenvolve e commita
3. git push origin feature/minha-feature
4. # Abre Pull Request → Dispara pr-validation.yml │ ├── ✅ Build compila com sucesso └── ✅ Testes passam com cobertura │
5. # Code review + Aprovação
6. # Merge na main → Dispara build-and-deploy.yml │ ├── 🔐 Autenticação via OIDC ├── 🐳 Build da imagem Docker (multi-stage) ├── 📦 Push para o ECR └── 🚀 Deploy no ECS Fargate │
7. # Nova versão rodando em produção
1. git checkout -b feature/minha-feature
2. # Desenvolve e commita
3. git push origin feature/minha-feature
4. # Abre Pull Request → Dispara pr-validation.yml │ ├── ✅ Build compila com sucesso └── ✅ Testes passam com cobertura │
5. # Code review + Aprovação
6. # Merge na main → Dispara build-and-deploy.yml │ ├── 🔐 Autenticação via OIDC ├── 🐳 Build da imagem Docker (multi-stage) ├── 📦 Push para o ECR └── 🚀 Deploy no ECS Fargate │
7. # Nova versão rodando em produção
1. git checkout -b feature/minha-feature
2. # Desenvolve e commita
3. git push origin feature/minha-feature
4. # Abre Pull Request → Dispara pr-validation.yml │ ├── ✅ Build compila com sucesso └── ✅ Testes passam com cobertura │
5. # Code review + Aprovação
6. # Merge na main → Dispara build-and-deploy.yml │ ├── 🔐 Autenticação via OIDC ├── 🐳 Build da imagem Docker (multi-stage) ├── 📦 Push para o ECR └── 🚀 Deploy no ECS Fargate │
7. # Nova versão rodando em produção - Pré-requisitos
- Visão Geral da Arquitetura
- Configurando o IAM para o Terraform
- Infraestrutura como Código com Terraform Recursos Provisionados
IAM Role para Tarefas ECS
Task Definition (Fargate)
ECS Service
OIDC: Autenticação Sem Credenciais Estáticas
- Recursos Provisionados
- IAM Role para Tarefas ECS
- Task Definition (Fargate)
- ECS Service
- OIDC: Autenticação Sem Credenciais Estáticas
- Dockerfile Multi-Stage
- Pipeline de CI
- Protegendo a Branch Main
- Configurando as Secrets no GitHub
- Pipeline de CD
- Acessando a Aplicação após o Deploy
- Segurança: OIDC em Detalhe
- Fluxo Completo: Do Commit ao Deploy
- Considerações Finais - Recursos Provisionados
- IAM Role para Tarefas ECS
- Task Definition (Fargate)
- ECS Service
- OIDC: Autenticação Sem Credenciais Estáticas - Acesse IAM > Users > Create User
- Nomeie o usuário (ex: terraform-deployer)
- Anexe as policies necessárias para os recursos que serão criados: - Após criar o usuário, gere um Access Key (IAM > Users > Security credentials > Create access key)
- Selecione o caso de uso Command Line Interface (CLI) - A imagem final contém apenas o runtime, não o SDK completo
- Reduz significativamente o tamanho da imagem
- O código-fonte não fica presente na imagem de produção - Job build — Compila a solução para garantir que não há erros de compilação
- Job test — Roda os testes unitários com cobertura de código usando Coverlet - Branch name pattern: main
- Marque Require a pull request before merging — impede push direto na main
- Marque Require status checks to pass before merging — bloqueia o merge até que os checks passem
- Em Status checks that are required, busque e adicione os jobs da pipeline de CI: build
test - Autenticação OIDC — O GitHub troca seu token JWT por credenciais AWS temporárias
- Login no ECR — Autentica o Docker no registro da AWS
- Build e Push — Constrói a imagem Docker e envia para o ECR
- Deploy — Dispara um novo deployment no ECS, que puxa a imagem atualizada e substitui o container antigo - Acesse ECS > Clusters > minha-app-cluster
- Clique na aba Tasks
- Clique na task em execução (status RUNNING)
- Na seção Network, copie o Public IP
- Acesse no navegador: http://<PUBLIC_IP>:8080 - Registrar o GitHub como OIDC Provider na AWS (via Terraform)
- Criar uma IAM Role com trust policy apontando para o repositório
- No workflow, usar permissions: id-token: write e a action configure-aws-credentials com role-to-assume - Infraestrutura como Código — Toda a infraestrutura é versionada e reproduzível
- Autenticação Keyless — OIDC elimina o risco de credenciais estáticas
- Serverless Containers — Fargate remove a necessidade de gerenciar servidores
- Separação CI/CD — Validação em PRs e deploy apenas na main
- Imagens otimizadas — Multi-stage build reduz a superfície de ataque - Location Santa Maria, Brazil
- Education computer Science
- Work FrontEnd Developer at Bitzen
- Joined Dec 3, 2021