I did not notice in #1508 that the hydra evaluator now crashed because the hydra config is shared between all components, all of them need to be able to read the secret.
169 lines
4.9 KiB
Markdown
169 lines
4.9 KiB
Markdown
# Webhook Authentication Migration Guide
|
|
|
|
This guide helps Hydra administrators migrate from unauthenticated webhooks to authenticated webhooks to secure their Hydra instances against unauthorized job evaluations.
|
|
|
|
## Why Migrate?
|
|
|
|
Currently, Hydra's webhook endpoints (`/api/push-github` and `/api/push-gitea`) accept any POST request without authentication. This vulnerability allows:
|
|
- Anyone to trigger expensive job evaluations
|
|
- Potential denial of service through repeated requests
|
|
- Manipulation of build timing and scheduling
|
|
|
|
## Step-by-Step Migration for NixOS
|
|
|
|
### 1. Create Webhook Configuration
|
|
|
|
Create a webhook secrets configuration file with the generated secrets:
|
|
|
|
```bash
|
|
# Create the secrets configuration file with inline secret generation
|
|
cat > /var/lib/hydra/secrets/webhook-secrets.conf <<EOF
|
|
<github>
|
|
secret = $(openssl rand -hex 32)
|
|
</github>
|
|
<gitea>
|
|
secret = $(openssl rand -hex 32)
|
|
</gitea>
|
|
EOF
|
|
|
|
# Set secure permissions
|
|
chmod 0440 /var/lib/hydra/secrets/webhook-secrets.conf
|
|
chown hydra:hydra /var/lib/hydra/secrets/webhook-secrets.conf
|
|
```
|
|
|
|
**Important**: Save the generated secrets to configure them in GitHub/Gitea later. You can view them with:
|
|
```bash
|
|
cat /var/lib/hydra/secrets/webhook-secrets.conf
|
|
```
|
|
|
|
Then update your NixOS configuration to include the webhook configuration:
|
|
|
|
```nix
|
|
{
|
|
services.hydra-dev = {
|
|
enable = true;
|
|
hydraURL = "https://hydra.example.com";
|
|
notificationSender = "hydra@example.com";
|
|
|
|
extraConfig = ''
|
|
<webhooks>
|
|
Include /var/lib/hydra/secrets/webhook-secrets.conf
|
|
</webhooks>
|
|
'';
|
|
};
|
|
}
|
|
```
|
|
|
|
For multiple secrets (useful for rotation or multiple environments), update your webhook-secrets.conf:
|
|
|
|
```apache
|
|
<github>
|
|
secret = your-github-webhook-secret-prod
|
|
secret = your-github-webhook-secret-staging
|
|
</github>
|
|
<gitea>
|
|
secret = your-gitea-webhook-secret
|
|
</gitea>
|
|
```
|
|
|
|
### 2. Deploy Configuration
|
|
|
|
Apply the NixOS configuration:
|
|
|
|
```bash
|
|
nixos-rebuild switch
|
|
```
|
|
|
|
This will automatically restart Hydra services with the new configuration.
|
|
|
|
### 3. Verify Configuration
|
|
|
|
Check Hydra's logs to ensure secrets were loaded successfully:
|
|
|
|
```bash
|
|
journalctl -u hydra-server | grep -i webhook
|
|
```
|
|
|
|
You should not see warnings about webhook authentication not being configured.
|
|
|
|
### 4. Update Your Webhooks
|
|
|
|
#### GitHub
|
|
1. Navigate to your repository settings: `https://github.com/<owner>/<repo>/settings/hooks`
|
|
2. Edit your existing Hydra webhook
|
|
3. In the "Secret" field, paste the content of `/var/lib/hydra/secrets/github-webhook-secret`
|
|
4. Click "Update webhook"
|
|
5. GitHub will send a ping event to verify the configuration
|
|
|
|
#### Gitea
|
|
1. Navigate to your repository webhook settings
|
|
2. Edit your existing Hydra webhook
|
|
3. In the "Secret" field, paste the content of `/var/lib/hydra/secrets/gitea-webhook-secret`
|
|
4. Click "Update Webhook"
|
|
5. Use the "Test Delivery" button to verify the configuration
|
|
|
|
### 5. Test the Configuration
|
|
|
|
After updating each webhook:
|
|
1. Make a test commit to trigger the webhook
|
|
2. Check Hydra's logs for successful authentication
|
|
3. Verify the evaluation was triggered in Hydra's web interface
|
|
|
|
## Troubleshooting
|
|
|
|
### 401 Unauthorized Errors
|
|
|
|
If webhooks start failing with 401 errors:
|
|
- Verify the secret in the Git forge matches the file content exactly
|
|
- Check file permissions: `ls -la /var/lib/hydra/secrets/`
|
|
- Ensure no extra whitespace in secret files
|
|
- Check Hydra logs for specific error messages
|
|
|
|
### Webhook Still Unauthenticated
|
|
|
|
If you see warnings about unauthenticated webhooks after configuration:
|
|
- Verify the configuration syntax in your NixOS module
|
|
- Ensure the NixOS configuration was successfully applied
|
|
- Check that the webhook-secrets.conf file exists and is readable by the Hydra user
|
|
- Verify the Include path is correct in your hydra.conf
|
|
- Check the syntax of your webhook-secrets.conf file
|
|
|
|
### Testing Without Git Forge
|
|
|
|
You can test webhook authentication using curl:
|
|
|
|
```bash
|
|
# Read the secret
|
|
SECRET=$(cat /var/lib/hydra/secrets/github-webhook-secret)
|
|
|
|
# Create test payload
|
|
PAYLOAD='{"ref":"refs/heads/main","repository":{"clone_url":"https://github.com/test/repo.git"}}'
|
|
|
|
# Calculate signature
|
|
SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)"
|
|
|
|
# Send authenticated request
|
|
curl -X POST https://your-hydra/api/push-github \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Hub-Signature-256: $SIGNATURE" \
|
|
-d "$PAYLOAD"
|
|
```
|
|
|
|
For Gitea (no prefix in signature):
|
|
```bash
|
|
# Read the secret
|
|
SECRET=$(cat /var/lib/hydra/secrets/gitea-webhook-secret)
|
|
|
|
# Create test payload
|
|
PAYLOAD='{"ref":"refs/heads/main","repository":{"clone_url":"https://gitea.example.com/test/repo.git"}}'
|
|
|
|
# Calculate signature
|
|
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
|
|
|
|
# Send authenticated request
|
|
curl -X POST https://your-hydra/api/push-gitea \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Gitea-Signature: $SIGNATURE" \
|
|
-d "$PAYLOAD"
|
|
```
|