Documentation

Multi-Source Example

Production configuration collecting evidence from GitHub, AWS, and Google Workspace.

Use Case

Perfect for:

  • Production environments
  • Complete SOC 2 Type I compliance
  • Multiple evidence sources
  • Full control coverage (CC6.1, CC6.6, CC7.2)

Coverage: All 3 controls across 3 sources


What This Collects

ControlSourceEvidence
CC6.1GitHubOrganization 2FA enforcement
CC6.1AWSIAM password policy
CC6.1Google Workspace2-Step Verification enforcement
CC6.6GitHubCODEOWNERS files
CC6.6Google WorkspaceAdmin role assignments
CC7.2GitHubBranch protection rules
CC7.2AWSCloudTrail logging status

Total artifacts: ~9-12 files


Prerequisites

1. GitHub

  • Personal access token with repo:read, read:org scopes
  • Organization with 2FA enforced
  • Repositories with branch protection

2. AWS

  • IAM user with read-only permissions
  • Access key ID and secret access key
  • CloudTrail configured and logging

3. Google Workspace

  • Service account with domain-wide delegation
  • Required OAuth scopes authorized
  • 2-Step Verification enforced

Complete Configuration

evidence.yaml

# evidence.yaml - Production multi-source configuration

framework: soc2_type1

controls:
  - CC6.1  # Logical Access Controls
  - CC6.6  # Access Removal/Modification
  - CC7.2  # Change Management

sources:
  # GitHub: Code repository evidence
  github:
    mode: token
    token_env: GITHUB_TOKEN
    org: acme
    repos: '*'  # All repositories
    branch: main

  # AWS: Infrastructure evidence
  aws:
    mode: env
    region: us-east-1
    log_groups:
      - /aws/lambda/production-*
    cloudtrail:
      trails:
        - production-audit-trail

  # Google Workspace: Identity management evidence
  google_workspace:
    mode: service_account
    credentials_env: GOOGLE_APPLICATION_CREDENTIALS
    customer_id: C01234567
    admin_email: evidence-admin@acme.com
    domains:
      - acme.com

bundle:
  signing:
    private_key_path: /etc/evidence/keys/production.pem
    key_id: production-2026-01
  output_path: /var/evidence/bundles
  max_size_mb: 100
  naming_pattern: '{org}-{framework}-{timestamp}'

upload:
  enabled: true
  retention_days: 730  # 2 years
  tags:
    environment: production
    team: security
    compliance: soc2
  verify_before_upload: true

Environment Variables

Production Server

Create /etc/evidence/.env:

# GitHub
GITHUB_TOKEN=ghp_production_token_here

# AWS
AWS_ACCESS_KEY_ID=AKIA_production_key
AWS_SECRET_ACCESS_KEY=production_secret_key
AWS_REGION=us-east-1

# Google Workspace
GOOGLE_APPLICATION_CREDENTIALS=/etc/evidence/keys/google-service-account.json

# Evidence Platform
EVIDENCE_API_KEY=evd_api_production_key_here

Load before collection:

source /etc/evidence/.env
evidence collect

GitHub Actions (Alternative)

Use secrets for automated collection:

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  GOOGLE_APPLICATION_CREDENTIALS: /tmp/google-sa.json
  EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}

Setup Instructions

1. GitHub Setup

Create token:

  1. GitHub → Settings → Developer settings → Personal access tokens
  2. Generate new token (classic)
  3. Name: evidence-production
  4. Scopes: repo, read:org
  5. Expiration: 90 days
  6. Generate and copy token

Set environment variable:

export GITHUB_TOKEN=ghp_production_token_here

2. AWS Setup

Create IAM user:

aws iam create-user --user-name evidence-collector-production

# Attach policy
aws iam put-user-policy \
  --user-name evidence-collector-production \
  --policy-name EvidenceCollection \
  --policy-document file://evidence-policy.json

Policy (evidence-policy.json):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:GetAccountPasswordPolicy",
        "cloudtrail:DescribeTrails",
        "cloudtrail:GetTrailStatus",
        "logs:DescribeLogGroups"
      ],
      "Resource": "*"
    }
  ]
}

Create access key:

aws iam create-access-key --user-name evidence-collector-production

Set environment variables:

export AWS_ACCESS_KEY_ID=AKIA_key_from_above
export AWS_SECRET_ACCESS_KEY=secret_from_above

3. Google Workspace Setup

Create service account:

  1. Go to Google Cloud Console
  2. IAM & Admin → Service Accounts
  3. Create service account: evidence-collector-production
  4. Create JSON key
  5. Download to /etc/evidence/keys/google-service-account.json

Enable domain-wide delegation:

  1. Copy client ID from service account
  2. Go to Admin Console
  3. Security → API controls → Domain-wide Delegation
  4. Add client ID with scopes:
    https://www.googleapis.com/auth/admin.directory.user.readonly
    https://www.googleapis.com/auth/admin.directory.rolemanagement.readonly
    https://www.googleapis.com/auth/admin.reports.audit.readonly

Set environment variable:

export GOOGLE_APPLICATION_CREDENTIALS=/etc/evidence/keys/google-service-account.json

4. Generate Signing Keys

evidence init --generate-keys --key-id production-2026-01

Move to production location:

sudo mkdir -p /etc/evidence/keys
sudo mv ~/.evidence/keys/private.pem /etc/evidence/keys/production.pem
sudo chmod 600 /etc/evidence/keys/production.pem

5. Get evidence Platform API Key

  1. Log in to evidence platform
  2. Settings → API Keys
  3. Create API Key
  4. Permissions: bundles:create, bundles:upload
  5. Copy key (starts with evd_api_)

Set environment variable:

export EVIDENCE_API_KEY=evd_api_your_key_here

Collection

Run Collection

evidence collect

Expected output:

Validating configuration...
  ✓ Configuration valid (3 sources)
  ✓ Signing key found
  ✓ All environment variables set

Validating credentials...
  ✓ GitHub token valid (scopes: repo, read:org)
  ✓ AWS credentials valid (account: 123456789012)
  ✓ Google Workspace service account valid

Collecting from GitHub...
  → Fetching organization settings
  → Discovering repositories (47 found)
  → Fetching branch protection (47 repos)
  → Fetching CODEOWNERS (44 repos)
  ✓ GitHub: 93 artifacts collected

Collecting from AWS...
  → Fetching IAM password policy
  → Fetching CloudTrail status (production-audit-trail)
  → Fetching CloudWatch log groups (12 found)
  ✓ AWS: 14 artifacts collected

Collecting from Google Workspace...
  → Fetching 2SV enforcement
  → Fetching admin roles (5 roles)
  → Fetching user lifecycle events
  ✓ Google Workspace: 3 artifacts collected

Creating bundle...
  → Generating manifest
  → Computing checksums (110 files)
  → Signing bundle
  ✓ Bundle created: acme-soc2_type1-20260110-143022.tar.gz

Verifying bundle...
  ✓ Checksums valid (110/110 files)
  ✓ Signature valid

Uploading to evidence platform...
  ✓ Authenticated (organization: acme)
  ✓ Upload complete (35.7 KB in 2.1s)
  ✓ Verified on platform

✓ Collection complete

Bundle ID: bundle_abc123def456
Platform URL: https://app.evidence-platform.com/bundles/bundle_abc123def456

Summary:
  Framework: soc2_type1
  Controls: CC6.1, CC6.6, CC7.2
  Sources: github, aws, google_workspace
  Artifacts: 110
  Size: 35.7 KB (compressed)
  Duration: 23.4 seconds

Verification

Verify Bundle Locally

evidence verify /var/evidence/bundles/acme-soc2_type1-*.tar.gz

Output:

Verifying bundle...
  ✓ Checksums valid (110/110 files)
  ✓ Signature valid

Bundle is authentic and unmodified.

Control Coverage:
  CC6.1: Complete (3/3 sources)
  CC6.6: Complete (2/2 sources)
  CC7.2: Complete (2/2 sources)

Bundle Details:
  Framework: soc2_type1
  Controls: CC6.1, CC6.6, CC7.2
  Sources: github, aws, google_workspace
  Artifacts: 110
  Created: 2026-01-10T14:30:22Z
  Signed: production-2026-01

Inspect Bundle Contents

tar -xzf /var/evidence/bundles/acme-soc2_type1-*.tar.gz -C /tmp/inspect
tree /tmp/inspect

Structure:

/tmp/inspect/
├── manifest.json
├── run.json
├── checksums.sha256
├── signature.sig
├── sources/
│   ├── github/
│   │   ├── org_settings.json
│   │   ├── repo_acme_backend_branch_protection.json
│   │   ├── repo_acme_backend_codeowners.json
│   │   ├── repo_acme_frontend_branch_protection.json
│   │   ... (93 total)
│   ├── aws/
│   │   ├── iam_password_policy.json
│   │   ├── cloudtrail_trail_production_status.json
│   │   ├── cloudwatch_log_group_aws_lambda_production_api.json
│   │   ... (14 total)
│   └── google_workspace/
│       ├── 2sv_enforcement.json
│       ├── admin_roles.json
│       └── user_lifecycle.json
└── derived/
    ├── normalized.json
    └── hints.json

Automation

Cron Job

# /etc/cron.d/evidence-collection
# Collect evidence on first day of each month at 2 AM

0 2 1 * * evidence source /etc/evidence/.env && evidence collect >> /var/log/evidence-collection.log 2>&1

systemd Timer

Service file (/etc/systemd/system/evidence-collection.service):

[Unit]
Description=Evidence Collection
After=network.target

[Service]
Type=oneshot
User=evidence
EnvironmentFile=/etc/evidence/.env
ExecStart=/usr/bin/evidence collect
WorkingDirectory=/var/evidence

Timer file (/etc/systemd/system/evidence-collection.timer):

[Unit]
Description=Monthly Evidence Collection
Requires=evidence-collection.service

[Timer]
OnCalendar=monthly
Persistent=true

[Install]
WantedBy=timers.target

Enable:

sudo systemctl enable evidence-collection.timer
sudo systemctl start evidence-collection.timer

Production Considerations

Security

  1. Credentials storage:

    • Use secrets manager (Vault, AWS Secrets Manager)
    • Restrict file permissions (600)
    • Rotate credentials quarterly
  2. Access control:

    • Dedicated service account
    • Least privilege permissions
    • Audit access logs
  3. Key management:

    • Separate keys per environment
    • Annual rotation schedule
    • Encrypted backups

Monitoring

Check collection success:

# View recent bundles
ls -lt /var/evidence/bundles/ | head -5

# Check last collection log
tail -50 /var/log/evidence-collection.log

# Verify upload
curl -H "Authorization: Bearer $EVIDENCE_API_KEY" \
  https://api.evidence-platform.com/bundles/latest

Alerts:

  • Email notification on failure
  • Platform notification on upload
  • Slack integration for team visibility

Retention

Local bundles:

# Keep last 6 months locally
find /var/evidence/bundles -name "*.tar.gz" -mtime +180 -delete

Platform bundles:

  • Configured in upload.retention_days: 730
  • Auto-deleted after 2 years
  • Export before deletion if needed

Troubleshooting

Rate Limiting (GitHub)

Error:

✗ GitHub connector failed
Error: API rate limit exceeded

Solution:

  • Collection pauses automatically
  • Wait for reset (up to 1 hour)
  • Or schedule collection during off-hours

Bundle Too Large

Error:

✗ Bundle creation failed
Error: Bundle size (125 MB) exceeds maximum (100 MB)

Solution:

  • Increase limit: max_size_mb: 200
  • Reduce scope: Limit repos or log groups
  • Disable verbose manifest

Upload Timeout

Error:

✗ Upload failed
Error: Request timeout after 300s

Solution:

  • Increase timeout: upload.timeout_seconds: 600
  • Check network connectivity
  • Reduce bundle size

See Also