Skip to content

Add a guide for doing assumable identities on Azure (#3328) #520

Add a guide for doing assumable identities on Azure (#3328)

Add a guide for doing assumable identities on Azure (#3328) #520

Workflow file for this run

name: Compile Documentation Bundle (Secure)
on:
push:
branches: [ main ]
paths:
- 'content/**'
- 'scripts/compile_docs.py'
- 'scripts/compile_docs_secure.py'
schedule:
- cron: '0 2 * * 0' # Weekly on Sundays at 2 AM
workflow_dispatch:
inputs:
create_release:
description: 'Create a GitHub release with signed artifacts'
required: false
default: 'false'
permissions:
contents: write # For creating/updating releases
actions: read
id-token: write # For cosign keyless signing
packages: write # For GHCR
# TODO: Split into separate compile (read-only) and publish (write) jobs
jobs:
compile-docs:
if: github.repository == 'chainguard-dev/edu'
runs-on: ubuntu-latest
environment: documentation # Use environment protection rules
steps:
- name: Harden the runner
uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
with:
egress-policy: block
allowed-endpoints: >
api.github.com:443
*.r2.cloudflarestorage.com:443
apk.cgr.dev:443
cgr.dev:443
files.pythonhosted.org:443
fulcio.sigstore.dev:443
ghcr.io:443
github.com:443
objects.githubusercontent.com:443
pypi.org:443
raw.githubusercontent.com:443
release-assets.githubusercontent.com:443
rekor.sigstore.dev:443
timestamp.sigstore.dev:443
tuf-repo-cdn.sigstore.dev:443
uploads.github.com:443
- name: Checkout edu repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: edu
persist-credentials: false # Don't persist auth token
- name: Create placeholder directories for compilation
run: |
# Create empty directories for future repos (will be populated when credentials are added)
mkdir -p courses
mkdir -p images-private
echo "# Placeholder" > courses/README.md
echo "# Placeholder" > images-private/README.md
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.10'
- name: Cache Python dependencies
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
- name: Validate repositories
run: |
# Verify we have the expected repositories
for repo in edu courses images-private; do
if [ ! -d "$repo" ]; then
echo "Error: Expected repository $repo not found"
exit 1
fi
done
# Check for suspicious files
find . -name "*.sh" -o -name "*.py" | grep -v -E "(compile_docs\.py|create_compressed_docs\.sh)" | while read file; do
echo "Warning: Unexpected script found: $file"
done
- name: Run security scan on Python script
run: |
cd edu
# Install security tools
pip install bandit==1.9.4 safety==3.7.0
# Scan for security issues
bandit -r scripts/compile_docs.py -f json -o bandit-report.json || true
# Check for critical issues
if [ -f bandit-report.json ]; then
critical_issues=$(python -c "import json; data=json.load(open('bandit-report.json')); print(len([i for i in data.get('results', []) if i.get('issue_severity') == 'HIGH']))")
if [ "$critical_issues" -gt 0 ]; then
echo "Critical security issues found in compile_docs.py"
cat bandit-report.json
exit 1
fi
fi
- name: Set environment variable for GitHub Actions
run: echo "GITHUB_ACTIONS=true" >> $GITHUB_ENV
- name: Create temporary directory
run: echo "TEMP_BUILD_DIR=$(mktemp -d)" >> $GITHUB_ENV
- name: Compile documentation with resource limits
run: |
cd edu
# Create output directory
mkdir -p $TEMP_BUILD_DIR
# Run with timeout and memory limits, output to temp directory
timeout 600 python3 scripts/compile_docs.py --output $TEMP_BUILD_DIR/chainguard-complete-docs.md
# Verify output file size (max 50MB uncompressed)
if [ -f $TEMP_BUILD_DIR/chainguard-complete-docs.md ]; then
size=$(stat -c%s $TEMP_BUILD_DIR/chainguard-complete-docs.md)
if [ $size -gt 52428800 ]; then
echo "Error: Compiled documentation exceeds 50MB limit"
exit 1
fi
fi
- name: Generate image catalog
env:
COMMIT_SHA: ${{ github.sha }}
run: |
cd edu
python3 scripts/generate_image_catalog.py \
--docs "$TEMP_BUILD_DIR/chainguard-complete-docs.md" \
--mappings data/package-mappings.yaml \
--output scripts/image-catalog.json \
--commit "$COMMIT_SHA"
- name: Create compressed versions
run: |
cd $TEMP_BUILD_DIR
# Create compressed versions with integrity checks
gzip -k -9 chainguard-complete-docs.md
zip -9 chainguard-complete-docs.zip chainguard-complete-docs.md
tar -czf chainguard-complete-docs.tar.gz chainguard-complete-docs.md
# Generate checksums
sha256sum chainguard-complete-docs.* > checksums.txt
# Verify compressed files
gzip -t chainguard-complete-docs.md.gz
unzip -t chainguard-complete-docs.zip > /dev/null
tar -tzf chainguard-complete-docs.tar.gz > /dev/null
- name: Install cosign
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
- name: Sign documentation with cosign
run: |
cd $TEMP_BUILD_DIR
# Sign the main documentation file (bundle format for cosign v3)
cosign sign-blob chainguard-complete-docs.md \
--yes \
--bundle=chainguard-complete-docs.md.bundle
# Sign the checksums file (bundle format for cosign v3)
cosign sign-blob checksums.txt \
--yes \
--bundle=checksums.txt.bundle
# Copy verification script
cp $GITHUB_WORKSPACE/edu/scripts/verification.sh .
# Create release bundle with all verification files
tar -czf chainguard-ai-docs.tar.gz \
chainguard-complete-docs.md \
chainguard-complete-docs.md.bundle \
checksums.txt \
checksums.txt.bundle \
verification.sh
# Sign the bundle (bundle format for cosign v3)
cosign sign-blob chainguard-ai-docs.tar.gz \
--yes \
--bundle=chainguard-ai-docs.tar.gz.bundle
- name: Login to GHCR
if: github.ref == 'refs/heads/main'
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push container image
if: github.ref == 'refs/heads/main'
env:
REPO_OWNER: ${{ github.repository_owner }}
COMMIT_SHA: ${{ github.sha }}
run: |
cd edu
# Copy necessary files for container build (rename to match Dockerfile expectations)
cp "$TEMP_BUILD_DIR/chainguard-complete-docs.md" scripts/chainguard-ai-docs.md
cp "$TEMP_BUILD_DIR/checksums.txt" scripts/checksums.txt
# verification.sh is already in scripts/ directory
# Build container with GitHub Container Registry
docker build -f scripts/Dockerfile.ai-docs -t "ghcr.io/$REPO_OWNER/ai-docs:latest" scripts/
docker tag "ghcr.io/$REPO_OWNER/ai-docs:latest" "ghcr.io/$REPO_OWNER/ai-docs:$COMMIT_SHA"
# Push images and capture digest for signing
DIGEST=$(docker push "ghcr.io/$REPO_OWNER/ai-docs:latest" | grep -oP 'sha256:[a-f0-9]+')
if [ -z "$DIGEST" ]; then
echo "ERROR: Failed to capture image digest from docker push"
exit 1
fi
docker push "ghcr.io/$REPO_OWNER/ai-docs:$COMMIT_SHA"
# Sign container image by immutable digest
cosign sign --yes "ghcr.io/$REPO_OWNER/ai-docs@$DIGEST"
- name: Scan for sensitive data
run: |
cd edu
# Create a custom gitleaks config to exclude false positives from documentation
cat > .gitleaks.toml << 'EOF'
title = "Gitleaks config for documentation scanning"
[allowlist]
description = "Allowlisted patterns for documentation"
paths = [
'''.*\.md$'''
]
regexes = [
'''`-----BEGIN PRIVATE KEY-----`''',
'''GitHub tokens \(`ghp_`, `ghs_`\)''',
'''id_ed25519\.pub''',
'''\[REDACTED\]''',
'''Example patterns we redact''',
'''-----BEGIN PRIVATE KEY-----'''
]
EOF
# Install gitleaks (with checksum verification)
wget -q https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz
echo "6e19050a3ee0688265ed3be4c46a0362487d20456ecd547e8c7328eaed3980cb gitleaks_8.18.0_linux_x64.tar.gz" | sha256sum -c -
tar -xzf gitleaks_8.18.0_linux_x64.tar.gz
# Scan compiled documentation for secrets with custom config
./gitleaks detect --no-git --source $TEMP_BUILD_DIR/ --config .gitleaks.toml --verbose --report-format json --report-path gitleaks-report.json || true
# Check results - parse JSON to see if there are actual findings
if [ -f gitleaks-report.json ]; then
# Check if JSON array is not empty (more than just "[]")
findings_count=$(cat gitleaks-report.json | grep -o '"Description":' | wc -l)
if [ "$findings_count" -gt 0 ]; then
echo "Potential secrets detected in compiled documentation!"
cat gitleaks-report.json
# Double-check if these are real secrets or just documentation examples
if grep -q "Example patterns we redact" gitleaks-report.json; then
echo "Note: These appear to be documentation examples, not actual secrets"
else
exit 1
fi
else
echo "No secrets detected in compiled documentation"
fi
fi