diff --git a/.gitea/workflows/sonarqube.yaml b/.gitea/workflows/pipeline.yaml similarity index 78% rename from .gitea/workflows/sonarqube.yaml rename to .gitea/workflows/pipeline.yaml index 6f329e9..8fa9140 100644 --- a/.gitea/workflows/sonarqube.yaml +++ b/.gitea/workflows/pipeline.yaml @@ -98,7 +98,7 @@ jobs: run: terraform validate sonarqube: - name: SonarQube Trigger + name: SonarQube Scan runs-on: ubuntu-latest needs: terraform-validate steps: @@ -128,10 +128,30 @@ jobs: 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 }} @@ -139,10 +159,10 @@ jobs: VAULT_ADDR: ${{ secrets.VAULT_ADDR }} run: | terraform init -input=false \ - -backend-config="endpoints={s3=\"${{ secrets.MINIO_ENDPOINT }}\"}" \ - -backend-config="bucket=${{ secrets.MINIO_BUCKET }}" \ - -backend-config="key=docker/renovate/terraform.tfstate" \ - -backend-config="region=main" \ + -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" \ @@ -162,6 +182,12 @@ jobs: 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 }} @@ -169,11 +195,6 @@ jobs: MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }} MINIO_BUCKET: ${{ secrets.MINIO_BUCKET }} run: | - # Install AWS CLI for S3-compatible operations - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip -q awscliv2.zip - sudo ./aws/install - # Upload plan files to MinIO PLAN_PATH="terraform-plans/${{ github.repository }}/${{ github.run_number }}" aws s3 cp tfplan "s3://${MINIO_BUCKET}/${PLAN_PATH}/tfplan" \ @@ -201,6 +222,22 @@ jobs: 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" @@ -211,6 +248,10 @@ jobs: 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 }} @@ -218,10 +259,10 @@ jobs: VAULT_ADDR: ${{ secrets.VAULT_ADDR }} run: | terraform init \ - -backend-config="endpoints={s3=\"${{ secrets.MINIO_ENDPOINT }}\"}" \ - -backend-config="bucket=${{ secrets.MINIO_BUCKET }}" \ - -backend-config="key=docker/renovate/terraform.tfstate" \ - -backend-config="region=main" \ + -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" \ @@ -269,7 +310,7 @@ jobs: echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" echo "This action will PERMANENTLY DESTROY the Renovate container" - echo "and all associated resources managed by this Terraform configuration." + echo "managed by this Terraform configuration." echo "" echo "Waiting for manual approval via environment protection rules..." @@ -283,10 +324,30 @@ jobs: 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 }} @@ -295,10 +356,10 @@ jobs: run: | echo "Performing fresh terraform init (no cache for safety)..." terraform init \ - -backend-config="endpoints={s3=\"${{ secrets.MINIO_ENDPOINT }}\"}" \ - -backend-config="bucket=${{ secrets.MINIO_BUCKET }}" \ - -backend-config="key=docker/renovate/terraform.tfstate" \ - -backend-config="region=main" \ + -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" \ @@ -335,5 +396,5 @@ jobs: echo "" terraform apply -input=false -auto-approve destroy.tfplan echo "" - echo "✅ Renovate infrastructure has been destroyed" - echo "State file updated in MinIO" + echo "✅ Renovate container has been destroyed" + echo "State file updated in MinIO: docker/renovate/terraform.tfstate" diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 0000000..d3f18d6 --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,37 @@ +plugin "terraform" { + enabled = true + preset = "recommended" +} + +# Additional Terraform best practice rules +rule "terraform_deprecated_interpolation" { + enabled = true +} + +rule "terraform_documented_outputs" { + enabled = true +} + +rule "terraform_documented_variables" { + enabled = true +} + +rule "terraform_naming_convention" { + enabled = true +} + +rule "terraform_required_version" { + enabled = true +} + +rule "terraform_required_providers" { + enabled = true +} + +rule "terraform_unused_declarations" { + enabled = true +} + +rule "terraform_standard_module_structure" { + enabled = true +} diff --git a/provider.tf b/provider.tf index a500fb7..8da8d2a 100644 --- a/provider.tf +++ b/provider.tf @@ -31,12 +31,19 @@ provider "dns" { provider "docker" { host = "tcp://192.168.2.170:2376" - cert_path = pathexpand("~/.docker") + # Use cert_path only if certificates exist (local development) + # For CI/CD, use DOCKER_HOST environment variable instead + cert_path = fileexists(pathexpand("~/.docker/ca.pem")) ? pathexpand("~/.docker") : null } # Configure the Vault Provider provider "vault" { address = "https://wbyc-srv-docker01.bsdserver.lan:8200" + + # Skip TLS verification for self-signed certificates in CI/CD + # Set VAULT_SKIP_VERIFY=true environment variable in pipeline + skip_tls_verify = tobool(coalesce(try(var.vault_skip_tls_verify, null), false)) + auth_login { path = "auth/approle/login" parameters = { diff --git a/setup-ssh.sh b/setup-ssh.sh new file mode 100755 index 0000000..111f305 --- /dev/null +++ b/setup-ssh.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +# This script sets up the SSH key for Docker provider authentication +# It should be run before terraform init/plan/apply + +echo "Setting up SSH key for Docker provider..." + +# Skip TLS verification for self-signed certificates +export VAULT_SKIP_VERIFY=1 + +# Login to Vault using AppRole +echo "Authenticating to Vault with AppRole..." +VAULT_TOKEN=$(vault write -field=token auth/approle/login \ + role_id="${VAULT_ROLE_ID}" \ + secret_id="${VAULT_SECRET_ID}") +export VAULT_TOKEN + +# Create .ssh directory if it doesn't exist +mkdir -p .ssh + +# Fetch SSH private key from Vault and write to file +# Use -format=json to get raw value and preserve newlines +vault kv get -format=json secret/docker-ssh | jq -r '.data.data["private-key"]' > .ssh/id_rsa + +# Ensure the key ends with a newline +echo "" >> .ssh/id_rsa + +# Set correct permissions +chmod 600 .ssh/id_rsa + +echo "SSH key setup complete" +echo "Key file size: $(wc -c < .ssh/id_rsa) bytes" +echo "Key file lines: $(wc -l < .ssh/id_rsa) lines"