Skip to content

mmob-tech/webhook

Repository files navigation

GitHub Webhook Handler

This project is an AWS Lambda function that processes GitHub webhook events for comprehensive repository monitoring and automation. It validates incoming event data and triggers appropriate actions based on the event type, supporting all major GitHub webhook events with secure signature validation.

Project Structure

webhook
├── src
│   ├── handler.ts          # Entry point for the AWS Lambda function
│   ├── handler.test.ts     # Comprehensive test suite for all webhook events
│   ├── types
│   │   └── github.ts       # TypeScript interfaces for GitHub webhook events
│   └── utils
│       ├── health.ts       # Health check fun tion for the webhook
        ├── logging.ts          # Advanced logging utilities with structured event data
│       ├── validator.ts    # Utility functions for validating webhook data
│       └── signature.ts    # Webhook signature verification utilities
├── package.json            # npm configuration file
├── tsconfig.json           # TypeScript configuration file
├── serverless.yml          # Serverless Framework configuration file
├── .env.example            # Environment variable template
└── README.md               # Project documentation

Supported GitHub Webhook Events

This handler supports all major GitHub webhook events, organized by category:

Core Repository Events

  • ping - Webhook ping event for testing connectivity
  • repository - Repository created, deleted, archived, etc.
  • push - Code pushed to repository
  • create - Branch or tag created
  • delete - Branch or tag deleted
  • fork - Repository forked
  • star - Repository starred/unstarred
  • watch - Repository watched/unwatched
  • public - Repository made public

Pull Request Events

  • pull_request - Pull request opened, closed, merged, etc.
  • pull_request_review - Pull request review submitted, edited, dismissed
  • pull_request_review_comment - Comments on pull request reviews

Issue Events

  • issues - Issue opened, closed, edited, labeled, etc.
  • issue_comment - Comments on issues and pull requests

Code & Comments

  • commit_comment - Comments on commits
  • status - Commit status updates from CI/CD systems
  • gollum - Wiki page updates

Workflow & Actions

  • workflow_run - GitHub Actions workflow runs
  • workflow_job - Individual workflow job status
  • check_suite - Check suite created, completed, etc.
  • check_run - Individual check run status

Releases & Packages

  • release - Release published, edited, deleted
  • package - GitHub Packages published, updated

Organization & Team Management

  • organization - Organization settings changed
  • team - Team created, deleted, modified
  • member - Organization member added, removed

Deployment Events

  • deployment - Deployment created
  • deployment_status - Deployment status updated

Discussion Events

  • discussion - Repository discussion created, edited, etc.
  • discussion_comment - Comments on discussions

Project Management (4)

  • milestone - Milestone creation, editing, deletion
  • label - Repository label management
  • project - Classic project board events
  • project_card - Project card movements
  • project_column - Project column management

Security Events (4)

  • dependabot_alert - Dependabot vulnerability alerts
  • security_advisory - Security advisory publications
  • code_scanning_alert - Code scanning security alerts
  • secret_scanning_alert - Secret scanning alerts

Advanced Events (6)

  • audit_log_streaming - Organization audit logs
  • branch_protection_rule - Branch protection rule changes
  • repository_dispatch - Custom repository dispatch events
  • repository_vulnerability_alert - Repository vulnerability alerts
  • marketplace_purchase - GitHub Marketplace purchases
  • installation - GitHub App installations
  • installation_repositories - GitHub App repository access changes

Setup Instructions

1. Prerequisites

  • Node.js 20.x or later
  • AWS CLI configured
  • Serverless Framework installed globally

2. Install Dependencies

npm install

3. Environment Configuration

Create a .env file for local development:

# Copy the example file
cp .env.example .env

# Edit the file with your values
GITHUB_WEBHOOK_SECRET=your-github-secret-webhook

Generate a secure webhook secret:

# Use openssl to generate a secure random string
openssl rand -base64 32

# Or use Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

4. AWS Configuration

# Set environment variable for deployment
export GITHUB_WEBHOOK_SECRET="your-super-secret-webhook-key-here"

This project reads the webhook secret from serverless.yml via:

GITHUB_WEBHOOK_SECRET: ${env:GITHUB_WEBHOOK_SECRET}

That means you can rotate the secret manually by changing the environment value and redeploying.

5. Deploy the Lambda Function

# Deploy to AWS
npm run deploy

6. Test the Deployment

# Run comprehensive test suite
npm test

# Run tests with coverage
npm run test:coverage

# Test specific event types
npm test -- --testNamePattern="Pull Request"

Rotate Webhook Secret (Manual Steps)

Use these steps any time you need to rotate a compromised or expired webhook secret.

  1. Generate a new secret.
openssl rand -base64 32
  1. Update the webhook secret in GitHub.
  • Repository(Simi): Settings -> Webhooks -> select webhook -> Edit -> Change secret
  • Replace the Secret value and save.
  1. Update your deployment environment variable with the same new value.
export GITHUB_WEBHOOK_SECRET="paste-new-secret-here"
  • AWS(mmob-dev): Lambda -> Functions -> select webhook -> Environment variables -> GITHUB_WEBHOOK_SECRET
  • Replace the Secret value and save.
  1. Redeploy Lambda.
npm run deploy

For production profile/stage:

export GITHUB_WEBHOOK_SECRET="paste-new-secret-here"
npm run deploy:prod
  1. Verify delivery.
  • In GitHub Webhook "Recent Deliveries", confirm new deliveries return 200.
  • If deliveries fail signature checks, confirm GitHub secret and GITHUB_WEBHOOK_SECRET match exactly.

GitHub Webhook Configuration

Repository Webhooks

  1. Navigate to Repository Settings

    • Go to your repository on GitHub
    • Click on "Settings" tab
    • Select "Webhooks" from the left sidebar
  2. Add New Webhook

    • Click "Add webhook"
    • Payload URL: Your Lambda endpoint (from serverless deploy output)
    • Content type: application/json
    • Secret: Enter your webhook secret (same as GITHUB_WEBHOOK_SECRET)
    • SSL verification: ✅ Enable SSL verification
    • Which events: Select individual events or "Send me everything"
  3. Event Selection Examples

    Repository events: repository, push, create, delete, fork, star, watch
    Pull Request events: pull_request, pull_request_review, pull_request_review_comment
    Issue events: issues, issue_comment
    Workflow events: workflow_run, workflow_job, check_suite, check_run
    

Organization Webhooks

  1. Navigate to Organization Settings

    • Go to your organization on GitHub
    • Click on "Settings" tab
    • Select "Webhooks" from the left sidebar
  2. Configure Organization-Wide Events

    • Follow same setup as repository webhooks
    • Additional events: organization, team, member
    • Audit log streaming: Enable for audit_log_streaming events

Webhook Security Configuration

{
  "name": "GitHub Webhook Handler",
  "url": "https://your-api-gateway-url.amazonaws.com/dev/webhook",
  "content_type": "application/json",
  "secret": "your-super-secret-webhook-key-here",
  "insecure_ssl": false,
  "events": ["push", "pull_request", "issues", "workflow_run"]
}

Security Implementation

Signature Validation Process

  1. GitHub generates signature using your webhook secret
  2. Signature sent in header as X-Hub-Signature-256
  3. Lambda validates signature using HMAC-SHA256
  4. Timing-safe comparison prevents timing attacks
  5. Request rejected if signature doesn't match

Signature Validation Code

// Verify GitHub webhook signature
const verifyGitHubSignature = (
  payload: string,
  signature: string,
  secret: string,
): boolean => {
  try {
    const expectedSignature = `sha256=${crypto
      .createHmac("sha256", secret)
      .update(payload, "utf8")
      .digest("hex")}`;

    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature),
    );
  } catch (error) {
    return false;
  }
};

Response Format

Successful Responses

{
  "statusCode": 200,
  "body": {
    "message": "Event type processed successfully",
    "event_data": {
      "repository": "my-org/test-repo",
      "action": "opened",
      "details": "..."
    }
  }
}

Error Responses

Missing Signature:

{
  "statusCode": 401,
  "body": {
    "message": "Missing signature header"
  }
}

Invalid Signature:

{
  "statusCode": 401,
  "body": {
    "message": "Invalid signature"
  }
}

Unsupported Event:

{
  "statusCode": 400,
  "body": {
    "message": "Unsupported GitHub event: event_name",
    "supported_events": [
      "ping",
      "repository",
      "push",
      "pull_request",
      "issues",
      "..."
    ]
  }
}

Configuration Error:

{
  "statusCode": 500,
  "body": {
    "message": "Webhook secret not configured"
  }
}

Development

Adding New Event Types

  1. Update handler.ts - Add new event case with signature validation
  2. Update types/github.ts - Add TypeScript interfaces
  3. Add comprehensive tests - Include signature validation tests
  4. Update README.md - Document the new event type

Testing with Signatures

// Test pattern for all webhook events
const body = JSON.stringify(payload);
const signature = generateWebhookSignature(body, testSecret);

mockEvent.headers["X-GitHub-Event"] = "event_name";
mockEvent.headers["X-Hub-Signature-256"] = signature;
mockEvent.body = body;

await webhookHandler(mockEvent, mockContext, mockCallback);

Local Development

# Install dependencies
npm install

# Run tests with signature validation
npm test

# Run tests in watch mode
npm run test:watch

# Type checking
npm run type-check

# Build project
npm run build

# Local development with serverless-offline
serverless offline

Testing Webhook Signatures Locally

# Test signature generation
node -e "
const crypto = require('crypto');
const payload = JSON.stringify({test: 'data'});
const secret = 'your-secret';
const signature = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
console.log('Signature:', signature);
"

Event Processing Examples

Pull Request Events (with Security)

// Signature validation happens before event processing
case "pull_request":
  await processPullRequestEvent(payload as GitHubPullRequestPayload);
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: `Pull request ${payload.action} event processed`,
      pr_number: payload.pull_request.number,
      title: payload.pull_request.title,
      action: payload.action,
    })
  };

Push Events (with Security)

// All events require valid signatures
case "push":
  await processPushEvent(payload as GitHubPushPayload);
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: "Push event processed",
      ref: payload.ref,
      commits_count: payload.commits.length,
      repository: payload.repository.full_name,
    })
  };

Workflow Events (with Security)

// Secure workflow event processing
case "workflow_run":
  await processWorkflowRunEvent(payload as GitHubWorkflowRunPayload);
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: `Workflow ${payload.action} event processed`,
      workflow_name: payload.workflow_run.name,
      conclusion: payload.workflow_run.conclusion,
      action: payload.action,
    })
  };

Monitoring and Logging

CloudWatch Metrics

The handler automatically logs:

  • Successful webhook processing with event details
  • Signature validation failures with source IP
  • Processing errors with full error context
  • Performance metrics for each event type

Log Examples

INFO: Webhook signature validated successfully
INFO: Received GitHub webhook event: pull_request
INFO: Processing pull request opened event
INFO: Pull request #123 opened in my-org/test-repo

ERROR: Invalid webhook signature from IP: 192.168.1.1
ERROR: Missing X-Hub-Signature-256 header
ERROR: Webhook secret not configured

Alerting Setup

# CloudWatch Alarms
SignatureValidationFailures:
  Type: AWS::CloudWatch::Alarm
  Properties:
    AlarmName: GitHub-Webhook-Invalid-Signatures
    MetricName: SignatureValidationFailures
    Threshold: 5
    ComparisonOperator: GreaterThanThreshold
    EvaluationPeriods: 2
    Period: 300

Troubleshooting

Common Issues

  1. Signature Validation Failures

    • Verify webhook secret matches in GitHub and Lambda
    • Check for trailing whitespace in secret
    • Ensure content-type is application/json
  2. Missing Environment Variables

    • Verify GITHUB_WEBHOOK_SECRET is set
    • Check serverless.yml environment configuration
    • Validate AWS parameter store/secrets manager setup
  3. Deployment Issues

    • Ensure AWS credentials are configured
    • Check IAM permissions for Lambda execution
    • Verify API Gateway configuration
  4. Testing Issues

    • Use correct signature generation in tests
    • Verify test secret matches handler expectations
    • Check mock setup for all required headers

Debug Commands

# Check environment variables
serverless info

# View Lambda logs
serverless logs -f webhookHandler

# Test health check endpoint
curl -v https://yyk1br4jof.execute-api.eu-west-2.amazonaws.com/dev/health


# Test specific webhook event
curl -X POST https://yyk1br4jof.execute-api.eu-west-2.amazonaws.com/dev/webhook \
  -H "Content-Type: application/json" \
  -H "X-GitHub-Event: ping" \
  -H "X-Hub-Signature-256: sha256=your-signature" \
  -d '{"zen":"test"}'

Security Considerations

  • Never commit webhook secrets to version control
  • Test signature validation for all new event types
  • Follow secure coding practices
  • Review security implications of changes

🔒 Security Notice: This webhook handler implements GitHub's recommended security practices including HMAC-SHA256 signature validation and timing-safe comparison. It's designed for production use in enterprise environments with comprehensive error handling, logging, and monitoring capabilities.

⚠️ Important: Always use HTTPS endpoints and never expose webhook secrets. Rotate secrets regularly and monitor for unauthorized access attempts.

About

Event webhook for mmob

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors