Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 65 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ notifications. Deploy as AWS Lambda, standard HTTP server, or container.

### Prerequisites

* GitHub App ([setup guide](#github-app-setup))
* Go ≥ 1.24
* **Optional**: Okta API Service app for group sync
* **Optional**: Slack app for notifications
* GitHub App ([setup guide](docs/github-app-setup.md))
* **Optional**: Okta API Service app ([setup guide](docs/okta-setup.md))
* **Optional**: Slack app ([setup guide](docs/slack-setup.md))

### Deployment Options

Expand Down Expand Up @@ -176,36 +176,14 @@ Map Okta groups to GitHub teams using JSON rules:
Okta-synced teams and sends Slack notifications. Enabled by default when
sync is enabled.

## Okta Setup
## Integration Setup

Create an API Services application in Okta Admin Console:
Detailed setup guides for each integration:

1. **Applications** → **Create App Integration** → **API Services**
2. Name: `github-bot-api-service`
3. **Client Credentials**:
- Authentication: **Public key / Private key**
- Generate and download private key (PEM format)
- Note the Client ID
4. **Okta API Scopes**: Grant `okta.groups.read` and `okta.users.read`

Use the Client ID and private key in your environment variables.

## GitHub App Setup

Create a GitHub App in your organization settings:

1. **Developer settings** → **GitHub Apps** → **New GitHub App**
2. **Basic info**:
- Name: `github-ops-app`
- Webhook URL: Your API Gateway URL
- Webhook secret: Generate and save for `APP_GITHUB_WEBHOOK_SECRET`
3. **Permissions**:
- Repository: Pull requests (Read), Contents (Read)
- Organization: Members (Read & write), Administration (Read)
4. **Events**: Subscribe to Pull request, Team, Membership
5. Generate and download private key (`.pem` file)
6. Install app to your organization
7. Note: **App ID**, **Installation ID** (from install URL), **Private key**
- [GitHub App Setup](docs/github-app-setup.md) - Create and install the GitHub
App with required permissions
- [Okta Setup](docs/okta-setup.md) - Configure API Services app for group sync
- [Slack Setup](docs/slack-setup.md) - Create Slack app for notifications

## Development

Expand Down Expand Up @@ -243,15 +221,63 @@ CMD ["/server"]

## How It Works

**Okta Sync**: EventBridge triggers sync → Fetch Okta groups → Apply rules →
Update GitHub teams → Detect orphaned users → Send Slack reports. Automatically
reconciles when external team changes are detected. Only syncs ACTIVE Okta
users, skips external collaborators, and prevents mass removal during outages
via safety threshold. Orphaned user detection identifies org members not in any
synced teams.
```
┌─────────────────────────────────────────────────┐
│ github-ops-app │
│ │
┌──────────────┐ │ ┌───────────────────────────────────────────┐ │
│ GitHub │ webhooks │ │ Webhook Handler │ │
│ │───────────────▶ • PR merge events │ │
│ • PR merge │ │ │ • Team membership changes │ │
│ • Team edit │ │ │ • Signature verification │ │
└──────────────┘ │ └─────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ PR Compliance Check │ │
┌──────────────┐ │ │ • Branch protection verification │────────┐
│ Okta │ │ │ • Required checks validation │ │ │
│ │ │ │ • Bypass detection │ │ │
│ • Groups │◀──────────────┴─────────────────────────────────────────┘ │ │
│ • Users │ │ │ │
└──────────────┘ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Okta Sync Engine │ │ │
│ │ │ • Match groups via rules │ │ │
└─────────────────────────▶ • Create/update GitHub teams │ │ │
│ │ • Sync team membership │ │ │
│ │ • Orphaned user detection │────────┤
│ │ • Safety threshold protection │ │ │
┌──────────────┐ │ └─────────────────────────────────────────┘ │ │
│ GitHub │ │ │ │ │
│ Teams API │◀─────────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ • Teams │ └─────────────────────────────────────────────────┘ │
│ • Members │ │
└──────────────┘ │
┌──────────────┐ │
│ Slack │◀─────────────────────────────────────┘
│ │ Notifications
│ • Alerts │ • PR violations
│ • Reports │ • Sync reports
└──────────────┘ • Orphaned users
```

### Okta Sync Flow

1. **Trigger**: Scheduled cron/EventBridge or team membership webhook
2. **Fetch**: Query Okta groups matching configured rules
3. **Match**: Apply sync rules to map Okta groups → GitHub teams
4. **Sync**: Add/remove GitHub team members (ACTIVE Okta users only)
5. **Safety**: Abort if removal ratio exceeds threshold (default 50%)
6. **Report**: Send Slack notification with changes and orphaned users

### PR Compliance Flow

**PR Compliance**: Webhook on PR merge → Verify signature → Check branch
protection rules → Detect bypasses → Notify Slack if violations found.
1. **Receive**: GitHub webhook on PR merge to monitored branch
2. **Verify**: Validate webhook signature (HMAC-SHA256)
3. **Check**: Query branch protection rules and required status checks
4. **Detect**: Identify bypasses (admin override, missing reviews, failed checks)
5. **Notify**: Send Slack alert with violation details

## Troubleshooting

Expand Down
165 changes: 165 additions & 0 deletions docs/github-app-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# GitHub App Setup

This guide walks through creating and installing a GitHub App for github-ops-app.

## Prerequisites

- GitHub organization with admin access

## Step 1: Create the GitHub App

1. Navigate to your organization's settings:
- Go to `https://github.com/organizations/YOUR_ORG/settings/apps`
- Or: **Organization** → **Settings** → **Developer settings** → **GitHub Apps**

2. Click **New GitHub App**

3. Fill in the basic information:

| Field | Value |
|-----------------------|-------------------------------------------------|
| GitHub App name | `github-ops-app` (must be unique across GitHub) |
| Homepage URL | Your organization's URL or repo URL |
| Webhook > Webhook URL | Leave blank for now |
| Webhook > Secret | Generate a strong secret (save this for later) |
| Webhook > Active | **Uncheck** to disable webhooks initially |

> **Note**: Disable webhooks during creation since you may not know your
> endpoint URL until after deployment. You'll configure webhooks and
> subscribe to events in [Step 7](#step-7-configure-webhook-and-events).

4. Under **Permissions**, set the following:
- Repository Permissions
- Contents: Read
- Read branch protection rules
- Pull requests: Read
- Access PR details for compliance
- Organization Permissions
- Administration: Read
- Read organization settings
- Members: Read/Write
- Manage team membership

4. Under Set installation scope:
- Where can this GitHub App be installed?: Only on this account

5. Click **Create GitHub App**

## Step 2: Generate Private Key

After creating the app:

1. Scroll to **Private keys** section
2. Click **Generate a private key**
3. Save the downloaded `.pem` file securely
4. This file is used for `APP_GITHUB_APP_PRIVATE_KEY` or
`APP_GITHUB_APP_PRIVATE_KEY_PATH`

## Step 3: Note Your App ID

On the app's settings page, find and save:

- **App ID** - numeric ID displayed near the top (e.g., `123456`)

## Step 4: Install the App

1. In the left sidebar, click **Install App**
2. Select your organization
3. Choose repository access:
- **All repositories** - recommended for org-wide PR compliance
- **Only select repositories** - if limiting scope
4. Click **Install**

## Step 5: Get Installation ID

After installation, you'll be redirected to a URL like:
```
https://github.com/organizations/YOUR_ORG/settings/installations/12345678
```

The number at the end (`12345678`) is your **Installation ID**.

Alternatively, use the GitHub API:
```bash
# List installations (requires app JWT authentication)
curl -H "Authorization: Bearer YOUR_JWT" \
https://api.github.com/app/installations
```

## Step 6: Configure Environment Variables

Set these environment variables in your deployment:

```bash
# Required GitHub configuration
APP_GITHUB_APP_ID=123456
APP_GITHUB_INSTALLATION_ID=12345678
APP_GITHUB_ORG=your-org-name
APP_GITHUB_WEBHOOK_SECRET=your-webhook-secret

# Private key (choose one method)
APP_GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"

# Or use a file path
APP_GITHUB_APP_PRIVATE_KEY_PATH=/path/to/private-key.pem

# Or use AWS SSM parameter
APP_GITHUB_APP_PRIVATE_KEY=arn:aws:ssm:us-east-1:123456789:parameter/github-bot/private-key
```

## Step 7: Configure Webhook and Events

After deploying your server, configure and enable webhooks:

1. Go to your GitHub App settings:
`https://github.com/organizations/YOUR_ORG/settings/apps/YOUR_APP`
2. On the **General** tab, under **Webhook**:
- Set **Webhook URL** to your endpoint:
- Lambda: `https://xxx.execute-api.region.amazonaws.com/webhooks`
- Server: `https://your-domain.com/webhooks`
- Check **Active** to enable webhooks
- Click **Save changes**
3. Go to the **Permissions & events** tab
4. Scroll to **Subscribe to events** and check:
- [x] **Pull request** - PR open, close, merge events
- [x] **Team** - Team creation, deletion, changes
- [x] **Membership** - Team membership changes
5. Click **Save changes**

## Verification

Test your setup:

1. **Webhook delivery**: Check **Settings** → **Developer settings** →
**GitHub Apps** → your app → **Advanced** → **Recent Deliveries**

2. **Create a test PR**: Open and merge a PR to a monitored branch to verify
webhook reception

3. **Check logs**: Verify your application receives and processes the webhook

## Troubleshooting

### Webhook signature verification failed

- Verify `APP_GITHUB_WEBHOOK_SECRET` matches the secret in GitHub App settings
- Check for whitespace or encoding issues in the secret

### 401 Unauthorized from GitHub API

- Verify the private key matches the one generated for this app
- Check that the app is installed on the target organization
- Ensure `APP_GITHUB_INSTALLATION_ID` is correct

### Missing permissions error

- Re-check the app's permission settings
- After changing permissions, organization admins may need to re-approve

### Webhook not received

- Verify the webhook URL is accessible from the internet
- Check the webhook URL doesn't have a trailing slash mismatch
- Review recent deliveries in GitHub App settings for error details
Loading