diff --git a/.env.example b/.env.example index b8979d7..9f62c64 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,11 @@ NODE_ENV=development PORT=3002 +# Trust Proxy Configuration +# Set to 'true' when running behind reverse proxies (nginx, cloudflare, etc.) +# This allows proper handling of X-Forwarded-For headers for rate limiting +TRUST_PROXY=false + # ============================ # SECRETS CONFIGURATION # ============================ @@ -43,6 +48,10 @@ DEFAULT_BRANCH=main # Claude API Settings ANTHROPIC_API_KEY=your_anthropic_api_key_here +# Claude Hub Directory +# Directory where Claude Hub stores configuration, authentication, and database files (default: ~/.claude-hub) +CLAUDE_HUB_DIR=/home/user/.claude-hub + # Container Settings CLAUDE_USE_CONTAINERS=1 CLAUDE_CONTAINER_IMAGE=claudecode:latest diff --git a/.gitignore b/.gitignore index ec9049f..6419b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,9 @@ config auth.json service-account.json +# Claude authentication output +.claude-hub/ + # Docker secrets secrets/ diff --git a/CLAUDE.md b/CLAUDE.md index a7c349c..c49f857 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -89,6 +89,37 @@ Use the demo repository for testing auto-tagging and webhook functionality: - Advanced usage: `node cli/webhook-cli.js --repo myrepo --command "Your command" --verbose` - Secure mode: `node cli/webhook-cli-secure.js` (uses AWS profile authentication) +### Claude Authentication Options + +This service supports three authentication methods for different use cases: + +| Method | Best For | Cost | Documentation | +|--------|----------|------|---------------| +| **Setup Container** | Development/Personal ($20-200/month subscriptions) | Fixed subscription cost | [Setup Container Guide](./docs/setup-container-guide.md) | +| **ANTHROPIC_API_KEY** | Production/Team | Pay-per-use (high cost) | [Authentication Guide](./docs/claude-authentication-guide.md) | +| **AWS Bedrock** | Enterprise | Enterprise pricing | [Authentication Guide](./docs/claude-authentication-guide.md) | + +#### Quick Start: Setup Container (Personal/Development) +For Claude Max/20x subscribers wanting to use their subscription for automation: + +```bash +# 1. Run interactive authentication setup +./scripts/setup/setup-claude-interactive.sh + +# 2. In container: authenticate with your subscription +claude login # Follow browser flow +claude status # Verify +exit # Save authentication + +# 3. Test captured authentication +./scripts/setup/test-claude-auth.sh + +# 4. Use in production +cp -r ${CLAUDE_HUB_DIR:-~/.claude-hub}/* ~/.claude/ +``` + +๐Ÿ“– **See [Complete Authentication Guide](./docs/claude-authentication-guide.md) for all methods** + ## Features ### Auto-Tagging diff --git a/Dockerfile.claude-setup b/Dockerfile.claude-setup new file mode 100644 index 0000000..cb2fb41 --- /dev/null +++ b/Dockerfile.claude-setup @@ -0,0 +1,90 @@ +FROM node:24 + +# Install dependencies for interactive session +RUN apt update && apt install -y \ + git \ + sudo \ + zsh \ + curl \ + vim \ + nano \ + gh + +# Set up npm global directory +RUN mkdir -p /usr/local/share/npm-global && \ + chown -R node:node /usr/local/share + +# Switch to node user for npm install +USER node +ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global +ENV PATH=$PATH:/usr/local/share/npm-global/bin + +# Install Claude Code +RUN npm install -g @anthropic-ai/claude-code + +# Switch back to root for setup +USER root + +# Create authentication workspace +RUN mkdir -p /auth-setup && chown -R node:node /auth-setup + +# Set up interactive shell environment +ENV SHELL /bin/zsh +WORKDIR /auth-setup + +# Create setup script that captures authentication state +RUN cat > /setup-claude-auth.sh << 'EOF' +#!/bin/bash +set -e + +echo "๐Ÿ”ง Claude Authentication Setup Container" +echo "========================================" +echo "" +echo "This container allows you to authenticate with Claude interactively" +echo "and capture the authentication state for use in other containers." +echo "" +echo "Instructions:" +echo "1. Run: claude login" +echo "2. Follow the authentication flow" +echo "3. Test with: claude status" +echo "4. Type 'exit' when authentication is working" +echo "" +echo "The ~/.claude directory will be preserved in /auth-output" +echo "" + +# Function to copy authentication state +copy_auth_state() { + if [ -d "/home/node/.claude" ] && [ -d "/auth-output" ]; then + echo "๐Ÿ’พ Copying authentication state..." + cp -r /home/node/.claude/* /auth-output/ 2>/dev/null || true + cp -r /home/node/.claude/.* /auth-output/ 2>/dev/null || true + chown -R node:node /auth-output + echo "โœ… Authentication state copied to /auth-output" + fi +} + +# Set up signal handling to capture state on exit +trap copy_auth_state EXIT + +# Create .claude directory for node user +sudo -u node mkdir -p /home/node/.claude + +echo "๐Ÿ” Starting interactive shell as 'node' user..." +echo "๐Ÿ’ก Tip: Run 'claude --version' to verify Claude CLI is available" +echo "" + +# Switch to node user and start interactive shell +sudo -u node bash -c ' + export HOME=/home/node + export PATH=/usr/local/share/npm-global/bin:$PATH + cd /home/node + echo "Environment ready! Claude CLI is available at: $(which claude || echo "/usr/local/share/npm-global/bin/claude")" + echo "Run: claude login" + exec bash -i +' +EOF + +RUN chmod +x /setup-claude-auth.sh + +# Set entrypoint to setup script +ENTRYPOINT ["/setup-claude-auth.sh"] \ No newline at end of file diff --git a/Dockerfile.claudecode b/Dockerfile.claudecode index 2f7ddd4..baf0c7d 100644 --- a/Dockerfile.claudecode +++ b/Dockerfile.claudecode @@ -75,8 +75,10 @@ RUN chmod +x /usr/local/bin/init-firewall.sh && \ # Create scripts directory and copy entrypoint scripts RUN mkdir -p /scripts/runtime COPY scripts/runtime/claudecode-entrypoint.sh /usr/local/bin/entrypoint.sh +COPY scripts/runtime/claudecode-entrypoint.sh /scripts/runtime/claudecode-entrypoint.sh COPY scripts/runtime/claudecode-tagging-entrypoint.sh /scripts/runtime/claudecode-tagging-entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh && \ + chmod +x /scripts/runtime/claudecode-entrypoint.sh && \ chmod +x /scripts/runtime/claudecode-tagging-entrypoint.sh # Set the default shell to bash diff --git a/debug-file-copy.sh b/debug-file-copy.sh new file mode 100755 index 0000000..38d431f --- /dev/null +++ b/debug-file-copy.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -e + +echo "=== Debugging Claude Auth File Copying ===" + +# Test the exact same logic as the entrypoint scripts +SOURCE_DIR="/home/node/.claude" +DEST_DIR="/workspace/.claude" + +echo "1. Checking source directory..." +if [ -d "$SOURCE_DIR" ]; then + echo "โœ“ Source directory exists: $SOURCE_DIR" + echo "Source contents:" + ls -la "$SOURCE_DIR/" || echo "ERROR: Cannot list source directory" + + echo "Checking .credentials.json specifically:" + if [ -f "$SOURCE_DIR/.credentials.json" ]; then + echo "โœ“ .credentials.json exists in source" + echo "Size: $(stat -c%s "$SOURCE_DIR/.credentials.json" 2>/dev/null || echo 'unknown') bytes" + echo "Permissions: $(stat -c%a "$SOURCE_DIR/.credentials.json" 2>/dev/null || echo 'unknown')" + else + echo "โœ— .credentials.json NOT found in source" + fi +else + echo "โœ— Source directory does not exist: $SOURCE_DIR" + exit 1 +fi + +echo -e "\n2. Creating destination directory..." +mkdir -p "$DEST_DIR" +echo "โœ“ Destination directory created: $DEST_DIR" + +echo -e "\n3. Testing rsync copy..." +if command -v rsync >/dev/null 2>&1; then + echo "Using rsync for copy..." + rsync -av "$SOURCE_DIR/" "$DEST_DIR/" || echo "ERROR: rsync failed" +else + echo "rsync not available, using cp..." + cp -r "$SOURCE_DIR"/* "$DEST_DIR/" 2>/dev/null || true + cp -r "$SOURCE_DIR"/.* "$DEST_DIR/" 2>/dev/null || true +fi + +echo -e "\n4. Checking destination after copy..." +if [ -d "$DEST_DIR" ]; then + echo "โœ“ Destination directory exists after copy" + echo "Destination contents:" + ls -la "$DEST_DIR/" || echo "ERROR: Cannot list destination directory" + + echo "Checking .credentials.json in destination:" + if [ -f "$DEST_DIR/.credentials.json" ]; then + echo "โœ“ .credentials.json successfully copied" + echo "Size: $(stat -c%s "$DEST_DIR/.credentials.json" 2>/dev/null || echo 'unknown') bytes" + echo "Permissions: $(stat -c%a "$DEST_DIR/.credentials.json" 2>/dev/null || echo 'unknown')" + echo "First 100 chars of content:" + head -c 100 "$DEST_DIR/.credentials.json" 2>/dev/null || echo "ERROR: Cannot read file" + else + echo "โœ— .credentials.json NOT copied to destination" + fi +else + echo "โœ— Destination directory does not exist after copy" +fi + +echo -e "\n5. Setting permissions..." +chown -R node:node "$DEST_DIR" 2>/dev/null || echo "WARNING: Cannot change ownership" +chmod 600 "$DEST_DIR/.credentials.json" 2>/dev/null || echo "WARNING: Cannot change file permissions" +chmod 755 "$DEST_DIR" 2>/dev/null || echo "WARNING: Cannot change directory permissions" + +echo -e "\n6. Final verification..." +if [ -f "$DEST_DIR/.credentials.json" ]; then + echo "โœ“ Final check: .credentials.json exists and is accessible" + echo "Final permissions: $(stat -c%a "$DEST_DIR/.credentials.json" 2>/dev/null || echo 'unknown')" + echo "Owner: $(stat -c%U:%G "$DEST_DIR/.credentials.json" 2>/dev/null || echo 'unknown')" +else + echo "โœ— Final check: .credentials.json still missing" +fi + +echo -e "\n=== Debug Complete ===" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 323c425..d4ee27a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,16 +2,17 @@ services: webhook: build: . ports: - - "8082:3002" + - "8082:3003" volumes: - .:/app - /app/node_modules - /var/run/docker.sock:/var/run/docker.sock - ${HOME}/.aws:/root/.aws:ro - - ${HOME}/.claude:/home/claudeuser/.claude + - ${HOME}/.claude:/home/node/.claude:ro environment: - NODE_ENV=production - - PORT=3002 + - PORT=3003 + - TRUST_PROXY=${TRUST_PROXY:-true} - AUTHORIZED_USERS=${AUTHORIZED_USERS:-Cheffromspace} - BOT_USERNAME=${BOT_USERNAME:-@MCPClaude} - DEFAULT_GITHUB_OWNER=${DEFAULT_GITHUB_OWNER:-Cheffromspace} @@ -19,6 +20,8 @@ services: - DEFAULT_BRANCH=${DEFAULT_BRANCH:-main} - CLAUDE_USE_CONTAINERS=1 - CLAUDE_CONTAINER_IMAGE=claudecode:latest + - CLAUDE_AUTH_HOST_DIR=${CLAUDE_AUTH_HOST_DIR:-./claude-auth-output} + - DISABLE_LOG_REDACTION=true # Smart wait for all meaningful checks by default, or use specific workflow trigger - PR_REVIEW_WAIT_FOR_ALL_CHECKS=${PR_REVIEW_WAIT_FOR_ALL_CHECKS:-true} - PR_REVIEW_TRIGGER_WORKFLOW=${PR_REVIEW_TRIGGER_WORKFLOW:-} @@ -31,7 +34,7 @@ services: - GITHUB_WEBHOOK_SECRET=${GITHUB_WEBHOOK_SECRET} restart: unless-stopped healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3002/health"] + test: ["CMD", "curl", "-f", "http://localhost:3003/health"] interval: 30s timeout: 10s retries: 3 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..75f885a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,163 @@ +# Claude Hub Documentation + +Welcome to the Claude GitHub Webhook service documentation! This service enables Claude AI to respond to GitHub events and automate repository workflows. + +## ๐Ÿ“‹ Quick Start Guides + +### For Developers with Claude Subscriptions +**๐Ÿ’ก Recommended for personal projects and development** + +You can use your existing Claude Max ($20/month) or Claude 20x ($200/month) subscription instead of paying API fees: + +1. **[Setup Container Authentication](./setup-container-guide.md)** - Use your subscription for automation +2. **[Complete Authentication Guide](./claude-authentication-guide.md)** - All authentication methods + +### For Production and Teams +**๐Ÿข Recommended for production applications** + +- **[ANTHROPIC_API_KEY Setup](./claude-authentication-guide.md#-option-2-anthropic_api_key-productionteam)** - Direct API key authentication +- **[AWS Bedrock Setup](./claude-authentication-guide.md#๏ธ-option-3-aws-bedrock-enterprise)** - Enterprise-grade deployment + +## ๐Ÿš€ Key Features + +### GitHub Integration +- **Auto-tagging**: Automatically categorize and label new issues +- **PR Reviews**: Comprehensive automated pull request reviews +- **Webhook Responses**: Claude responds to mentions in issues and PRs +- **CLI Access**: Direct command-line interface for testing + +### Authentication Flexibility +- **Personal**: Use Claude Max/20x subscriptions via setup container +- **Production**: ANTHROPIC_API_KEY for stable production usage +- **Enterprise**: AWS Bedrock integration for compliance and scale + +### Security & Reliability +- **Container Isolation**: Secure execution environment +- **Credential Management**: Multiple secure authentication methods +- **Rate Limiting**: Built-in protection against abuse +- **Logging**: Comprehensive audit trail + +## ๐Ÿ“š Documentation Index + +### Getting Started +- **[Main README](../README.md)** - Project overview and basic setup +- **[CLAUDE.md](../CLAUDE.md)** - Complete build and run commands +- **[Authentication Guide](./claude-authentication-guide.md)** - Choose your auth method + +### Authentication Methods +- **[Setup Container Guide](./setup-container-guide.md)** - Use your Claude subscription +- **[AWS Authentication](./aws-authentication-best-practices.md)** - Enterprise AWS setup +- **[Credential Security](./credential-security.md)** - Security best practices + +### Workflows & CI/CD +- **[Complete Workflow](./complete-workflow.md)** - End-to-end process documentation +- **[GitHub Workflow](./github-workflow.md)** - GitHub-specific integration +- **[Docker CI/CD](./docker-ci-cd.md)** - Container deployment +- **[PR Review Workflow](./pr-review-workflow.md)** - Automated code reviews + +### Container & Deployment +- **[Container Setup](./container-setup.md)** - Docker configuration +- **[Container Limitations](./container-limitations.md)** - Known constraints +- **[Docker Optimization](./docker-optimization.md)** - Performance tuning + +### Security & Operations +- **[Logging Security](./logging-security.md)** - Secure logging practices +- **[Pre-commit Setup](./pre-commit-setup.md)** - Code quality automation +- **[Scripts Documentation](./SCRIPTS.md)** - Available utility scripts + +## ๐Ÿ’ฐ Cost Comparison + +| Usage Level | Setup Container | API Key | AWS Bedrock | +|-------------|-----------------|---------|-------------| +| **Light** (< 1M tokens/month) | $20-200/month | ~$15/month | ~$20/month | +| **Medium** (1-10M tokens/month) | $20-200/month | $150-1500/month | $150-1500/month | +| **Heavy** (10M+ tokens/month) | $20-200/month | $1500+/month | $1500+/month | + +**๐Ÿ’ก Pro Tip**: If you're already paying for Claude 20x ($200/month), the setup container method gives you unlimited automation at no additional cost! + +## ๐ŸŽฏ Use Case Recommendations + +### Individual Developers +- **Start with**: [Setup Container](./setup-container-guide.md) (use your Claude subscription) +- **Scale to**: API Key if you need higher stability + +### Small Teams (2-10 developers) +- **Recommended**: [ANTHROPIC_API_KEY](./claude-authentication-guide.md#-option-2-anthropic_api_key-productionteam) +- **Budget option**: Multiple setup containers for different team members + +### Enterprise (10+ developers) +- **Recommended**: [AWS Bedrock](./claude-authentication-guide.md#๏ธ-option-3-aws-bedrock-enterprise) +- **Alternative**: ANTHROPIC_API_KEY with enterprise support + +## ๐Ÿ”ง Quick Commands + +### Authentication Setup +```bash +# Personal/Development (use Claude subscription) +./scripts/setup/setup-claude-interactive.sh + +# Production (API key) +echo "ANTHROPIC_API_KEY=sk-ant-your-key" >> .env + +# Enterprise (AWS Bedrock) +./scripts/aws/create-aws-profile.sh +``` + +### Service Management +```bash +# Start services +docker compose up -d + +# View logs +docker compose logs -f webhook + +# Restart services +docker compose restart webhook + +# Test webhook +node cli/webhook-cli.js --repo "owner/repo" --command "Hello Claude!" --url "http://localhost:8082" +``` + +### Development +```bash +# Run tests +npm test + +# Type checking +npm run typecheck + +# Linting +npm run lint + +# Build +npm run build +``` + +## ๐Ÿ†˜ Support & Troubleshooting + +### Common Issues +1. **Authentication Problems**: See [Authentication Guide](./claude-authentication-guide.md) +2. **Container Issues**: Check [Container Limitations](./container-limitations.md) +3. **GitHub Integration**: Review [GitHub Workflow](./github-workflow.md) +4. **Performance**: Consult [Docker Optimization](./docker-optimization.md) + +### Getting Help +- **Documentation**: Check the relevant guide above +- **Logs**: Use `docker compose logs -f webhook` for debugging +- **Testing**: Use CLI tools for isolated testing +- **Community**: Share experiences and solutions + +## ๐Ÿš€ Innovation Highlights + +### Setup Container Method +Our **setup container approach** is a breakthrough innovation that allows Claude Max/20x subscribers to use their existing subscriptions for automation - potentially saving thousands of dollars compared to API usage. + +### Multi-tier Authentication +Flexible authentication supports everything from personal development ($20/month) to enterprise deployment with full compliance and security. + +### Production Ready +Built for real-world usage with comprehensive logging, security, container isolation, and monitoring capabilities. + +--- + +**Get started today**: Choose your authentication method and follow the corresponding guide above! ๐Ÿš€ \ No newline at end of file diff --git a/docs/claude-authentication-guide.md b/docs/claude-authentication-guide.md new file mode 100644 index 0000000..b538e1c --- /dev/null +++ b/docs/claude-authentication-guide.md @@ -0,0 +1,308 @@ +# Claude Authentication Guide + +This guide covers three authentication methods for using Claude with the webhook service, each designed for different use cases and requirements. + +## Authentication Methods Overview + +| Method | Best For | Cost | Stability | Setup Complexity | +|--------|----------|------|-----------|------------------| +| **Setup Container** | Development/Personal | ~$20-200/month | Good | Medium | +| **ANTHROPIC_API_KEY** | Production/Team | High usage costs | Excellent | Low | +| **AWS Bedrock** | Enterprise | Moderate | Excellent | High | + +--- + +## ๐Ÿณ Option 1: Setup Container (Development/Personal) + +**Best for:** Developers with Claude Max subscriptions ($100-200/month) who want to use their existing subscription for automation. Note: Claude Code is not included with Claude Pro ($20/month). + +### Advantages +- โœ… **Cost-effective**: Use your existing Claude subscription +- โœ… **Full feature access**: Access to latest models included in subscription +- โœ… **No API key management**: Uses OAuth tokens +- โœ… **Reusable authentication**: Capture once, use everywhere + +### Limitations +- โš ๏ธ **Less stable**: OAuth tokens may expire +- โš ๏ธ **Development-focused**: Not recommended for high-volume production +- โš ๏ธ **Setup required**: Requires interactive authentication + +### Setup Process + +#### 1. Run Interactive Authentication Setup +```bash +./scripts/setup/setup-claude-interactive.sh +``` + +#### 2. Authenticate in Container +When the container starts: +```bash +# In the container shell: +claude login +# Follow browser authentication flow +claude status # Verify authentication +exit # Save authentication state +``` + +#### 3. Test Captured Authentication +```bash +./scripts/setup/test-claude-auth.sh +``` + +#### 4. Use Captured Authentication +```bash +# Option A: Copy to your main Claude directory +cp -r ${CLAUDE_HUB_DIR:-~/.claude-hub}/* ~/.claude/ + +# Option B: Mount in docker-compose +# Update docker-compose.yml: +# - ./${CLAUDE_HUB_DIR:-~/.claude-hub}:/home/node/.claude:ro +``` + +#### 5. Verify Setup +```bash +# Test webhook with your subscription +node cli/webhook-cli.js --repo "owner/repo" --command "Test my Claude subscription" --url "http://localhost:8082" +``` + +### Troubleshooting +- **OAuth tokens expire**: Re-run authentication setup when needed +- **File permissions**: Ensure `.credentials.json` is readable by container user +- **Mount issues**: Verify correct path in docker-compose volume mounts + +--- + +## ๐Ÿ”‘ Option 2: ANTHROPIC_API_KEY (Production/Team) + +**Best for:** Production environments, team usage, or when you need guaranteed stability and higher rate limits. + +### Advantages +- โœ… **Highly stable**: Direct API key authentication +- โœ… **Higher limits**: Production-grade rate limits +- โœ… **Simple setup**: Just set environment variable +- โœ… **Team-friendly**: Multiple developers can use same key + +### Limitations +- ๐Ÿ’ฐ **High costs**: Pay-per-use pricing can be expensive +- ๐Ÿ”’ **Requires API access**: Need Anthropic Console access + +### Setup Process + +#### 1. Get API Key +1. Go to [Anthropic Console](https://console.anthropic.com/) +2. Create a new API key +3. Copy the key (starts with `sk-ant-`) + +#### 2. Configure Environment +```bash +# Add to .env file +ANTHROPIC_API_KEY=sk-ant-your-api-key-here +``` + +#### 3. Restart Service +```bash +docker compose restart webhook +``` + +#### 4. Test +```bash +node cli/webhook-cli.js --repo "owner/repo" --command "Test API key authentication" --url "http://localhost:8082" +``` + +### Best Practices +- **Key rotation**: Regularly rotate API keys +- **Environment security**: Never commit keys to version control +- **Usage monitoring**: Monitor API usage and costs +- **Rate limiting**: Implement appropriate rate limiting for your use case + +--- + +## โ˜๏ธ Option 3: AWS Bedrock (Enterprise) + +**Best for:** Enterprise deployments, AWS-integrated environments, or when you need the highest stability and compliance. + +### Advantages +- โœ… **Enterprise-grade**: Highest stability and reliability +- โœ… **AWS integration**: Works with existing AWS infrastructure +- โœ… **Compliance**: Meets enterprise security requirements +- โœ… **Cost predictable**: More predictable pricing models +- โœ… **Regional deployment**: Data residency control + +### Limitations +- ๐Ÿ”ง **Complex setup**: Requires AWS configuration +- ๐Ÿ“‹ **AWS knowledge**: Requires familiarity with AWS services +- ๐Ÿข **Enterprise-focused**: May be overkill for individual developers + +### Setup Process + +#### 1. Configure AWS Credentials +```bash +# Option A: AWS Profile (Recommended) +./scripts/aws/create-aws-profile.sh + +# Option B: Environment Variables +export AWS_ACCESS_KEY_ID=your_access_key +export AWS_SECRET_ACCESS_KEY=your_secret_key +export AWS_REGION=us-east-1 +``` + +#### 2. Configure Bedrock Settings +```bash +# Add to .env file +CLAUDE_CODE_USE_BEDROCK=1 +ANTHROPIC_MODEL=us.anthropic.claude-3-7-sonnet-20250219-v1:0 +AWS_REGION=us-east-1 + +# If using profiles +USE_AWS_PROFILE=true +AWS_PROFILE=claude-webhook +``` + +#### 3. Verify Bedrock Access +```bash +# Test AWS Bedrock access +aws bedrock list-foundation-models --region us-east-1 +``` + +#### 4. Restart Service +```bash +docker compose restart webhook +``` + +#### 5. Test +```bash +node cli/webhook-cli.js --repo "owner/repo" --command "Test Bedrock authentication" --url "http://localhost:8082" +``` + +### Available Models +- `us.anthropic.claude-3-7-sonnet-20250219-v1:0` - Latest Claude 3.5 Sonnet +- `us.anthropic.claude-3-5-haiku-20241022-v1:0` - Claude 3.5 Haiku (faster/cheaper) +- `us.anthropic.claude-3-opus-20240229-v1:0` - Claude 3 Opus (most capable) + +### Best Practices +- **IAM policies**: Use minimal required permissions +- **Regional selection**: Choose region closest to your users +- **Cost monitoring**: Set up CloudWatch billing alerts +- **Access logging**: Enable CloudTrail for audit compliance + +--- + +## ๐Ÿš€ Authentication Priority and Fallback + +The system checks authentication methods in this order: + +1. **ANTHROPIC_API_KEY** (highest priority) +2. **Claude Interactive Authentication** (setup container) +3. **AWS Bedrock** (if configured) + +### Environment Variables + +```bash +# Method 1: Direct API Key +ANTHROPIC_API_KEY=sk-ant-your-key + +# Method 2: Claude Interactive (automatic if ~/.claude is mounted) +# No environment variables needed + +# Method 3: AWS Bedrock +CLAUDE_CODE_USE_BEDROCK=1 +ANTHROPIC_MODEL=us.anthropic.claude-3-7-sonnet-20250219-v1:0 +AWS_REGION=us-east-1 +AWS_ACCESS_KEY_ID=your_key_id +AWS_SECRET_ACCESS_KEY=your_secret_key +# OR +USE_AWS_PROFILE=true +AWS_PROFILE=your-profile-name +``` + +--- + +## ๐Ÿ“Š Cost Comparison + +### Setup Container (Personal/Development) +- **Claude Max**: $20/month unlimited +- **Claude 20x**: $200/month unlimited (20x faster) +- **Perfect for**: Individual developers, hobbyists, development workflows + +### ANTHROPIC_API_KEY (Production) +- **Pricing**: Pay-per-token usage +- **Claude 3.5 Sonnet**: ~$15 per million tokens +- **High volume**: Can easily exceed $100s/month +- **Perfect for**: Production applications, team environments + +### AWS Bedrock (Enterprise) +- **Pricing**: Pay-per-token with enterprise features +- **Claude 3.5 Sonnet**: Similar to API pricing +- **Additional costs**: AWS infrastructure, data transfer +- **Perfect for**: Enterprise deployments, compliance requirements + +--- + +## ๐Ÿ› ๏ธ Switching Between Methods + +You can easily switch between authentication methods by updating your `.env` file: + +```bash +# Development with personal subscription +# Comment out API key, ensure ~/.claude is mounted +# ANTHROPIC_API_KEY= +# Mount: ~/.claude:/home/node/.claude:ro + +# Production with API key +ANTHROPIC_API_KEY=sk-ant-your-production-key + +# Enterprise with Bedrock +CLAUDE_CODE_USE_BEDROCK=1 +ANTHROPIC_MODEL=us.anthropic.claude-3-7-sonnet-20250219-v1:0 +USE_AWS_PROFILE=true +AWS_PROFILE=production-claude +``` + +--- + +## ๐Ÿ” Troubleshooting + +### Authentication Not Working +1. Check environment variables are set correctly +2. Verify API keys are valid and not expired +3. For Bedrock: Ensure AWS credentials have correct permissions +4. For setup container: Re-run authentication if OAuth tokens expired + +### Rate Limiting +- **API Key**: Contact Anthropic for rate limit increases +- **Bedrock**: Configure AWS throttling settings +- **Setup Container**: Limited by subscription tier + +### Cost Monitoring +- **API Key**: Monitor usage in Anthropic Console +- **Bedrock**: Set up AWS billing alerts +- **Setup Container**: Covered by subscription + +--- + +## ๐Ÿ“š Additional Resources + +- [Anthropic Console](https://console.anthropic.com/) - API key management +- [AWS Bedrock Documentation](https://docs.aws.amazon.com/bedrock/) - Enterprise setup +- [Claude Code Documentation](https://docs.anthropic.com/en/docs/claude-code) - Official Claude CLI docs +- [Setup Container Deep Dive](./setup-container-guide.md) - Detailed setup container documentation + +--- + +## ๐ŸŽฏ Recommendations by Use Case + +### Individual Developer +- **Start with**: Setup Container (use your Claude Max subscription) +- **Upgrade to**: API Key if you need higher stability + +### Small Team +- **Recommended**: ANTHROPIC_API_KEY with cost monitoring +- **Alternative**: Multiple setup containers for development + +### Enterprise +- **Recommended**: AWS Bedrock with full compliance setup +- **Alternative**: ANTHROPIC_API_KEY with enterprise support contract + +--- + +*This guide covers all authentication methods for the Claude GitHub Webhook service. Choose the method that best fits your needs, budget, and technical requirements.* \ No newline at end of file diff --git a/docs/setup-container-guide.md b/docs/setup-container-guide.md new file mode 100644 index 0000000..3211e4b --- /dev/null +++ b/docs/setup-container-guide.md @@ -0,0 +1,297 @@ +# Setup Container Deep Dive + +The setup container method allows Claude Max subscribers to use their existing subscriptions for automation and webhook integrations by capturing and reusing authentication state. + +## The Approach + +Traditional Claude CLI usage requires interactive sessions. This setup container captures the complete authentication state, including OAuth tokens and session data, making it portable to non-interactive environments. + +## How It Works + +```mermaid +graph TD + A[Setup Container] --> B[Interactive Claude Login] + B --> C[OAuth Authentication] + C --> D[Capture Auth State] + D --> E[Mount in Production] + E --> F[Automated Claude Usage] +``` + +### 1. Interactive Authentication +- Clean container environment with Claude CLI +- User runs `claude login` and completes browser flow +- OAuth tokens are stored locally + +### 2. State Capture +- Complete `~/.claude` directory is copied on container exit +- Includes credentials, settings, project data, session info +- Preserves all authentication context + +### 3. Production Mount +- Captured authentication mounted read-only +- Working copy created for each execution +- OAuth tokens used automatically by Claude CLI + +## Architecture Benefits + +### For $200/month Claude 20x Users +- **Massive Cost Savings**: Use subscription instead of pay-per-token +- **Full Feature Access**: All Claude 20x benefits (speed, priority) +- **No Usage Anxiety**: Unlimited usage within subscription + +### Technical Advantages +- **OAuth Security**: No API keys in environment variables +- **Session Persistence**: Maintains Claude CLI session state +- **Portable**: Works across different container environments +- **Reusable**: One setup, multiple deployments + +## Files Captured + +The setup container captures all essential Claude authentication files: + +```bash +~/.claude/ +โ”œโ”€โ”€ .credentials.json # OAuth tokens (primary auth) +โ”œโ”€โ”€ settings.local.json # User preferences +โ”œโ”€โ”€ projects/ # Project history +โ”œโ”€โ”€ todos/ # Task management data +โ”œโ”€โ”€ statsig/ # Analytics and feature flags +โ””โ”€โ”€ package.json # CLI dependencies +``` + +### Critical File: .credentials.json +```json +{ + "claudeAiOauth": { + "accessToken": "sk-ant-oat01-...", + "refreshToken": "sk-ant-ort01-...", + "expiresAt": 1748658860401, + "scopes": ["user:inference", "user:profile"] + } +} +``` + +## Container Implementation + +### Setup Container (`Dockerfile.claude-setup`) +- Node.js environment with Claude CLI +- Interactive shell for authentication +- Signal handling for clean state capture +- Automatic file copying on exit + +### Entrypoint Scripts +- **Authentication copying**: Comprehensive file transfer +- **Permission handling**: Correct ownership for container user +- **Debug output**: Detailed logging for troubleshooting + +## Token Lifecycle and Management + +### Token Expiration Timeline +Based on testing, Claude OAuth tokens typically expire within **8-12 hours**: +- **Access tokens**: Short-lived (8-12 hours) +- **Refresh tokens**: Longer-lived but also expire +- **Automatic refresh**: Claude CLI attempts to refresh when needed + +### Refresh Token Behavior +```json +{ + "claudeAiOauth": { + "accessToken": "sk-ant-oat01-...", // Short-lived + "refreshToken": "sk-ant-ort01-...", // Used to get new access tokens + "expiresAt": 1748658860401, // Timestamp when access token expires + "scopes": ["user:inference", "user:profile"] + } +} +``` + +### Automatic Refresh Strategy +The Claude CLI automatically attempts to refresh tokens when: +- Access token is expired or near expiration +- API calls return authentication errors +- Session state indicates refresh is needed + +However, refresh tokens themselves eventually expire, requiring **full re-authentication**. + +### Expected Maintenance Schedule +For production usage with setup containers: + +**Daily Operations** (Recommended) +- Monitor authentication health +- Check for expired tokens in logs + +**Weekly Maintenance** (Conservative) +- Re-run authentication setup +- Update captured authentication state +- Test authentication validity + +**As-Needed Basis** (Minimum) +- Re-authenticate when tokens expire +- Typically required every few days to weeks + +### Automated Refresh Implementation +Currently, token refresh requires manual intervention. Future enhancements could include: + +```bash +# Planned: Automated refresh script +./scripts/setup/refresh-claude-auth.sh + +# Planned: Health check with auto-refresh +./scripts/setup/check-and-refresh-auth.sh +``` + +## Advanced Usage + +### Multiple Environments +```bash +# Development +./${CLAUDE_HUB_DIR:-~/.claude-hub} โ†’ ~/.claude/ + +# Staging +./claude-auth-staging โ†’ staging container + +# Testing +./claude-auth-test โ†’ test container +``` + +### Team Sharing +```bash +# Capture authentication +./scripts/setup/setup-claude-interactive.sh + +# Share auth directory (be cautious with tokens) +tar -czf claude-auth.tar.gz ${CLAUDE_HUB_DIR:-~/.claude-hub}/ + +# Deploy to team environments +``` + +## Security Considerations + +### Token Protection +- OAuth tokens are sensitive credentials +- Store in secure, encrypted storage +- Rotate regularly by re-authenticating + +### Container Security +- Mount authentication read-only +- Use minimal container privileges +- Avoid logging sensitive data + +### Network Security +- HTTPS for all Claude API communication +- Secure token transmission +- Monitor for token abuse + +## Monitoring and Maintenance + +### Health Checks +```bash +# Test authentication status +./scripts/setup/test-claude-auth.sh + +# Verify token validity +docker run --rm -v "./${CLAUDE_HUB_DIR:-~/.claude-hub}:/home/node/.claude:ro" \ + claude-setup:latest claude status +``` + +### Refresh Workflow +```bash +# When authentication expires +./scripts/setup/setup-claude-interactive.sh + +# Update production environment +cp -r ${CLAUDE_HUB_DIR:-~/.claude-hub}/* ~/.claude/ +docker compose restart webhook +``` + +## Troubleshooting + +### Common Issues + +#### 1. Empty .credentials.json +**Symptom**: Authentication fails, file exists but is 0 bytes +**Cause**: Interactive authentication wasn't completed +**Solution**: Re-run setup container and complete browser flow + +#### 2. Permission Errors +**Symptom**: "Permission denied" accessing .credentials.json +**Cause**: File ownership mismatch in container +**Solution**: Entrypoint scripts handle this automatically + +#### 3. OAuth Token Expired +**Symptom**: "Invalid API key" or authentication errors +**Cause**: Tokens expired (natural expiration) +**Solution**: Re-authenticate using setup container + +#### 4. Mount Path Issues +**Symptom**: Authentication files not found in container +**Cause**: Incorrect volume mount in docker-compose +**Solution**: Verify mount path matches captured auth directory + +### Debug Commands + +```bash +# Check captured files +ls -la ${CLAUDE_HUB_DIR:-~/.claude-hub}/ + +# Test authentication directly +docker run --rm -v "$(pwd)/${CLAUDE_HUB_DIR:-~/.claude-hub}:/tmp/auth:ro" \ + --entrypoint="" claude-setup:latest \ + bash -c "cp -r /tmp/auth /home/node/.claude && + sudo -u node env HOME=/home/node \ + /usr/local/share/npm-global/bin/claude --print 'test'" + +# Verify OAuth tokens +cat ${CLAUDE_HUB_DIR:-~/.claude-hub}/.credentials.json | jq '.claudeAiOauth' +``` + +## Future Enhancements + +### Planned Improvements +- **Automatic token refresh**: Monitor and refresh expired tokens +- **Multi-user support**: Separate auth for different users +- **Token rotation**: Automated re-authentication workflow +- **Health monitoring**: Proactive auth status checking + +### Community Contributions +- **Authentication sharing**: Secure team auth distribution +- **Cloud storage**: Store auth in encrypted cloud storage +- **CI/CD integration**: Automated auth setup in pipelines + +## Cost Analysis for $200/month Users + +### Traditional API Approach +- **Claude 3.5 Sonnet**: ~$15 per million tokens +- **Heavy usage**: Easily $500+ per month +- **Usage anxiety**: Every request costs money + +### Setup Container Approach +- **Fixed cost**: $200/month for Claude 20x +- **Unlimited usage**: Within subscription limits +- **Peace of mind**: No per-request charging + +### Break-even Analysis +If you would use more than ~13 million tokens per month, the setup container approach with Claude 20x subscription becomes cost-effective while providing better performance and unlimited usage. + +## Real-world Applications + +### Development Workflows +- **Code review automation**: PR reviews without API costs +- **Issue auto-tagging**: Unlimited issue processing +- **Documentation generation**: Bulk doc creation +- **Test case generation**: Comprehensive test coverage + +### Personal Projects +- **GitHub automation**: Personal repository management +- **Content creation**: Blog posts, documentation +- **Learning projects**: Educational coding assistance +- **Prototyping**: Rapid development iteration + +### Small Business +- **Customer support**: Automated responses +- **Content moderation**: Community management +- **Documentation**: Internal knowledge base +- **Training**: Employee onboarding assistance + +--- + +*The setup container approach democratizes Claude automation for subscription users, making enterprise-level AI automation accessible at subscription pricing.* \ No newline at end of file diff --git a/scripts/runtime/claudecode-entrypoint.sh b/scripts/runtime/claudecode-entrypoint.sh index 19ea424..6075a1b 100755 --- a/scripts/runtime/claudecode-entrypoint.sh +++ b/scripts/runtime/claudecode-entrypoint.sh @@ -13,6 +13,44 @@ set -e mkdir -p /workspace chown -R node:node /workspace +# Set up Claude authentication by syncing from captured auth directory +if [ -d "/claude-auth-source" ]; then + echo "Setting up Claude authentication from captured auth directory..." >&2 + + # Create a writable copy of Claude configuration in workspace + CLAUDE_WORK_DIR="/workspace/.claude" + mkdir -p "$CLAUDE_WORK_DIR" + + echo "DEBUG: Source auth directory contents:" >&2 + ls -la /claude-auth-source/ >&2 || echo "DEBUG: Source auth directory not accessible" >&2 + + # Sync entire auth directory to writable location (including database files, project state, etc.) + if command -v rsync >/dev/null 2>&1; then + rsync -av /claude-auth-source/ "$CLAUDE_WORK_DIR/" 2>/dev/null || echo "rsync failed, trying cp" >&2 + else + # Fallback to cp with comprehensive copying + cp -r /claude-auth-source/* "$CLAUDE_WORK_DIR/" 2>/dev/null || true + cp -r /claude-auth-source/.* "$CLAUDE_WORK_DIR/" 2>/dev/null || true + fi + + echo "DEBUG: Working directory contents after sync:" >&2 + ls -la "$CLAUDE_WORK_DIR/" >&2 || echo "DEBUG: Working directory not accessible" >&2 + + # Set proper ownership and permissions for the node user + chown -R node:node "$CLAUDE_WORK_DIR" + chmod 600 "$CLAUDE_WORK_DIR"/.credentials.json 2>/dev/null || true + chmod 755 "$CLAUDE_WORK_DIR" 2>/dev/null || true + + echo "DEBUG: Final permissions check:" >&2 + ls -la "$CLAUDE_WORK_DIR/.credentials.json" >&2 || echo "DEBUG: .credentials.json not found" >&2 + + echo "Claude authentication directory synced to $CLAUDE_WORK_DIR" >&2 +elif [ -d "/home/node/.claude" ]; then + echo "WARNING: Found /home/node/.claude but no /claude-auth-source. This might use your personal auth." >&2 +else + echo "WARNING: No Claude authentication source found." >&2 +fi + # Configure GitHub authentication if [ -n "${GITHUB_TOKEN}" ]; then export GH_TOKEN="${GITHUB_TOKEN}" @@ -45,8 +83,26 @@ fi sudo -u node git config --global user.email "${BOT_EMAIL:-claude@example.com}" sudo -u node git config --global user.name "${BOT_USERNAME:-ClaudeBot}" -# Configure Anthropic API key -export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" +# Configure Claude authentication +# Support both API key and interactive auth methods +echo "DEBUG: Checking authentication options..." >&2 +echo "DEBUG: ANTHROPIC_API_KEY set: $([ -n "${ANTHROPIC_API_KEY}" ] && echo 'YES' || echo 'NO')" >&2 +echo "DEBUG: /workspace/.claude/.credentials.json exists: $([ -f "/workspace/.claude/.credentials.json" ] && echo 'YES' || echo 'NO')" >&2 +echo "DEBUG: /workspace/.claude contents:" >&2 +ls -la /workspace/.claude/ >&2 || echo "DEBUG: /workspace/.claude directory not found" >&2 + +if [ -n "${ANTHROPIC_API_KEY}" ]; then + echo "Using Anthropic API key for authentication..." >&2 + export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" +elif [ -f "/workspace/.claude/.credentials.json" ]; then + echo "Using Claude interactive authentication from working directory..." >&2 + # No need to set ANTHROPIC_API_KEY - Claude CLI will use the credentials file + # Set HOME to point to our working directory for Claude CLI + export CLAUDE_HOME="/workspace/.claude" + echo "DEBUG: Set CLAUDE_HOME to $CLAUDE_HOME" >&2 +else + echo "WARNING: No Claude authentication found. Please set ANTHROPIC_API_KEY or ensure ~/.claude is mounted." >&2 +fi # Create response file with proper permissions RESPONSE_FILE="/workspace/response.txt" @@ -65,9 +121,18 @@ fi # Log the command length for debugging echo "Command length: ${#COMMAND}" >&2 -# Run Claude Code +# Run Claude Code with proper HOME environment +# If we synced Claude auth to workspace, use workspace as HOME +if [ -f "/workspace/.claude/.credentials.json" ]; then + CLAUDE_USER_HOME="/workspace" + echo "DEBUG: Using /workspace as HOME for Claude CLI (synced auth)" >&2 +else + CLAUDE_USER_HOME="${CLAUDE_HOME:-/home/node}" + echo "DEBUG: Using $CLAUDE_USER_HOME as HOME for Claude CLI (fallback)" >&2 +fi + sudo -u node -E env \ - HOME="/home/node" \ + HOME="$CLAUDE_USER_HOME" \ PATH="/usr/local/bin:/usr/local/share/npm-global/bin:$PATH" \ ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \ GH_TOKEN="${GITHUB_TOKEN}" \ diff --git a/scripts/runtime/claudecode-tagging-entrypoint.sh b/scripts/runtime/claudecode-tagging-entrypoint.sh index d45ecec..b8e812d 100755 --- a/scripts/runtime/claudecode-tagging-entrypoint.sh +++ b/scripts/runtime/claudecode-tagging-entrypoint.sh @@ -12,6 +12,44 @@ set -e mkdir -p /workspace chown -R node:node /workspace +# Set up Claude authentication by syncing from captured auth directory +if [ -d "/claude-auth-source" ]; then + echo "Setting up Claude authentication from captured auth directory..." >&2 + + # Create a writable copy of Claude configuration in workspace + CLAUDE_WORK_DIR="/workspace/.claude" + mkdir -p "$CLAUDE_WORK_DIR" + + echo "DEBUG: Source auth directory contents:" >&2 + ls -la /claude-auth-source/ >&2 || echo "DEBUG: Source auth directory not accessible" >&2 + + # Sync entire auth directory to writable location (including database files, project state, etc.) + if command -v rsync >/dev/null 2>&1; then + rsync -av /claude-auth-source/ "$CLAUDE_WORK_DIR/" 2>/dev/null || echo "rsync failed, trying cp" >&2 + else + # Fallback to cp with comprehensive copying + cp -r /claude-auth-source/* "$CLAUDE_WORK_DIR/" 2>/dev/null || true + cp -r /claude-auth-source/.* "$CLAUDE_WORK_DIR/" 2>/dev/null || true + fi + + echo "DEBUG: Working directory contents after sync:" >&2 + ls -la "$CLAUDE_WORK_DIR/" >&2 || echo "DEBUG: Working directory not accessible" >&2 + + # Set proper ownership and permissions for the node user + chown -R node:node "$CLAUDE_WORK_DIR" + chmod 600 "$CLAUDE_WORK_DIR"/.credentials.json 2>/dev/null || true + chmod 755 "$CLAUDE_WORK_DIR" 2>/dev/null || true + + echo "DEBUG: Final permissions check:" >&2 + ls -la "$CLAUDE_WORK_DIR/.credentials.json" >&2 || echo "DEBUG: .credentials.json not found" >&2 + + echo "Claude authentication directory synced to $CLAUDE_WORK_DIR" >&2 +elif [ -d "/home/node/.claude" ]; then + echo "WARNING: Found /home/node/.claude but no /claude-auth-source. This might use your personal auth." >&2 +else + echo "WARNING: No Claude authentication source found." >&2 +fi + # Configure GitHub authentication if [ -n "${GITHUB_TOKEN}" ]; then export GH_TOKEN="${GITHUB_TOKEN}" @@ -39,8 +77,19 @@ sudo -u node git checkout main >&2 || sudo -u node git checkout master >&2 sudo -u node git config --global user.email "${BOT_EMAIL:-claude@example.com}" sudo -u node git config --global user.name "${BOT_USERNAME:-ClaudeBot}" -# Configure Anthropic API key -export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" +# Configure Claude authentication +# Support both API key and interactive auth methods +if [ -n "${ANTHROPIC_API_KEY}" ]; then + echo "Using Anthropic API key for authentication..." >&2 + export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" +elif [ -f "/workspace/.claude/.credentials.json" ]; then + echo "Using Claude interactive authentication from working directory..." >&2 + # No need to set ANTHROPIC_API_KEY - Claude CLI will use the credentials file + # Set HOME to point to our working directory for Claude CLI + export CLAUDE_HOME="/workspace/.claude" +else + echo "WARNING: No Claude authentication found. Please set ANTHROPIC_API_KEY or ensure ~/.claude is mounted." >&2 +fi # Create response file with proper permissions RESPONSE_FILE="/workspace/response.txt" @@ -60,8 +109,17 @@ fi echo "Command length: ${#COMMAND}" >&2 # Run Claude Code with minimal tool set: Read (for repository context) and GitHub (for label operations) +# If we synced Claude auth to workspace, use workspace as HOME +if [ -f "/workspace/.claude/.credentials.json" ]; then + CLAUDE_USER_HOME="/workspace" + echo "DEBUG: Using /workspace as HOME for Claude CLI (synced auth)" >&2 +else + CLAUDE_USER_HOME="${CLAUDE_HOME:-/home/node}" + echo "DEBUG: Using $CLAUDE_USER_HOME as HOME for Claude CLI (fallback)" >&2 +fi + sudo -u node -E env \ - HOME="/home/node" \ + HOME="$CLAUDE_USER_HOME" \ PATH="/usr/local/bin:/usr/local/share/npm-global/bin:$PATH" \ ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \ GH_TOKEN="${GITHUB_TOKEN}" \ diff --git a/scripts/setup/setup-claude-interactive.sh b/scripts/setup/setup-claude-interactive.sh new file mode 100755 index 0000000..e41ac1a --- /dev/null +++ b/scripts/setup/setup-claude-interactive.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -e + +# Claude Interactive Authentication Setup Script +# This script creates a container for interactive Claude authentication + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +AUTH_OUTPUT_DIR="${CLAUDE_HUB_DIR:-$HOME/.claude-hub}" + +echo "๐Ÿ”ง Claude Interactive Authentication Setup" +echo "=========================================" +echo "" + +# Create output directory for authentication state +mkdir -p "$AUTH_OUTPUT_DIR" + +echo "๐Ÿ“ฆ Building Claude setup container..." +docker build -f "$PROJECT_ROOT/Dockerfile.claude-setup" -t claude-setup:latest "$PROJECT_ROOT" + +echo "" +echo "๐Ÿš€ Starting interactive Claude authentication container..." +echo "" +echo "IMPORTANT: This will open an interactive shell where you can:" +echo " 1. Run 'claude login' to authenticate" +echo " 2. Follow the browser-based authentication flow" +echo " 3. Test with 'claude status' to verify authentication" +echo " 4. Type 'exit' when done to preserve authentication state" +echo "" +echo "The authenticated ~/.claude directory will be saved to:" +echo " $AUTH_OUTPUT_DIR" +echo "" +read -p "Press Enter to continue or Ctrl+C to cancel..." + +# Run the interactive container +docker run -it --rm \ + -v "$AUTH_OUTPUT_DIR:/auth-output" \ + -v "$HOME/.gitconfig:/home/node/.gitconfig:ro" \ + --name claude-auth-setup \ + claude-setup:latest + +echo "" +echo "๐Ÿ“‹ Checking authentication output..." + +if [ -f "$AUTH_OUTPUT_DIR/.credentials.json" ] || [ -f "$AUTH_OUTPUT_DIR/settings.local.json" ]; then + echo "โœ… Authentication files found in $AUTH_OUTPUT_DIR" + echo "" + echo "๐Ÿ“ Captured authentication files:" + find "$AUTH_OUTPUT_DIR" -type f -name "*.json" -o -name "*.db" | head -10 + echo "" + echo "๐Ÿ”„ To use this authentication in your webhook service:" + echo " 1. Copy files to your ~/.claude directory:" + echo " cp -r $AUTH_OUTPUT_DIR/* ~/.claude/" + echo " 2. Or update docker-compose.yml to mount the auth directory:" + echo " - $AUTH_OUTPUT_DIR:/home/node/.claude:ro" + echo "" +else + echo "โš ๏ธ No authentication files found. You may need to:" + echo " 1. Run the container again and complete the authentication flow" + echo " 2. Ensure you ran 'claude login' and completed the browser authentication" + echo " 3. Check that you have an active Claude Max or Pro subscription" +fi + +echo "" +echo "๐Ÿงช Testing authentication..." +echo "You can test the captured authentication with:" +echo " docker run --rm -v \"$AUTH_OUTPUT_DIR:/home/node/.claude:ro\" claude-setup:latest claude status" \ No newline at end of file diff --git a/scripts/setup/test-claude-auth.sh b/scripts/setup/test-claude-auth.sh new file mode 100755 index 0000000..dd37ee0 --- /dev/null +++ b/scripts/setup/test-claude-auth.sh @@ -0,0 +1,91 @@ +#!/bin/bash +set -e + +# Test captured Claude authentication +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +AUTH_OUTPUT_DIR="${CLAUDE_HUB_DIR:-$HOME/.claude-hub}" + +echo "๐Ÿงช Testing Claude Authentication" +echo "================================" +echo "" + +if [ ! -d "$AUTH_OUTPUT_DIR" ]; then + echo "โŒ Authentication directory not found: $AUTH_OUTPUT_DIR" + echo " Run ./scripts/setup/setup-claude-interactive.sh first" + exit 1 +fi + +echo "๐Ÿ“ Authentication files found:" +find "$AUTH_OUTPUT_DIR" -type f | head -20 +echo "" + +echo "๐Ÿ” Testing authentication with Claude CLI..." +echo "" + +# Test Claude version +echo "1. Testing Claude CLI version..." +docker run --rm \ + -v "$AUTH_OUTPUT_DIR:/home/node/.claude:ro" \ + claude-setup:latest \ + sudo -u node -E env HOME=/home/node PATH=/usr/local/share/npm-global/bin:$PATH \ + /usr/local/share/npm-global/bin/claude --version + +echo "" + +# Test Claude status (might fail due to TTY requirements) +echo "2. Testing Claude status..." +docker run --rm \ + -v "$AUTH_OUTPUT_DIR:/home/node/.claude:ro" \ + claude-setup:latest \ + timeout 5 sudo -u node -E env HOME=/home/node PATH=/usr/local/share/npm-global/bin:$PATH \ + /usr/local/share/npm-global/bin/claude status 2>&1 || echo "Status command failed (expected due to TTY requirements)" + +echo "" + +# Test Claude with a simple print command +echo "3. Testing Claude with simple command..." +docker run --rm \ + -v "$AUTH_OUTPUT_DIR:/home/node/.claude:ro" \ + claude-setup:latest \ + timeout 10 sudo -u node -E env HOME=/home/node PATH=/usr/local/share/npm-global/bin:$PATH \ + /usr/local/share/npm-global/bin/claude --print "Hello, testing authentication" 2>&1 || echo "Print command failed" + +echo "" +echo "๐Ÿ” Authentication file analysis:" +echo "================================" + +# Check for key authentication files +if [ -f "$AUTH_OUTPUT_DIR/.credentials.json" ]; then + echo "โœ… .credentials.json found ($(wc -c < "$AUTH_OUTPUT_DIR/.credentials.json") bytes)" +else + echo "โŒ .credentials.json not found" +fi + +if [ -f "$AUTH_OUTPUT_DIR/settings.local.json" ]; then + echo "โœ… settings.local.json found" + echo " Contents: $(head -1 "$AUTH_OUTPUT_DIR/settings.local.json")" +else + echo "โŒ settings.local.json not found" +fi + +if [ -d "$AUTH_OUTPUT_DIR/statsig" ]; then + echo "โœ… statsig directory found ($(ls -1 "$AUTH_OUTPUT_DIR/statsig" | wc -l) files)" +else + echo "โŒ statsig directory not found" +fi + +# Look for SQLite databases +DB_FILES=$(find "$AUTH_OUTPUT_DIR" -name "*.db" 2>/dev/null | wc -l) +if [ "$DB_FILES" -gt 0 ]; then + echo "โœ… Found $DB_FILES SQLite database files" + find "$AUTH_OUTPUT_DIR" -name "*.db" | head -5 +else + echo "โŒ No SQLite database files found" +fi + +echo "" +echo "๐Ÿ’ก Next steps:" +echo " If authentication tests pass, copy to your main Claude directory:" +echo " cp -r $AUTH_OUTPUT_DIR/* ~/.claude/" +echo " Or update your webhook service to use this authentication directory" \ No newline at end of file diff --git a/src/controllers/githubController.ts b/src/controllers/githubController.ts index cae4d0d..d7873e7 100644 --- a/src/controllers/githubController.ts +++ b/src/controllers/githubController.ts @@ -114,6 +114,12 @@ export const handleWebhook: WebhookHandler = async (req, res) => { const event = req.headers['x-github-event'] as string; const delivery = req.headers['x-github-delivery'] as string; + // Check if request body exists + if (!req.body) { + logger.error('Webhook request missing body'); + return res.status(400).json({ error: 'Missing request body' }); + } + // Log webhook receipt with key details (sanitize user input to prevent log injection) logger.info( { diff --git a/src/index.ts b/src/index.ts index f7002db..6a96beb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,14 @@ import type { import { execSync } from 'child_process'; const app = express(); + +// Configure trust proxy setting based on environment +// Set TRUST_PROXY=true when running behind reverse proxies (nginx, cloudflare, etc.) +const trustProxy = process.env['TRUST_PROXY'] === 'true'; +if (trustProxy) { + app.set('trust proxy', true); +} + const PORT = parseInt(process.env['PORT'] ?? '3003', 10); const appLogger = createLogger('app'); const startupMetrics = new StartupMetrics(); diff --git a/src/services/claudeService.ts b/src/services/claudeService.ts index 8ff0f85..d11aad5 100644 --- a/src/services/claudeService.ts +++ b/src/services/claudeService.ts @@ -55,7 +55,9 @@ export async function processCommand({ const githubToken = secureCredentials.get('GITHUB_TOKEN'); // In test mode, skip execution and return a mock response - if (process.env['NODE_ENV'] === 'test' || !githubToken?.includes('ghp_')) { + // Support both classic (ghp_) and fine-grained (github_pat_) GitHub tokens + const isValidGitHubToken = githubToken && (githubToken.includes('ghp_') || githubToken.includes('github_pat_')); + if (process.env['NODE_ENV'] === 'test' || !isValidGitHubToken) { logger.info( { repo: repoFullName, @@ -378,6 +380,18 @@ function buildDockerArgs({ // Add container name dockerArgs.push('--name', containerName); + // Add Claude authentication directory as a volume mount for syncing + // This allows the entrypoint to copy auth files to a writable location + const hostAuthDir = process.env.CLAUDE_AUTH_HOST_DIR; + if (hostAuthDir) { + // Resolve relative paths to absolute paths for Docker volume mounting + const path = require('path'); + const absoluteAuthDir = path.isAbsolute(hostAuthDir) + ? hostAuthDir + : path.resolve(process.cwd(), hostAuthDir); + dockerArgs.push('-v', `${absoluteAuthDir}:/claude-auth-source:ro`); + } + // Add environment variables as separate arguments Object.entries(envVars) .filter(([, value]) => value !== undefined && value !== '') diff --git a/src/services/githubService.ts b/src/services/githubService.ts index e8fcc6c..09cb4bb 100644 --- a/src/services/githubService.ts +++ b/src/services/githubService.ts @@ -24,7 +24,8 @@ let octokit: Octokit | null = null; function getOctokit(): Octokit | null { if (!octokit) { const githubToken = secureCredentials.get('GITHUB_TOKEN'); - if (githubToken?.includes('ghp_')) { + // Support both classic (ghp_) and fine-grained (github_pat_) GitHub tokens + if (githubToken && (githubToken.includes('ghp_') || githubToken.includes('github_pat_'))) { octokit = new Octokit({ auth: githubToken, userAgent: 'Claude-GitHub-Webhook' diff --git a/src/utils/logger.ts b/src/utils/logger.ts index ad97d5d..022ca7c 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -365,7 +365,7 @@ const logger = pino({ '*.*.*.*.connectionString', '*.*.*.*.DATABASE_URL' ], - censor: '[REDACTED]' + censor: process.env.DISABLE_LOG_REDACTION ? undefined : '[REDACTED]' } });