All checks were successful
Code Quality & Security Scan / TFLint (push) Successful in 23s
Code Quality & Security Scan / Terraform Destroy (push) Has been skipped
Code Quality & Security Scan / Tfsec Security Scan (push) Successful in 31s
Code Quality & Security Scan / Checkov Security Scan (push) Successful in 33s
Code Quality & Security Scan / Terraform Validate (push) Successful in 35s
Code Quality & Security Scan / SonarQube Scan (push) Successful in 45s
Code Quality & Security Scan / Terraform Plan (push) Successful in 1m16s
Code Quality & Security Scan / Terraform Apply (push) Successful in 1m35s
The renovate_endpoint and renovate_token values are retrieved from Vault (secret/renovate) via data sources in the Terraform code, not passed as Terraform variables. Changes: - Commented out TF_VAR_renovate_endpoint in all pipeline stages - Commented out TF_VAR_renovate_token in all pipeline stages - These values are properly sourced from Vault data sources This fixes the container restart issue where Renovate couldn't find the Gitea personal access token because the environment variable wasn't being set correctly from Vault data. Affected stages: - terraform-validate (init and validate steps) - terraform-plan (init and plan steps) - terraform-apply (init and apply steps) - terraform-destroy (init, plan, and execute steps)
401 lines
14 KiB
YAML
401 lines
14 KiB
YAML
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
pull_request:
|
|
types: [opened, synchronize, reopened]
|
|
|
|
name: Code Quality & Security Scan
|
|
jobs:
|
|
tflint:
|
|
name: TFLint
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup TFLint
|
|
uses: terraform-linters/setup-tflint@v4
|
|
with:
|
|
tflint_version: latest
|
|
|
|
- name: Initialize TFLint
|
|
run: tflint --init
|
|
|
|
- name: Run TFLint
|
|
run: tflint --format compact
|
|
|
|
tfsec:
|
|
name: Tfsec Security Scan
|
|
runs-on: ubuntu-latest
|
|
needs: tflint
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Run Tfsec
|
|
uses: aquasecurity/tfsec-action@v1.0.3
|
|
with:
|
|
format: default
|
|
soft_fail: false
|
|
|
|
checkov:
|
|
name: Checkov Security Scan
|
|
runs-on: ubuntu-latest
|
|
needs: tfsec
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Run Checkov
|
|
uses: bridgecrewio/checkov-action@v12
|
|
with:
|
|
directory: .
|
|
framework: terraform
|
|
output_format: cli
|
|
soft_fail: false
|
|
|
|
terraform-validate:
|
|
name: Terraform Validate
|
|
runs-on: ubuntu-latest
|
|
needs: checkov
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
with:
|
|
terraform_version: latest
|
|
|
|
- name: Terraform Format Check
|
|
run: terraform fmt -check -recursive
|
|
|
|
- name: Terraform Init (validation only)
|
|
env:
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: "https://gitea.example.com/api/v1/"
|
|
#TF_VAR_renovate_token: "dummy-token-for-validation"
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: terraform init -backend=false
|
|
|
|
- name: Terraform Validate
|
|
env:
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: "https://gitea.example.com/api/v1/"
|
|
#TF_VAR_renovate_token: "dummy-token-for-validation"
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: terraform validate
|
|
|
|
sonarqube:
|
|
name: SonarQube Scan
|
|
runs-on: ubuntu-latest
|
|
needs: terraform-validate
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
# Disabling shallow clone is recommended for improving relevancy of reporting
|
|
fetch-depth: 0
|
|
- name: SonarQube Scan
|
|
uses: sonarsource/sonarqube-scan-action@v6
|
|
env:
|
|
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }}
|
|
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
|
|
|
terraform-plan:
|
|
name: Terraform Plan
|
|
runs-on: ubuntu-latest
|
|
needs: sonarqube
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
with:
|
|
terraform_version: latest
|
|
|
|
- name: Setup Vault CLI
|
|
run: |
|
|
wget -O vault.zip https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
|
|
unzip vault.zip
|
|
sudo mv vault /usr/local/bin/
|
|
vault --version
|
|
|
|
- name: Setup SSH Key for Docker Provider
|
|
env:
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
VAULT_ROLE_ID: ${{ secrets.VAULT_ROLE_ID }}
|
|
VAULT_SECRET_ID: ${{ secrets.VAULT_SECRET_ID }}
|
|
run: |
|
|
chmod +x setup-ssh.sh
|
|
./setup-ssh.sh
|
|
|
|
- name: Terraform Init
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_BACKEND_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
TF_BACKEND_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
|
TF_BACKEND_KEY: docker/renovate/terraform.tfstate
|
|
TF_BACKEND_REGION: "main"
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
terraform init -input=false \
|
|
-backend-config="endpoint=${TF_BACKEND_ENDPOINT}" \
|
|
-backend-config="bucket=${TF_BACKEND_BUCKET}" \
|
|
-backend-config="key=${TF_BACKEND_KEY}" \
|
|
-backend-config="region=${TF_BACKEND_REGION}" \
|
|
-backend-config="skip_credentials_validation=true" \
|
|
-backend-config="skip_metadata_api_check=true" \
|
|
-backend-config="skip_requesting_account_id=true" \
|
|
-backend-config="skip_region_validation=true" \
|
|
-backend-config="use_path_style=true"
|
|
|
|
- name: Terraform Plan
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
terraform plan -input=false -out=tfplan
|
|
terraform show -no-color tfplan > tfplan.txt
|
|
|
|
- name: Install AWS CLI
|
|
run: |
|
|
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
|
unzip -q awscliv2.zip
|
|
sudo ./aws/install
|
|
|
|
- name: Upload Terraform Plan to MinIO
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
MINIO_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
|
run: |
|
|
# Upload plan files to MinIO
|
|
PLAN_PATH="terraform-plans/${{ github.repository }}/${{ github.run_number }}"
|
|
aws s3 cp tfplan "s3://${MINIO_BUCKET}/${PLAN_PATH}/tfplan" \
|
|
--endpoint-url="${MINIO_ENDPOINT}"
|
|
aws s3 cp tfplan.txt "s3://${MINIO_BUCKET}/${PLAN_PATH}/tfplan.txt" \
|
|
--endpoint-url="${MINIO_ENDPOINT}"
|
|
|
|
echo "Plan uploaded to: s3://${MINIO_BUCKET}/${PLAN_PATH}/"
|
|
|
|
terraform-apply:
|
|
name: Terraform Apply
|
|
runs-on: ubuntu-latest
|
|
needs: terraform-plan
|
|
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
environment:
|
|
name: production
|
|
steps:
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
with:
|
|
terraform_version: latest
|
|
|
|
- name: Setup Vault CLI
|
|
run: |
|
|
wget -O vault.zip https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
|
|
unzip vault.zip
|
|
sudo mv vault /usr/local/bin/
|
|
vault --version
|
|
|
|
- name: Setup SSH Key for Docker Provider
|
|
env:
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
VAULT_ROLE_ID: ${{ secrets.VAULT_ROLE_ID }}
|
|
VAULT_SECRET_ID: ${{ secrets.VAULT_SECRET_ID }}
|
|
run: |
|
|
chmod +x setup-ssh.sh
|
|
./setup-ssh.sh
|
|
|
|
- name: Install AWS CLI
|
|
run: |
|
|
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
|
unzip -q awscliv2.zip
|
|
sudo ./aws/install
|
|
|
|
- name: Terraform Init
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_BACKEND_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
TF_BACKEND_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
|
TF_BACKEND_KEY: docker/renovate/terraform.tfstate
|
|
TF_BACKEND_REGION: "main"
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
terraform init \
|
|
-backend-config="endpoint=${TF_BACKEND_ENDPOINT}" \
|
|
-backend-config="bucket=${TF_BACKEND_BUCKET}" \
|
|
-backend-config="key=${TF_BACKEND_KEY}" \
|
|
-backend-config="region=${TF_BACKEND_REGION}" \
|
|
-backend-config="skip_credentials_validation=true" \
|
|
-backend-config="skip_metadata_api_check=true" \
|
|
-backend-config="skip_requesting_account_id=true" \
|
|
-backend-config="skip_region_validation=true" \
|
|
-backend-config="use_path_style=true"
|
|
|
|
- name: Download Terraform Plan from MinIO
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
MINIO_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
|
run: |
|
|
PLAN_PATH="terraform-plans/${{ github.repository }}/${{ github.run_number }}"
|
|
aws s3 cp "s3://${MINIO_BUCKET}/${PLAN_PATH}/tfplan" tfplan \
|
|
--endpoint-url="${MINIO_ENDPOINT}"
|
|
echo "Plan downloaded from: s3://${MINIO_BUCKET}/${PLAN_PATH}/tfplan"
|
|
|
|
- name: Terraform Apply
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: terraform apply -input=false -auto-approve tfplan
|
|
|
|
terraform-destroy:
|
|
name: Terraform Destroy
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'destroy')
|
|
environment:
|
|
name: destroy-approval
|
|
steps:
|
|
- name: Verify Destroy Authorization
|
|
run: |
|
|
echo "⚠️ CRITICAL: INFRASTRUCTURE DESTRUCTION REQUESTED"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "PR: ${{ github.event.pull_request.html_url }}"
|
|
echo "Requested by: ${{ github.actor }}"
|
|
echo "Repository: ${{ github.repository }}"
|
|
echo "Branch: ${{ github.head_ref }}"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "This action will PERMANENTLY DESTROY the Renovate container"
|
|
echo "managed by this Terraform configuration."
|
|
echo ""
|
|
echo "Waiting for manual approval via environment protection rules..."
|
|
|
|
- name: Checking out
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Terraform
|
|
uses: hashicorp/setup-terraform@v3
|
|
with:
|
|
terraform_version: latest
|
|
|
|
- name: Setup Vault CLI
|
|
run: |
|
|
wget -O vault.zip https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
|
|
unzip vault.zip
|
|
sudo mv vault /usr/local/bin/
|
|
vault --version
|
|
|
|
- name: Setup SSH Key for Docker Provider
|
|
env:
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
VAULT_ROLE_ID: ${{ secrets.VAULT_ROLE_ID }}
|
|
VAULT_SECRET_ID: ${{ secrets.VAULT_SECRET_ID }}
|
|
run: |
|
|
chmod +x setup-ssh.sh
|
|
./setup-ssh.sh
|
|
|
|
- name: Terraform Init (Fresh - No Cache)
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_BACKEND_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
TF_BACKEND_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
|
TF_BACKEND_KEY: docker/renovate/terraform.tfstate
|
|
TF_BACKEND_REGION: "main"
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
echo "Performing fresh terraform init (no cache for safety)..."
|
|
terraform init \
|
|
-backend-config="endpoint=${TF_BACKEND_ENDPOINT}" \
|
|
-backend-config="bucket=${TF_BACKEND_BUCKET}" \
|
|
-backend-config="key=${TF_BACKEND_KEY}" \
|
|
-backend-config="region=${TF_BACKEND_REGION}" \
|
|
-backend-config="skip_credentials_validation=true" \
|
|
-backend-config="skip_metadata_api_check=true" \
|
|
-backend-config="skip_requesting_account_id=true" \
|
|
-backend-config="skip_region_validation=true" \
|
|
-backend-config="use_path_style=true"
|
|
|
|
- name: Terraform Destroy Plan
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
echo "Generating destroy plan..."
|
|
terraform plan -input=false -destroy -out=destroy.tfplan
|
|
echo ""
|
|
echo "Destroy plan generated. Review the plan above carefully."
|
|
|
|
- name: Terraform Destroy Execute
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
TF_VAR_role_id: ${{ secrets.VAULT_ROLE_ID }}
|
|
TF_VAR_secret_id: ${{ secrets.VAULT_SECRET_ID }}
|
|
#TF_VAR_renovate_endpoint: ${{ secrets.RENOVATE_ENDPOINT }}
|
|
#TF_VAR_renovate_token: ${{ secrets.RENOVATE_TOKEN }}
|
|
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
|
|
run: |
|
|
echo "🔥 DESTROYING INFRASTRUCTURE..."
|
|
echo "This cannot be undone!"
|
|
echo ""
|
|
terraform apply -input=false -auto-approve destroy.tfplan
|
|
echo ""
|
|
echo "✅ Renovate container has been destroyed"
|
|
echo "State file updated in MinIO: docker/renovate/terraform.tfstate"
|