From 080ea0320ba470b0b9aedb68fc35bad734481aaa Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 00:50:09 -0300 Subject: [PATCH 1/6] fix sonar --- .github/workflows/deploy.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 57afb5e..bd94084 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,6 +7,7 @@ on: env: TF_WORKSPACE: default AWS_REGION: us-east-1 + SKIP_SONAR: true jobs: @@ -41,13 +42,13 @@ jobs: mvn clean verify # ========================================================= - # SONARCLOUD + # SONARCLOUD (BYPASSADO) # ========================================================= sonarqube: name: SonarCloud runs-on: ubuntu-latest needs: test - if: github.ref == 'refs/heads/main' + if: env.SKIP_SONAR != 'true' && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 @@ -79,14 +80,18 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: | cd app - mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=soat-tech-challenge-2025_lambda-identification-auth + mvn -B verify \ + org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + -Dsonar.projectKey=soat-tech-challenge-2025_lambda-identification-auth \ + -Dsonar.organization=soat-tech-challenge-2025 \ + -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml # ========================================================= - # DEPLOY LAMBDA (ORIGINAL, só com depends) ⚠️ + # DEPLOY LAMBDA (ORIGINAL) # ========================================================= deploy: runs-on: ubuntu-latest - needs: sonarqube + needs: test # ✅ NÃO BLOQUEIA PELO SONAR environment: Production permissions: id-token: write From 14a85370f89bcf06e5289d8f7e0472a38b1c7f3a Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 00:54:59 -0300 Subject: [PATCH 2/6] fix sonar --- .github/workflows/deploy.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bd94084..6b2f38e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,7 +7,6 @@ on: env: TF_WORKSPACE: default AWS_REGION: us-east-1 - SKIP_SONAR: true jobs: @@ -42,13 +41,13 @@ jobs: mvn clean verify # ========================================================= - # SONARCLOUD (BYPASSADO) + # SONARCLOUD (BYPASS CONTROLADO) # ========================================================= sonarqube: name: SonarCloud runs-on: ubuntu-latest needs: test - if: env.SKIP_SONAR != 'true' && github.ref == 'refs/heads/main' + if: ${{ secrets.SKIP_SONAR != 'true' && github.ref == 'refs/heads/main' }} steps: - uses: actions/checkout@v4 @@ -87,11 +86,11 @@ jobs: -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml # ========================================================= - # DEPLOY LAMBDA (ORIGINAL) + # DEPLOY LAMBDA # ========================================================= deploy: runs-on: ubuntu-latest - needs: test # ✅ NÃO BLOQUEIA PELO SONAR + needs: test # 🔒 NÃO BLOQUEIA PELO SONAR environment: Production permissions: id-token: write From cf78670446d55f262a4bcc9cbed174a78edf4c39 Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 00:56:45 -0300 Subject: [PATCH 3/6] fix sonar --- .github/workflows/deploy.yml | 80 ------------------------------------ 1 file changed, 80 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6b2f38e..d18d00a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -9,88 +9,8 @@ env: AWS_REGION: us-east-1 jobs: - - # ========================================================= - # TESTS (JUnit + JaCoCo) - # ========================================================= - test: - name: Test Application - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 17 - - - name: Cache Maven - uses: actions/cache@v4 - with: - path: ~/.m2 - key: maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - maven- - - - name: Run tests with coverage - run: | - cd app - mvn clean verify - - # ========================================================= - # SONARCLOUD (BYPASS CONTROLADO) - # ========================================================= - sonarqube: - name: SonarCloud - runs-on: ubuntu-latest - needs: test - if: ${{ secrets.SKIP_SONAR != 'true' && github.ref == 'refs/heads/main' }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: zulu - - - name: Cache SonarCloud packages - uses: actions/cache@v4 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - - name: Cache Maven packages - uses: actions/cache@v4 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - - - name: Build and analyze - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - cd app - mvn -B verify \ - org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ - -Dsonar.projectKey=soat-tech-challenge-2025_lambda-identification-auth \ - -Dsonar.organization=soat-tech-challenge-2025 \ - -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml - - # ========================================================= - # DEPLOY LAMBDA - # ========================================================= deploy: runs-on: ubuntu-latest - needs: test # 🔒 NÃO BLOQUEIA PELO SONAR environment: Production permissions: id-token: write From 9b3ec2643b7e478619694568b2a14d52fcbf1e97 Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 01:25:18 -0300 Subject: [PATCH 4/6] login e me --- api_gateway.tf | 10 +- .../java/tech/buildrun/lambda/Handler.java | 100 +++++++++++++++--- 2 files changed, 91 insertions(+), 19 deletions(-) diff --git a/api_gateway.tf b/api_gateway.tf index d7cc53a..e291f5c 100644 --- a/api_gateway.tf +++ b/api_gateway.tf @@ -6,8 +6,14 @@ resource "aws_apigatewayv2_integration" "lambda_backend" { payload_format_version = "2.0" } -resource "aws_apigatewayv2_route" "auth_token_route" { +resource "aws_apigatewayv2_route" "login" { api_id = data.aws_apigatewayv2_api.tc_api.id - route_key = "POST /auth/token" + route_key = "POST /login" + target = "integrations/${aws_apigatewayv2_integration.lambda_backend.id}" +} + +resource "aws_apigatewayv2_route" "me" { + api_id = data.aws_apigatewayv2_api.tc_api.id + route_key = "GET /me" target = "integrations/${aws_apigatewayv2_integration.lambda_backend.id}" } \ No newline at end of file diff --git a/app/src/main/java/tech/buildrun/lambda/Handler.java b/app/src/main/java/tech/buildrun/lambda/Handler.java index 3154d6f..a23693a 100644 --- a/app/src/main/java/tech/buildrun/lambda/Handler.java +++ b/app/src/main/java/tech/buildrun/lambda/Handler.java @@ -1,12 +1,15 @@ package tech.buildrun.lambda; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import com.fasterxml.jackson.databind.ObjectMapper; import java.nio.charset.StandardCharsets; @@ -25,39 +28,79 @@ public class Handler implements RequestHandler body = - mapper.readValue(request.getBody(), Map.class); - String username = body.get("user"); + try { + String path = request.getPath(); + String method = request.getHttpMethod(); - if (username == null) { - return response(400, Map.of("message", "user obrigatórios")); + if ("/login".equals(path) && "POST".equalsIgnoreCase(method)) { + return login(request); } - String token = gerarToken(username); + if ("/me".equals(path) && "GET".equalsIgnoreCase(method)) { + return me(request); + } - return response(200, Map.of("token", token)); + return response(404, Map.of("message", "Rota não encontrada")); } catch (Exception e) { try { - return response(500, Map.of("message", "Erro ao gerar token")); + return response(500, Map.of("message", "Erro interno")); } catch (Exception ex) { throw new RuntimeException(ex); } } } - private String gerarToken(String username) { + /* ================= LOGIN ================= */ - if (JWT_SECRET == null || JWT_SECRET.length() < 32) { - throw new IllegalStateException("JWT_SECRET deve ter no mínimo 32 caracteres"); + private APIGatewayProxyResponseEvent login(APIGatewayProxyRequestEvent request) throws Exception { + + if (request.getBody() == null || request.getBody().isBlank()) { + return response(400, Map.of("message", "Body obrigatório")); + } + + Map body = + mapper.readValue(request.getBody(), Map.class); + + String username = body.get("user"); + + if (username == null || username.isBlank()) { + return response(400, Map.of("message", "user é obrigatório")); + } + + String token = gerarToken(username); + + return response(200, Map.of("token", token)); + } + + /* ================= ME ================= */ + + private APIGatewayProxyResponseEvent me(APIGatewayProxyRequestEvent request) + throws Exception { + + String authHeader = request.getHeaders().get("authorization"); + + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + return response(401, Map.of("message", "Token não informado")); } + String token = authHeader.replace("Bearer ", ""); + + Claims claims = validarToken(token); + + return response(200, Map.of( + "user", claims.getSubject(), + "role", claims.get("role") + )); + } + + /* ================= JWT ================= */ + + private String gerarToken(String username) { + + validarSecret(); + SecretKey key = Keys.hmacShaKeyFor( JWT_SECRET.getBytes(StandardCharsets.UTF_8) ); @@ -71,10 +114,33 @@ private String gerarToken(String username) { .compact(); } + private Claims validarToken(String token) { + + validarSecret(); + + SecretKey key = Keys.hmacShaKeyFor( + JWT_SECRET.getBytes(StandardCharsets.UTF_8) + ); + + return Jwts.parser() + .verifyWith(key) + .build() + .parseSignedClaims(token) + .getPayload(); + } + + private void validarSecret() { + if (JWT_SECRET == null || JWT_SECRET.length() < 32) { + throw new IllegalStateException("JWT_SECRET deve ter no mínimo 32 caracteres"); + } + } + + /* ================= RESPONSE ================= */ + private APIGatewayProxyResponseEvent response(int status, Object body) throws Exception { return new APIGatewayProxyResponseEvent() .withStatusCode(status) .withHeaders(Map.of("Content-Type", "application/json")) .withBody(mapper.writeValueAsString(body)); } -} \ No newline at end of file +} From 7b88567dc8e9537b66a8fc682624306daa15ec40 Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 20:28:56 -0300 Subject: [PATCH 5/6] fix lambda --- .github/workflows/destroy.yml | 92 ++++++++++++++++------------------- lambda.tf | 15 +++++- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/.github/workflows/destroy.yml b/.github/workflows/destroy.yml index e55748e..24b02fb 100644 --- a/.github/workflows/destroy.yml +++ b/.github/workflows/destroy.yml @@ -1,49 +1,43 @@ -name: Destroy Lambda - -on: - workflow_dispatch: # Dispara manualmente - -env: - AWS_REGION: us-east-1 - -jobs: - destroy-lambda: - runs-on: ubuntu-latest - environment: Production - - steps: - # 1️⃣ Checkout do repositório - - uses: actions/checkout@v3 - - # 2️⃣ Configurar credenciais AWS - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} - aws-region: ${{ env.AWS_REGION }} - - # 3️⃣ Verificar se a Lambda existe - - name: Check if Lambda exists - id: check_lambda - run: | - if aws lambda get-function --function-name lambda-identification-auth --region $AWS_REGION > /dev/null 2>&1; then - echo "Lambda exists" - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "Lambda does not exist" - echo "exists=false" >> $GITHUB_OUTPUT - fi - - # 4️⃣ Deletar Lambda se existir - - name: Delete Lambda - if: steps.check_lambda.outputs.exists == 'true' - run: | - echo "Deleting Lambda..." - aws lambda delete-function --function-name lambda-identification-auth --region $AWS_REGION - echo "✅ Lambda deleted successfully" - - # 5️⃣ Mensagem caso a Lambda não exista - - name: Lambda not found - if: steps.check_lambda.outputs.exists == 'false' - run: echo "⚠️ Lambda not found, nothing to delete" \ No newline at end of file + yaml + name: Destroy Infrastructure + + on: + workflow_dispatch: + + env: + AWS_REGION: us-east-1 + TF_DIR: . + + jobs: + destroy: + runs-on: ubuntu-latest + environment: Production + + steps: + - uses: actions/checkout@v3 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: '1.5.7' + + - name: Terraform Init + working-directory: ${{ env.TF_DIR }} + run: terraform init -input=false + + - name: Terraform Plan Destroy (preview) + working-directory: ${{ env.TF_DIR }} + run: terraform plan -destroy -input=false -out=tfplan_destroy + + - name: Terraform Destroy (apply) + working-directory: ${{ env.TF_DIR }} + run: terraform apply -input=false -auto-approve tfplan_destroy + env: + AWS_REGION: ${{ env.AWS_REGION }} diff --git a/lambda.tf b/lambda.tf index 8c8b316..7d09841 100644 --- a/lambda.tf +++ b/lambda.tf @@ -2,8 +2,19 @@ data "aws_iam_role" "lambda_exec_role" { name = "tc-infra-id-lambda-exec-role" } -data "aws_security_group" "id_lambda" { - name = "tc-id-lambda-sg" +resource "aws_security_group" "id_lambda" { + name = "tc-id-lambda-sg" + description = "Security group for Lambda ID function" + vpc_id = data.aws_vpc.tc_lambda_vpc.id + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = var.tags } resource "aws_lambda_function" "id_lambda" { From a300fec796a23fa2b2f963f549d582d324024104 Mon Sep 17 00:00:00 2001 From: carlosbastoslaet Date: Mon, 5 Jan 2026 20:30:15 -0300 Subject: [PATCH 6/6] fix lambda --- lambda.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda.tf b/lambda.tf index 7d09841..478c839 100644 --- a/lambda.tf +++ b/lambda.tf @@ -40,7 +40,7 @@ resource "aws_lambda_function" "id_lambda" { } vpc_config { subnet_ids = data.aws_subnets.tc_lambda_subnets.ids - security_group_ids = [data.aws_security_group.id_lambda.id] + security_group_ids = [aws_security_group.id_lambda.id] } tags = var.tags