Open-agreements iso-27001-evidence-collection
git clone https://github.com/open-agreements/open-agreements
T=$(mktemp -d) && git clone --depth=1 https://github.com/open-agreements/open-agreements "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/iso-27001-evidence-collection" ~/.claude/skills/open-agreements-open-agreements-iso-27001-evidence-collection && rm -rf "$T"
skills/iso-27001-evidence-collection/SKILL.mdISO 27001 Evidence Collection
Systematically collect audit evidence for ISO 27001:2022 and SOC 2. This skill provides API-first evidence collection commands, organizes evidence by control, and validates completeness before auditor review.
Security Model
- No scripts executed — this skill is markdown-only procedural guidance
- No secrets required — works with reference checklists; CLI commands use existing local credentials
- Evidence stays local — all outputs go to the local filesystem
- IP-clean — references NIST SP 800-53 (public domain); ISO controls cited by section ID only
When to Use
Activate this skill when:
- Preparing evidence package for external audit — 2-4 weeks before auditor arrives
- Quarterly evidence refresh — update evidence that has aged beyond the audit window
- After remediation — collect evidence proving a finding has been fixed
- New system onboarding — establish baseline evidence for a newly in-scope system
- Evidence gap analysis — identify what's missing before the audit
Do NOT use for:
- Running the internal audit itself — use
iso-27001-internal-audit - SOC 2-only readiness assessment — use
soc2-readiness - Interpreting audit findings — use the internal audit skill
Core Concepts
Evidence Hierarchy (Best to Worst)
| Rank | Type | Example | Why Better |
|---|---|---|---|
| 1 | API export (JSON/CSV) | | Timestamped, tamper-evident, reproducible |
| 2 | System-generated report | SOC 2 report from vendor, SIEM export | Authoritative source, includes metadata |
| 3 | Configuration export | Terraform state, policy JSON | Shows intended state, version-controlled |
| 4 | Screenshot with system clock | | Visual proof, but harder to validate |
| 5 | Manual attestation | Signed statement by responsible person | Last resort, requires corroboration |
Evidence Freshness Requirements
| Evidence Type | Max Age | Refresh Cadence |
|---|---|---|
| Access lists | 90 days | Quarterly |
| Vulnerability scans | 30 days | Monthly |
| Configuration exports | 90 days | Quarterly |
| Training records | 12 months | Annual |
| Penetration test | 12 months | Annual |
| Policy documents | 12 months | Annual review |
| Incident records | Audit period | Continuous |
| Risk assessment | 12 months | Annual + on change |
Evidence Naming Convention
{control_id}_{evidence_type}_{YYYY-MM-DD}.{ext}
Examples:
A.5.15_user-access-list_2026-02-28.jsonA.8.8_vulnerability-scan_2026-02-28.csvA.8.13_backup-test-results_2026-02-28.pdf
Step-by-Step Workflow
Step 1: Identify Evidence Gaps
Determine what evidence is missing or stale.
# If Internal ISO Audit MCP server is available: search_guidance(query="evidence", domain="organizational") # Find controls needing evidence list_controls(domain="technological") # List all tech controls to assess gaps get_control_guidance(control_id="A.5.15") # Get evidence requirements for a specific control # If reading local compliance data: # Check compliance/evidence/*.md files for upload_status != "OK" # Check renewal_next dates for upcoming expirations
Step 2: Prioritize Collection
Order evidence collection by:
- Missing evidence for Critical-tier controls — audit blockers
- Stale evidence past renewal date — auditor will reject
- Evidence for Relevant-tier controls — expected but not blocking
- Checkbox-tier evidence — policies and attestations
Step 3: Collect by Platform
Run evidence collection commands grouped by platform to minimize context-switching.
GitHub Evidence
# Org settings: MFA requirement, default permissions gh api orgs/{org} | jq '{ two_factor_requirement_enabled, default_repository_permission, members_can_create_public_repositories }' > evidence/A.5.17_github-org-mfa_$(date +%Y-%m-%d).json # Branch protection on production repos for repo in $(gh repo list {org} --json name -q '.[].name'); do gh api repos/{org}/$repo/branches/main/protection 2>/dev/null | \ jq '{repo: "'$repo'", protection: .}' >> evidence/A.8.32_branch-protection_$(date +%Y-%m-%d).json done # Recent merged PRs (change management evidence) gh pr list --state merged --limit 50 --json number,title,author,reviewDecision,mergedAt,mergedBy \ > evidence/A.8.32_change-records_$(date +%Y-%m-%d).json # Dependabot alerts (vulnerability management) gh api repos/{org}/{repo}/dependabot/alerts?state=open \ > evidence/A.8.8_dependabot-alerts_$(date +%Y-%m-%d).json # Secret scanning alerts gh api orgs/{org}/secret-scanning/alerts --paginate \ > evidence/A.8.24_secret-scanning_$(date +%Y-%m-%d).json # Audit log gh api orgs/{org}/audit-log?per_page=100 \ > evidence/A.8.15_github-audit-log_$(date +%Y-%m-%d).json
GCP Evidence
# IAM policy (access control) gcloud projects get-iam-policy {project} --format=json \ > evidence/A.5.15_gcp-iam-policy_$(date +%Y-%m-%d).json # Service accounts gcloud iam service-accounts list --format=json \ > evidence/A.5.16_gcp-service-accounts_$(date +%Y-%m-%d).json # Audit logging config gcloud projects get-iam-policy {project} --format=json | jq '.auditConfigs' \ > evidence/A.8.15_gcp-audit-config_$(date +%Y-%m-%d).json # Log sinks (centralization) gcloud logging sinks list --format=json \ > evidence/A.8.15_gcp-log-sinks_$(date +%Y-%m-%d).json # Compute instances (asset inventory) gcloud compute instances list --format=json \ > evidence/A.5.9_gcp-compute-inventory_$(date +%Y-%m-%d).json # Cloud SQL backup config gcloud sql backups list --instance={instance} --format=json \ > evidence/A.8.13_gcp-sql-backups_$(date +%Y-%m-%d).json # Firewall rules gcloud compute firewall-rules list --format=json \ > evidence/A.8.20_gcp-firewall-rules_$(date +%Y-%m-%d).json
Azure Evidence
# Role assignments (access control) az role assignment list --all --output json \ > evidence/A.5.15_azure-role-assignments_$(date +%Y-%m-%d).json # Activity log (audit trail) az monitor activity-log list --max-events 100 --output json \ > evidence/A.8.15_azure-activity-log_$(date +%Y-%m-%d).json # Network security groups az network nsg list --output json \ > evidence/A.8.20_azure-nsgs_$(date +%Y-%m-%d).json # Backup jobs az backup job list --resource-group {rg} --vault-name {vault} --output json \ > evidence/A.8.13_azure-backup-jobs_$(date +%Y-%m-%d).json # Storage encryption az storage account list --query "[].{name:name, encryption:encryption}" --output json \ > evidence/A.8.24_azure-storage-encryption_$(date +%Y-%m-%d).json
Google Workspace Evidence
# User list with MFA status gam print users fields primaryEmail,name,isEnrolledIn2Sv,isEnforcedIn2Sv,lastLoginTime,suspended \ > evidence/A.5.17_workspace-users-mfa_$(date +%Y-%m-%d).csv # Admin roles gam print admins > evidence/A.8.2_workspace-admins_$(date +%Y-%m-%d).csv # Mobile devices gam print mobile > evidence/A.8.1_workspace-mobile-devices_$(date +%Y-%m-%d).csv
macOS Endpoint Evidence
# FileVault encryption fdesetup status > evidence/A.8.24_filevault-status_$(date +%Y-%m-%d).txt # System configuration system_profiler SPHardwareDataType SPSoftwareDataType \ > evidence/A.8.1_endpoint-config_$(date +%Y-%m-%d).txt # Screen lock settings profiles show -type configuration 2>/dev/null | grep -A10 -i "lock\|idle\|screensaver" \ > evidence/A.6.7_screenlock-config_$(date +%Y-%m-%d).txt
Step 4: Validate Evidence Package
Check completeness before submitting to auditor:
- Completeness: Do you have evidence for every applicable control in the SoA?
- Freshness: Is every piece of evidence within the required age?
- Format: Are API exports in JSON/CSV with timestamps? Screenshots have system clock visible?
- Naming: Files follow the naming convention?
- Coverage: Critical-tier controls have at least 2 forms of evidence?
# If Internal ISO Audit MCP server is available: list_controls() # Get all controls to verify evidence coverage get_control_guidance(control_id="A.8.8") # Check specific control's evidence expectations search_guidance(query="vulnerability scanning evidence") # Find controls related to specific evidence types
Step 5: Generate Evidence Index
Create an index file listing all evidence, mapped to controls:
# Evidence Package Index Generated: {date} Audit period: {start} to {end} | Control | Evidence File | Type | Collected | Status | |---------|--------------|------|-----------|--------| | A.5.15 | gcp-iam-policy_2026-02-28.json | API export | 2026-02-28 | Current | | A.5.17 | workspace-users-mfa_2026-02-28.csv | API export | 2026-02-28 | Current | | ... | ... | ... | ... | ... |
DO / DON'T
DO
- Use API exports with ISO 8601 timestamps over screenshots whenever possible
- Collect evidence from the SOURCE system (IdP, not a secondary report)
- Include metadata: collection date, system version, user who collected
- Store evidence in version-controlled directory with clear naming
- Collect evidence for the AUDIT PERIOD (usually past 12 months), not just current state
- Use
for screenshots (captures without shadow/border)screencapture -x ~/evidence/{filename}.png
DON'T
- Take screenshots without visible system clock (menu bar on macOS, taskbar on Windows)
- Collect evidence from sandbox/staging instead of production
- Manually edit evidence after collection (auditors may verify against source)
- Wait until the week before the audit to collect everything
- Assume stale evidence is acceptable — check freshness requirements above
- Mix evidence from different audit periods in the same file
Troubleshooting
| Problem | Solution |
|---|---|
| API command requires auth | Use existing local credentials: , , |
| Tool not installed | Install: , , |
| Insufficient permissions | Request read-only access to the relevant service; document the access request as evidence |
| Evidence too large | Use or flags; collect summary statistics instead of full export |
| Vendor won't provide SOC 2 report | Request via their trust center; if unavailable, document the request and use their security page |
| Screenshot doesn't include clock | On macOS: use full-screen capture, or which includes menu bar |
Rules
For detailed evidence collection guidance by topic:
| File | Coverage |
|---|---|
| CLI commands by cloud provider (GCP, Azure, AWS, GitHub, Google Workspace) |
| When and how to take audit-ready screenshots |
| Evidence type requirements per control domain |
Attribution
Evidence collection procedures and control guidance developed with Internal ISO Audit (Hazel Castro, ISO 27001 Lead Auditor, 14+ years, 100+ audits).
Runtime Detection
- Internal ISO Audit MCP server available (best) — Live control guidance lookup, NIST cross-reference, full-text search across all control evidence expectations. Server:
internalisoaudit.com/api/mcp - Local compliance data available (good) — Reads evidence status from
compliance/evidence/*.md - Reference only (baseline) — Uses embedded checklists and command reference in
rules/
Connectors
For Internal ISO Audit MCP server setup, see CONNECTORS.md.