Our compliance team was manually screenshotting Vanta evidence and pasting it into Confluence for auditor access. This created version drift and was, frankly, a waste of engineering-adjacent time. I've automated it.
The core is a Python script that leverages Vanta's GraphQL API to fetch evidence items and their associated resources (screenshots, PDFs). It then formats this data and uses the Confluence REST API to create or update pages in a structured hierarchy.
Key components of the workflow:
* A scheduled Jenkins pipeline (could be GitHub Actions) runs the script weekly.
* It authenticates with both Vanta and Confluence using secrets stored in our vault.
* For each evidence item, it generates a consistent page title and summary table.
* Attachments are downloaded and uploaded to Confluence as page attachments.
Here's the basic script structure:
```python
import requests
import base64
# GraphQL query to fetch evidence with file URLs
EVIDENCE_QUERY = """
query GetEvidence($limit: Int) {
vantaEvidenceItems(limit: $limit) {
id
title
collectedAt
status
files {
fileName
url
}
resource {
name
}
}
}
"""
def fetch_vanta_evidence(api_key):
headers = {'Authorization': f'Bearer {api_key}'}
response = requests.post('https://api.vanta.com/graphql',
json={'query': EVIDENCE_QUERY, 'variables': {'limit': 50}},
headers=headers)
return response.json()['data']['vantaEvidenceItems']
# ... Confluence page creation logic follows ...
```
The Jenkinsfile uses a `cron` trigger and stores the artifacts (log files) for audit:
```groovy
pipeline {
agent any
triggers { cron('H 2 * * 0') } // Weekly Sunday at 2 AM
stages {
stage('Pull & Push Evidence') {
steps {
script {
withCredentials([string(credentialsId: 'vanta-api-key', variable: 'VANTA_KEY')]) {
sh 'python3 vanta_confluence_sync.py --key $VANTA_KEY'
}
}
}
}
}
}
```
Results: A single source of truth for auditors, reduced manual overhead by ~5 hours/month, and traceable logs of each sync. The main pitfall was handling pagination for large evidence sets and rate limiting on the Confluence uploads, which required adding jitter between requests.
--crusader
Commit early, deploy often, but always rollback-ready.