agent-governance/docs/CREDENTIALS_SETUP.md
profit 8c6e7831e9 Add Phase 10-12 implementation: multi-tenant, marketplace, observability
Major additions:
- marketplace/: Agent template registry with FTS5 search, ratings, versioning
- observability/: Prometheus metrics, distributed tracing, structured logging
- ledger/migrations/: Database migration scripts for multi-tenant support
- tests/governance/: 15 new test files for phases 6-12 (295 total tests)
- bin/validate-phases: Full 12-phase validation script

New features:
- Multi-tenant support with tenant isolation and quota enforcement
- Agent marketplace with semantic versioning and search
- Observability with metrics, tracing, and log correlation
- Tier-1 agent bootstrap scripts

Updated components:
- ledger/api.py: Extended API for tenants, marketplace, observability
- ledger/schema.sql: Added tenant, project, marketplace tables
- testing/framework.ts: Enhanced test framework
- checkpoint/checkpoint.py: Improved checkpoint management

Archived:
- External integrations (Slack/GitHub/PagerDuty) moved to .archive/
- Old checkpoint files cleaned up

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 18:39:47 -05:00

10 KiB

Production Credentials Setup Guide

How to configure external integration credentials for Slack, GitHub, and PagerDuty.

Overview

The Agent Governance System uses HashiCorp Vault for secure credential storage. Each integration has a dedicated secret path with specific required keys. The system also supports environment variable overrides for development and CI environments.

Prerequisites

  • Vault server running at https://127.0.0.1:8200 (or VAULT_ADDR)
  • Vault root token or appropriate access policy
  • Admin access to Slack, GitHub, and PagerDuty accounts

Credential Priority

The secrets manager loads credentials in this order:

  1. Environment variables (highest priority)
  2. Vault secrets (production)
  3. Mock values (testing only, when INTEGRATION_DRY_RUN=true)

Slack Integration

Vault Path

secret/data/integrations/slack

Required Keys

Key Description Format
slack_bot_token Bot User OAuth Token xoxb-...
slack_webhook_url Incoming Webhook URL https://hooks.slack.com/services/...

How to Obtain

Bot Token

  1. Go to api.slack.com/apps
  2. Create a new app or select existing
  3. Navigate to OAuth & Permissions
  4. Under Bot Token Scopes, add:
    • chat:write - Send messages
    • chat:write.public - Send to public channels
    • files:write - Upload files (optional)
  5. Click Install to Workspace
  6. Copy the Bot User OAuth Token (xoxb-...)

Webhook URL

  1. In your Slack app, go to Incoming Webhooks
  2. Enable incoming webhooks
  3. Click Add New Webhook to Workspace
  4. Select the target channel
  5. Copy the Webhook URL

Store in Vault

# Set Vault address and token
export VAULT_ADDR="https://127.0.0.1:8200"
export VAULT_TOKEN=$(cat /opt/vault/init-keys.json | python3 -c "import sys,json; print(json.load(sys.stdin)['root_token'])")

# Store Slack credentials
vault kv put secret/integrations/slack \
    slack_bot_token="xoxb-YOUR-BOT-TOKEN" \
    slack_webhook_url="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" \
    configured=true

# Or using curl (if vault CLI not available)
curl -sk -X POST \
    -H "X-Vault-Token: $VAULT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
        "data": {
            "slack_bot_token": "xoxb-YOUR-BOT-TOKEN",
            "slack_webhook_url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
            "configured": true
        }
    }' \
    "$VAULT_ADDR/v1/secret/data/integrations/slack"

Environment Variable Override

export SLACK_BOT_TOKEN="xoxb-YOUR-BOT-TOKEN"
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

Verify Configuration

# Test with Python
python3 -c "
from integrations.slack import SlackIntegration
slack = SlackIntegration()
print(f'Enabled: {slack.enabled}')
print(f'Connection test: {slack.test_connection()}')
"

GitHub Integration

Vault Path

secret/data/integrations/github

Required Keys

Key Description Format
github_token Personal Access Token or App Token ghp_... or ghs_...
github_webhook_secret Webhook signature secret Random string

How to Obtain

Personal Access Token (Classic)

  1. Go to github.com/settings/tokens
  2. Click Generate new token (classic)
  3. Select scopes:
    • repo - Full repository access
    • write:org - Organization webhooks (if needed)
    • admin:repo_hook - Manage webhooks
  4. Click Generate token
  5. Copy the token immediately (shown only once)
  1. Go to github.com/settings/tokens?type=beta
  2. Click Generate new token
  3. Set token name and expiration
  4. Select Repository access (specific repos or all)
  5. Under Permissions, enable:
    • Contents: Read and write
    • Pull requests: Read and write
    • Commit statuses: Read and write
    • Webhooks: Read and write
  6. Click Generate token

Webhook Secret

  1. Generate a random secret:
    openssl rand -hex 32
    
  2. When creating GitHub webhooks, use this secret for signature verification

Store in Vault

# Generate webhook secret
WEBHOOK_SECRET=$(openssl rand -hex 32)

# Store GitHub credentials
vault kv put secret/integrations/github \
    github_token="ghp_YOUR-PERSONAL-ACCESS-TOKEN" \
    github_webhook_secret="$WEBHOOK_SECRET" \
    configured=true

# Or using curl
curl -sk -X POST \
    -H "X-Vault-Token: $VAULT_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{
        \"data\": {
            \"github_token\": \"ghp_YOUR-PERSONAL-ACCESS-TOKEN\",
            \"github_webhook_secret\": \"$WEBHOOK_SECRET\",
            \"configured\": true
        }
    }" \
    "$VAULT_ADDR/v1/secret/data/integrations/github"

Environment Variable Override

export GITHUB_TOKEN="ghp_YOUR-PERSONAL-ACCESS-TOKEN"
export GITHUB_WEBHOOK_SECRET="your-webhook-secret"

Verify Configuration

python3 -c "
from integrations.github import GitHubIntegration
gh = GitHubIntegration()
print(f'Enabled: {gh.enabled}')
print(f'Connection test: {gh.test_connection()}')
"

PagerDuty Integration

Vault Path

secret/data/integrations/pagerduty

Required Keys

Key Description Format
pagerduty_routing_key Events API v2 Integration Key 32-char hex string
pagerduty_api_token REST API Token (optional) 20-char string
pagerduty_service_id Service ID (optional) P... format

How to Obtain

Routing Key (Events API v2) - Required

  1. Log into app.pagerduty.com
  2. Go to Services > Select your service
  3. Click Integrations tab
  4. Click Add Integration
  5. Select Events API v2
  6. Copy the Integration Key (this is your routing key)

REST API Token (Optional)

  1. Go to Configuration > API Access
  2. Click Create New API Key
  3. Enter a description (e.g., "Agent Governance")
  4. Choose Read/Write access
  5. Copy the generated token

Service ID (Optional)

  1. Go to Services > Select your service
  2. The Service ID is in the URL: app.pagerduty.com/services/PXXXXXX
  3. Or find it under Settings > Service ID

Store in Vault

# Store PagerDuty credentials
vault kv put secret/integrations/pagerduty \
    pagerduty_routing_key="YOUR-32-CHAR-ROUTING-KEY" \
    pagerduty_api_token="YOUR-API-TOKEN" \
    pagerduty_service_id="PXXXXXXX" \
    configured=true

# Or using curl
curl -sk -X POST \
    -H "X-Vault-Token: $VAULT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
        "data": {
            "pagerduty_routing_key": "YOUR-32-CHAR-ROUTING-KEY",
            "pagerduty_api_token": "YOUR-API-TOKEN",
            "pagerduty_service_id": "PXXXXXXX",
            "configured": true
        }
    }' \
    "$VAULT_ADDR/v1/secret/data/integrations/pagerduty"

Environment Variable Override

export PAGERDUTY_ROUTING_KEY="your-32-char-routing-key"
export PAGERDUTY_API_TOKEN="your-api-token"
export PAGERDUTY_SERVICE_ID="PXXXXXXX"

Verify Configuration

python3 -c "
from integrations.pagerduty import PagerDutyIntegration
pd = PagerDutyIntegration()
print(f'Enabled: {pd.enabled}')
print(f'Connection test: {pd.test_connection()}')
"

Runtime Environment Variables

The following environment variables control integration behavior:

Variable Description Default
VAULT_ADDR Vault server address https://127.0.0.1:8200
VAULT_TOKEN Vault authentication token Read from /opt/vault/init-keys.json
USE_VAULT Enable Vault secret loading true
INTEGRATION_DRY_RUN Prevent actual API calls (testing) false
TESTING Enable mock mode for all secrets false

Production Configuration

# /etc/environment or systemd unit file
VAULT_ADDR=https://vault.internal:8200
USE_VAULT=true
INTEGRATION_DRY_RUN=false

Development Configuration

# .env or shell profile
export SLACK_BOT_TOKEN="xoxb-dev-token"
export GITHUB_TOKEN="ghp_dev-token"
export PAGERDUTY_ROUTING_KEY="dev-routing-key"
export INTEGRATION_DRY_RUN=true

Verification Script

Run this script to verify all integrations are properly configured:

#!/bin/bash
# verify-integrations.sh

cd /opt/agent-governance

echo "=== Integration Credential Verification ==="
echo ""

python3 << 'EOF'
import os
import sys
sys.path.insert(0, "/opt/agent-governance/integrations")

from common.secrets import SecretsManager

secrets = SecretsManager()

integrations = ["slack", "github", "pagerduty"]

for name in integrations:
    result = secrets.validate_integration(name)
    status = "READY" if result["ready"] else "MISSING KEYS"
    print(f"\n[{name.upper()}] {status}")
    if result["configured"]:
        print(f"  Configured: {', '.join(result['configured'])}")
    if result["missing"]:
        print(f"  Missing: {', '.join(result['missing'])}")
    if result["mock_mode"]:
        print(f"  (Running in mock mode)")

print("\n" + "=" * 45)
EOF

Troubleshooting

"No credentials found"

  1. Check Vault is accessible: curl -sk $VAULT_ADDR/v1/sys/health
  2. Verify token is valid: vault token lookup
  3. Check secret path exists: vault kv get secret/integrations/slack

"Connection test failed"

  1. Verify credentials are correct (not placeholder values)
  2. Check network connectivity to external services
  3. Enable dry-run mode to test without making real API calls:
    INTEGRATION_DRY_RUN=true python3 -c "..."
    

"Rate limit exceeded"

  1. The integration base class handles rate limiting (60 req/min default)
  2. Check _request_times in the integration instance
  3. Wait 60 seconds and retry

Security Best Practices

  1. Never commit credentials to version control
  2. Rotate tokens regularly (GitHub: 90 days, PagerDuty: annually)
  3. Use least privilege - only request scopes you need
  4. Enable Vault audit logging for credential access tracking
  5. Use environment variables only in development; production should use Vault
  6. Monitor for credential leaks with GitHub secret scanning


Last updated: 2026-01-24