Skip to content

Rename duplicate resource group scripts with descriptive names #12

Rename duplicate resource group scripts with descriptive names

Rename duplicate resource group scripts with descriptive names #12

name: Infrastructure as Code Validation

Check failure on line 1 in .github/workflows/iac-validation.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/iac-validation.yml

Invalid workflow file

(Line: 43, Col: 11): Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.AZURE_CREDENTIALS != '', (Line: 105, Col: 11): Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.AZURE_CREDENTIALS != ''
on:
push:
paths:
- 'iac/**'
- '.github/workflows/iac-validation.yml'
pull_request:
paths:
- 'iac/**'
- '.github/workflows/iac-validation.yml'
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
jobs:
bicep-validation:
runs-on: ubuntu-latest
name: Validate Bicep Templates
continue-on-error: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bicep
continue-on-error: true
run: |
echo "Installing Bicep CLI..."
curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64
chmod +x ./bicep
sudo mv ./bicep /usr/local/bin/bicep
bicep --version || echo "Bicep installation optional for basic validation"
- name: Azure Login
continue-on-error: true
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
if: secrets.AZURE_CREDENTIALS != ''
- name: Lint Bicep templates
continue-on-error: true
run: |
echo "Linting Bicep templates (non-blocking)..."
if command -v bicep &> /dev/null; then
find bicep -name "*.bicep" -type f 2>/dev/null | while read -r template; do
echo "Linting: $template"
bicep build "$template" --outfile /dev/null || echo "Warning: $template has issues"
done
else
echo "Bicep CLI not available, skipping validation"
fi
- name: Validate main Bicep template
run: |
echo "Validating main Bicep template deployment..."
az deployment sub validate \
--location "East US" \
--template-file iac/bicep/main.bicep \
--parameters environment=dev adminPassword='TempP@ssw0rd123!' \
--output table
- name: Test Bicep deployment (What-If)
run: |
echo "Running Bicep What-If analysis..."
# Create temporary resource group for validation
TEMP_RG="bicep-validation-$(date +%s)"
az group create --name "$TEMP_RG" --location "East US" --tags Purpose=CI-Validation
# Run what-if deployment
az deployment group what-if \
--resource-group "$TEMP_RG" \
--template-file iac/bicep/main.bicep \
--parameters environment=dev adminPassword='TempP@ssw0rd123!' \
--output table
# Cleanup
az group delete --name "$TEMP_RG" --yes --no-wait
terraform-validation:
runs-on: ubuntu-latest
name: Validate Terraform Configuration
continue-on-error: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
continue-on-error: true
uses: hashicorp/setup-terraform@v3
with:
terraform_version: '1.5.0'
- name: Azure Login
continue-on-error: true
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
if: secrets.AZURE_CREDENTIALS != ''
- name: Terraform Format Check
working-directory: iac/terraform
run: |
echo "Checking Terraform formatting..."
terraform fmt -check -recursive
if [ $? -ne 0 ]; then
echo "Terraform files are not properly formatted"
echo "Run 'terraform fmt -recursive' to fix formatting"
exit 1
fi
- name: Terraform Init
working-directory: iac/terraform
run: |
echo "Initializing Terraform..."
terraform init -input=false
- name: Terraform Validate
working-directory: iac/terraform
run: |
echo "Validating Terraform configuration..."
terraform validate
- name: Terraform Plan
working-directory: iac/terraform
run: |
echo "Running Terraform plan..."
# Create terraform.tfvars for validation
cat > terraform.tfvars << EOF
environment = "dev"
location = "East US"
admin_password = "TempP@ssw0rd123!"
deploy_advanced = false
EOF
# Run plan
terraform plan -var-file="terraform.tfvars" -input=false -out=tfplan
# Display plan summary
terraform show -json tfplan | jq -r '.planned_values.root_module.resources[].address' | sort
- name: Upload Terraform Plan
uses: actions/upload-artifact@v4
with:
name: terraform-plan
path: iac/terraform/tfplan
retention-days: 5
security-scan:
runs-on: ubuntu-latest
name: Security Scan IaC Templates
continue-on-error: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Checkov security scan
continue-on-error: true
uses: bridgecrewio/checkov-action@master
with:
directory: bicep/
framework: arm
output_format: sarif
output_file_path: checkov-results.sarif
quiet: true
soft_fail: true
- name: Upload Checkov results to GitHub Security
continue-on-error: true
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: checkov-results.sarif
- name: Run TFSec security scan
continue-on-error: true
uses: aquasecurity/tfsec-action@v1.0.3
with:
working_directory: terraform/
soft_fail: true
format: sarif
output: tfsec-results.sarif
if: hashFiles('terraform/**/*.tf') != ''
- name: Upload TFSec results
continue-on-error: true
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: tfsec-results.sarif
cost-estimation:
runs-on: ubuntu-latest
name: Infrastructure Cost Estimation
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: '1.5.0'
- name: Setup Infracost
uses: infracost/actions/setup@v2
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Generate Infracost cost estimate
working-directory: iac/terraform
run: |
# Create terraform.tfvars for cost estimation
cat > terraform.tfvars << EOF
environment = "prod"
location = "East US"
admin_password = "TempP@ssw0rd123!"
deploy_advanced = true
EOF
# Initialize Terraform
terraform init -input=false
# Generate cost estimate
infracost breakdown --path . \
--format json \
--out-file /tmp/infracost.json \
--terraform-var-file terraform.tfvars
- name: Post Infracost comment
uses: infracost/actions/comment@v1
with:
path: /tmp/infracost.json
behavior: update
documentation-check:
runs-on: ubuntu-latest
name: Documentation Validation
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check Terraform documentation
run: |
echo "Checking Terraform module documentation..."
# Check if README exists for each module
for module_dir in iac/terraform/modules/*/; do
module_name=$(basename "$module_dir")
if [ ! -f "$module_dir/README.md" ]; then
echo "Warning: Missing README.md in $module_name module"
fi
# Check if all variables have descriptions
if [ -f "$module_dir/variables.tf" ]; then
if grep -q 'description.*=""' "$module_dir/variables.tf"; then
echo "Error: Empty descriptions found in $module_name variables"
exit 1
fi
fi
done
- name: Check Bicep documentation
run: |
echo "Checking Bicep module documentation..."
# Check parameter descriptions
find iac/bicep/modules -name "*.bicep" | while read -r bicep_file; do
if grep -q '@description.*""' "$bicep_file"; then
echo "Error: Empty descriptions found in $(basename "$bicep_file")"
exit 1
fi
done
drift-detection:
runs-on: ubuntu-latest
name: Infrastructure Drift Detection
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: '1.5.0'
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Terraform Drift Check
working-directory: iac/terraform
run: |
echo "Checking for infrastructure drift..."
# Initialize Terraform with backend
terraform init -input=false \
-backend-config="resource_group_name=${{ secrets.TF_STATE_RESOURCE_GROUP }}" \
-backend-config="storage_account_name=${{ secrets.TF_STATE_STORAGE_ACCOUNT }}" \
-backend-config="container_name=tfstate" \
-backend-config="key=terraform.tfstate"
# Run plan to detect drift
terraform plan -detailed-exitcode -input=false -no-color > drift-report.txt
PLAN_EXIT_CODE=$?
if [ $PLAN_EXIT_CODE -eq 1 ]; then
echo "Terraform plan failed"
cat drift-report.txt
exit 1
elif [ $PLAN_EXIT_CODE -eq 2 ]; then
echo "Infrastructure drift detected!"
cat drift-report.txt
# Create GitHub issue for drift
gh issue create \
--title "Infrastructure Drift Detected - $(date +%Y-%m-%d)" \
--body "$(cat drift-report.txt)" \
--label "infrastructure,drift" \
--assignee "${{ github.actor }}"
else
echo "No infrastructure drift detected"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload drift report
uses: actions/upload-artifact@v4
if: always()
with:
name: drift-report
path: iac/terraform/drift-report.txt
retention-days: 30
validation-summary:
runs-on: ubuntu-latest
name: Validation Summary
needs: [bicep-validation, terraform-validation, security-scan, documentation-check]
if: always()
steps:
- name: Validation Summary
run: |
echo "## Infrastructure as Code Validation Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Bicep Validation | ${{ needs.bicep-validation.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Terraform Validation | ${{ needs.terraform-validation.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Security Scan | ${{ needs.security-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Documentation Check | ${{ needs.documentation-check.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.bicep-validation.result }}" == "success" &&
"${{ needs.terraform-validation.result }}" == "success" &&
"${{ needs.security-scan.result }}" == "success" &&
"${{ needs.documentation-check.result }}" == "success" ]]; then
echo "✅ All IaC validation checks passed!" >> $GITHUB_STEP_SUMMARY
else
echo "❌ Some IaC validation checks failed. Please review the logs above." >> $GITHUB_STEP_SUMMARY
fi