Skip to content

FinOps Scan

FinOps Scan #7

Workflow file for this run

name: FinOps Scan
on:
schedule:
- cron: '0 6 * * 1' # Weekly Monday 06:00 UTC
workflow_dispatch:
permissions:
contents: read
security-events: write
id-token: write
jobs:
psrule-scan:
runs-on: ubuntu-latest
strategy:
matrix:
app: ['001', '002', '003', '004', '005']
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: devopsabcs-engineering/finops-demo-app-${{ matrix.app }}
token: ${{ secrets.ORG_ADMIN_TOKEN }}
path: target-app
- name: Run PSRule
uses: microsoft/ps-rule@v2.9.0
with:
inputPath: target-app/infra/
modules: PSRule.Rules.Azure
outputFormat: Sarif
outputPath: reports/psrule-${{ matrix.app }}.sarif
option: src/config/ps-rule.yaml
baseline: Azure.GA_2024_12
continue-on-error: true
- uses: actions/upload-artifact@v4
with:
name: sarif-psrule-${{ matrix.app }}
path: reports/psrule-${{ matrix.app }}.sarif
checkov-scan:
runs-on: ubuntu-latest
strategy:
matrix:
app: ['001', '002', '003', '004', '005']
steps:
- uses: actions/checkout@v4
with:
repository: devopsabcs-engineering/finops-demo-app-${{ matrix.app }}
token: ${{ secrets.ORG_ADMIN_TOKEN }}
- name: Run Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: infra/
output_format: sarif
output_file_path: reports/
soft_fail: true
- uses: actions/upload-artifact@v4
with:
name: sarif-checkov-${{ matrix.app }}
path: reports/results_sarif.sarif
custodian-scan:
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
app: ['001', '002', '003', '004', '005']
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Install Cloud Custodian
run: pip install c7n c7n-azure
- name: Run Cloud Custodian
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
run: |
mkdir -p output reports
# Run each policy file individually
# Cloud Custodian filters resources at query time, so we rely on
# the policy filters already defined in the YAML files.
# The subscription-level scan will find resources across all RGs,
# and the cross-repo-upload job routes results to the correct repo.
for policy_file in src/config/custodian/*.yml; do
echo "Running: $(basename $policy_file)"
custodian run -s output/ "$policy_file" --cache-period 0 2>&1 || true
done
# List what was found
echo "=== Custodian output ==="
find output/ -name "resources.json" -exec sh -c 'echo " $(dirname {} | xargs basename): $(cat {} | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0) resources"' \;
echo "Custodian scan complete for app ${{ matrix.app }}"
- name: Convert to SARIF
run: |
mkdir -p reports
if [ -d "output/" ] && [ "$(ls -A output/)" ]; then
python src/converters/custodian-to-sarif.py output/ reports/custodian-${{ matrix.app }}.sarif
else
echo "No custodian output to convert, creating empty SARIF"
echo '{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json","runs":[{"tool":{"driver":{"name":"custodian-to-sarif","version":"1.0.0","informationUri":"https://cloudcustodian.io","rules":[]}},"results":[]}]}' > reports/custodian-${{ matrix.app }}.sarif
fi
- uses: actions/upload-artifact@v4
with:
name: sarif-custodian-${{ matrix.app }}
path: reports/custodian-${{ matrix.app }}.sarif
cross-repo-upload:
needs: [psrule-scan, checkov-scan, custodian-scan]
if: always() && (needs.psrule-scan.result == 'success' || needs.checkov-scan.result == 'success')
runs-on: ubuntu-latest
strategy:
matrix:
app: ['001', '002', '003', '004', '005']
steps:
- uses: actions/download-artifact@v4
with:
pattern: sarif-*-${{ matrix.app }}
merge-multiple: true
path: reports/
- name: Upload SARIF to target repo
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
run: |
for sarif_file in reports/*.sarif; do
if [ ! -f "$sarif_file" ]; then continue; fi
SARIF_CONTENT=$(gzip -c "$sarif_file" | base64 -w0)
COMMIT_SHA=$(gh api repos/devopsabcs-engineering/finops-demo-app-${{ matrix.app }}/commits/main --jq '.sha')
gh api \
--method POST \
repos/devopsabcs-engineering/finops-demo-app-${{ matrix.app }}/code-scanning/sarifs \
-f "commit_sha=$COMMIT_SHA" \
-f "ref=refs/heads/main" \
-f "sarif=$SARIF_CONTENT"
echo "Uploaded $(basename $sarif_file) to finops-demo-app-${{ matrix.app }}"
done