re-uploading work
This commit is contained in:
497
docs/webhooks/webhook-manual-testing.md
Normal file
497
docs/webhooks/webhook-manual-testing.md
Normal file
@@ -0,0 +1,497 @@
|
||||
# Webhook System Manual Testing Guide
|
||||
|
||||
**Last Updated**: 2026-01-20
|
||||
**Status**: Phase 2 Complete
|
||||
|
||||
This guide provides step-by-step instructions for manually testing the webhook system functionality.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Attune API service running (default: `http://localhost:8080`)
|
||||
2. Database with migrations applied
|
||||
3. Test user account registered
|
||||
4. `curl` or similar HTTP client
|
||||
5. `jq` for JSON formatting (optional)
|
||||
|
||||
---
|
||||
|
||||
## Setup Test Environment
|
||||
|
||||
### 1. Start the API Service
|
||||
|
||||
```bash
|
||||
cd crates/api
|
||||
cargo run
|
||||
```
|
||||
|
||||
### 2. Register a Test User (if not already registered)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/auth/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "webhook_test_user",
|
||||
"email": "webhook@example.com",
|
||||
"password": "test_password_123"
|
||||
}'
|
||||
```
|
||||
|
||||
### 3. Login and Get JWT Token
|
||||
|
||||
```bash
|
||||
TOKEN=$(curl -s -X POST http://localhost:8080/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "webhook_test_user",
|
||||
"password": "test_password_123"
|
||||
}' | jq -r '.data.access_token')
|
||||
|
||||
echo "Token: $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 1: Enable Webhooks for Existing Trigger
|
||||
|
||||
### Step 1: Create a Test Pack
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/packs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ref": "webhook_test",
|
||||
"label": "Webhook Test Pack",
|
||||
"description": "Pack for webhook testing",
|
||||
"version": "1.0.0",
|
||||
"enabled": true
|
||||
}' | jq
|
||||
```
|
||||
|
||||
### Step 2: Create a Test Trigger
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ref": "webhook_test.github_push",
|
||||
"pack_ref": "webhook_test",
|
||||
"label": "GitHub Push Event",
|
||||
"description": "Trigger for GitHub push webhooks",
|
||||
"enabled": true,
|
||||
"param_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {"type": "string"},
|
||||
"branch": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}' | jq
|
||||
```
|
||||
|
||||
### Step 3: Enable Webhooks
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.github_push/webhooks/enable \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": 1,
|
||||
"ref": "webhook_test.github_push",
|
||||
"label": "GitHub Push Event",
|
||||
"webhook_enabled": true,
|
||||
"webhook_key": "wh_abc123...xyz789",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- `webhook_enabled` is `true`
|
||||
- `webhook_key` starts with `wh_`
|
||||
- `webhook_key` is 40+ characters long
|
||||
|
||||
### Step 4: Save Webhook Key
|
||||
|
||||
```bash
|
||||
WEBHOOK_KEY=$(curl -s -X GET http://localhost:8080/api/v1/triggers/webhook_test.github_push \
|
||||
-H "Authorization: Bearer $TOKEN" | jq -r '.data.webhook_key')
|
||||
|
||||
echo "Webhook Key: $WEBHOOK_KEY"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 2: Send Webhook Events
|
||||
|
||||
### Step 1: Send a Basic Webhook
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"payload": {
|
||||
"repository": "attune/automation-platform",
|
||||
"branch": "main",
|
||||
"commits": [
|
||||
{
|
||||
"sha": "abc123",
|
||||
"message": "Add webhook support",
|
||||
"author": "developer@example.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}' | jq
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"event_id": 1,
|
||||
"trigger_ref": "webhook_test.github_push",
|
||||
"received_at": "2026-01-20T15:30:00Z",
|
||||
"message": "Webhook received successfully"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- Response status is 200 OK
|
||||
- `event_id` is a positive integer
|
||||
- `trigger_ref` matches the trigger
|
||||
- `received_at` is a valid ISO timestamp
|
||||
|
||||
### Step 2: Send Webhook with Metadata
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-GitHub-Event: push" \
|
||||
-H "X-GitHub-Delivery: abc-123-def-456" \
|
||||
-d '{
|
||||
"payload": {
|
||||
"action": "synchronize",
|
||||
"number": 42,
|
||||
"pull_request": {
|
||||
"title": "Add new feature",
|
||||
"state": "open"
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"X-GitHub-Event": "push",
|
||||
"X-GitHub-Delivery": "abc-123-def-456"
|
||||
},
|
||||
"source_ip": "192.30.252.1",
|
||||
"user_agent": "GitHub-Hookshot/abc123"
|
||||
}' | jq
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- Event created successfully
|
||||
- Metadata is stored in event config
|
||||
|
||||
### Step 3: Verify Event Was Created
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8080/api/v1/events \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected:** Events list includes the webhook-triggered events
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 3: Webhook Key Management
|
||||
|
||||
### Step 1: Regenerate Webhook Key
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.github_push/webhooks/regenerate \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"webhook_enabled": true,
|
||||
"webhook_key": "wh_new_key_different_from_old",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- New `webhook_key` is different from the old one
|
||||
- Still starts with `wh_`
|
||||
|
||||
### Step 2: Verify Old Key No Longer Works
|
||||
|
||||
```bash
|
||||
# Try to use the old webhook key (should fail)
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"payload": {"test": "data"}}' | jq
|
||||
```
|
||||
|
||||
**Expected:** 404 Not Found - "Invalid webhook key"
|
||||
|
||||
### Step 3: Get New Key and Test
|
||||
|
||||
```bash
|
||||
NEW_WEBHOOK_KEY=$(curl -s -X GET http://localhost:8080/api/v1/triggers/webhook_test.github_push \
|
||||
-H "Authorization: Bearer $TOKEN" | jq -r '.data.webhook_key')
|
||||
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$NEW_WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"payload": {"test": "with new key"}}' | jq
|
||||
```
|
||||
|
||||
**Expected:** 200 OK - Event created successfully
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 4: Disable Webhooks
|
||||
|
||||
### Step 1: Disable Webhooks
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.github_push/webhooks/disable \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"webhook_enabled": false,
|
||||
"webhook_key": null,
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- `webhook_enabled` is `false`
|
||||
- `webhook_key` is `null`
|
||||
|
||||
### Step 2: Verify Webhook No Longer Accepts Events
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$NEW_WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"payload": {"test": "should fail"}}' | jq
|
||||
```
|
||||
|
||||
**Expected:** 404 Not Found - "Invalid webhook key"
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 5: Error Handling
|
||||
|
||||
### Test 1: Invalid Webhook Key
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/wh_invalid_key_xyz \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"payload": {}}' | jq
|
||||
```
|
||||
|
||||
**Expected:** 404 Not Found
|
||||
|
||||
### Test 2: Regenerate Without Enabling First
|
||||
|
||||
```bash
|
||||
# Create new trigger without webhooks
|
||||
curl -X POST http://localhost:8080/api/v1/triggers \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ref": "webhook_test.no_webhook",
|
||||
"pack_ref": "webhook_test",
|
||||
"label": "No Webhook Trigger",
|
||||
"enabled": true
|
||||
}' | jq
|
||||
|
||||
# Try to regenerate without enabling
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.no_webhook/webhooks/regenerate \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected:** 400 Bad Request - "Webhooks are not enabled for this trigger"
|
||||
|
||||
### Test 3: Management Endpoints Without Auth
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.github_push/webhooks/enable | jq
|
||||
```
|
||||
|
||||
**Expected:** 401 Unauthorized
|
||||
|
||||
---
|
||||
|
||||
## Test Scenario 6: Integration with Rules
|
||||
|
||||
### Step 1: Create a Rule for Webhook Trigger
|
||||
|
||||
```bash
|
||||
# First, create a test action
|
||||
curl -X POST http://localhost:8080/api/v1/actions \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ref": "webhook_test.log_event",
|
||||
"pack_ref": "webhook_test",
|
||||
"label": "Log Webhook Event",
|
||||
"description": "Logs webhook events",
|
||||
"entrypoint": "echo \"Webhook received: {{event.payload}}\"",
|
||||
"runtime_ref": "shell",
|
||||
"enabled": true
|
||||
}' | jq
|
||||
|
||||
# Create rule
|
||||
curl -X POST http://localhost:8080/api/v1/rules \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ref": "webhook_test.on_github_push",
|
||||
"pack_ref": "webhook_test",
|
||||
"label": "On GitHub Push",
|
||||
"description": "Execute action when GitHub push webhook received",
|
||||
"trigger_ref": "webhook_test.github_push",
|
||||
"action_ref": "webhook_test.log_event",
|
||||
"enabled": true
|
||||
}' | jq
|
||||
```
|
||||
|
||||
### Step 2: Re-enable Webhooks
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/triggers/webhook_test.github_push/webhooks/enable \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
|
||||
WEBHOOK_KEY=$(curl -s -X GET http://localhost:8080/api/v1/triggers/webhook_test.github_push \
|
||||
-H "Authorization: Bearer $TOKEN" | jq -r '.data.webhook_key')
|
||||
```
|
||||
|
||||
### Step 3: Send Webhook and Verify Rule Execution
|
||||
|
||||
```bash
|
||||
# Send webhook
|
||||
curl -X POST http://localhost:8080/api/v1/webhooks/$WEBHOOK_KEY \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"payload": {
|
||||
"repository": "test/repo",
|
||||
"branch": "main"
|
||||
}
|
||||
}' | jq
|
||||
|
||||
# Wait a moment for processing, then check executions
|
||||
sleep 2
|
||||
|
||||
curl -X GET http://localhost:8080/api/v1/executions \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
**Expected:** Execution created for the `webhook_test.log_event` action
|
||||
|
||||
---
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
### Webhook Enablement
|
||||
- [ ] Can enable webhooks for a trigger
|
||||
- [ ] Webhook key is generated and returned
|
||||
- [ ] Webhook key format is correct (starts with `wh_`)
|
||||
- [ ] `webhook_enabled` field is `true`
|
||||
|
||||
### Webhook Receiver
|
||||
- [ ] Can send webhook with basic payload
|
||||
- [ ] Can send webhook with metadata
|
||||
- [ ] Event is created in database
|
||||
- [ ] Event has webhook metadata in config
|
||||
- [ ] Response includes event ID and trigger reference
|
||||
|
||||
### Webhook Management
|
||||
- [ ] Can regenerate webhook key
|
||||
- [ ] Old key stops working after regeneration
|
||||
- [ ] New key works immediately
|
||||
- [ ] Can disable webhooks
|
||||
- [ ] Disabled webhooks return 404
|
||||
|
||||
### Error Handling
|
||||
- [ ] Invalid webhook key returns 404
|
||||
- [ ] Regenerate without enabling returns 400
|
||||
- [ ] Management endpoints require authentication
|
||||
- [ ] Disabled trigger webhooks return 404
|
||||
|
||||
### Integration
|
||||
- [ ] Webhook creates event
|
||||
- [ ] Event triggers rule evaluation
|
||||
- [ ] Rule creates execution
|
||||
- [ ] Execution runs action
|
||||
|
||||
---
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
# Delete test rule
|
||||
curl -X DELETE http://localhost:8080/api/v1/rules/webhook_test.on_github_push \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Delete test action
|
||||
curl -X DELETE http://localhost:8080/api/v1/actions/webhook_test.log_event \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Delete test triggers
|
||||
curl -X DELETE http://localhost:8080/api/v1/triggers/webhook_test.github_push \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
curl -X DELETE http://localhost:8080/api/v1/triggers/webhook_test.no_webhook \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Delete test pack
|
||||
curl -X DELETE http://localhost:8080/api/v1/packs/webhook_test \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Webhook Key Not Generated
|
||||
- Verify database migration applied
|
||||
- Check API logs for errors
|
||||
- Ensure trigger exists before enabling webhooks
|
||||
|
||||
### Webhook Not Creating Event
|
||||
- Verify webhook key is correct
|
||||
- Check that trigger has `webhook_enabled = true`
|
||||
- Ensure payload is valid JSON
|
||||
- Check API logs for errors
|
||||
|
||||
### Rule Not Executing
|
||||
- Verify rule is enabled
|
||||
- Check that rule's trigger matches webhook trigger
|
||||
- Review executor service logs
|
||||
- Ensure worker service is running
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
After verifying Phase 2 functionality:
|
||||
1. Implement Phase 3 features (HMAC, rate limiting)
|
||||
2. Build Web UI for webhook management
|
||||
3. Add webhook event history and analytics
|
||||
4. Create example packs using webhooks (GitHub, Stripe, etc.)
|
||||
333
docs/webhooks/webhook-testing.md
Normal file
333
docs/webhooks/webhook-testing.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Webhook Testing Documentation
|
||||
|
||||
This document describes the comprehensive test suite for the Attune webhook system, covering both Phase 2 (basic functionality) and Phase 3 (advanced security features).
|
||||
|
||||
## Test Files
|
||||
|
||||
### 1. `crates/common/tests/webhook_tests.rs`
|
||||
Repository-level integration tests for webhook database operations.
|
||||
|
||||
**Coverage:**
|
||||
- Webhook enable/disable functionality
|
||||
- Webhook key generation and uniqueness
|
||||
- Webhook key regeneration
|
||||
- Finding triggers by webhook key
|
||||
- Idempotent webhook enabling
|
||||
|
||||
**Key Tests:**
|
||||
- `test_webhook_enable` - Verifies webhook can be enabled and generates valid key
|
||||
- `test_webhook_disable` - Verifies webhook can be disabled while preserving key
|
||||
- `test_webhook_key_regeneration` - Tests key rotation functionality
|
||||
- `test_find_by_webhook_key` - Tests lookup by webhook key
|
||||
- `test_webhook_key_uniqueness` - Ensures unique keys across triggers
|
||||
- `test_enable_webhook_idempotent` - Verifies enabling twice returns same key
|
||||
|
||||
### 2. `crates/api/tests/webhook_api_tests.rs`
|
||||
API endpoint integration tests for webhook management and basic receiving.
|
||||
|
||||
**Coverage:**
|
||||
- Webhook management endpoints (enable/disable/regenerate)
|
||||
- Basic webhook receiving
|
||||
- Authentication requirements
|
||||
- Error handling for invalid keys
|
||||
|
||||
**Key Tests:**
|
||||
- `test_enable_webhook` - Tests enabling webhooks via API
|
||||
- `test_disable_webhook` - Tests disabling webhooks via API
|
||||
- `test_regenerate_webhook_key` - Tests key regeneration via API
|
||||
- `test_receive_webhook` - Tests successful webhook reception
|
||||
- `test_receive_webhook_invalid_key` - Tests invalid key handling
|
||||
- `test_receive_webhook_disabled` - Tests disabled webhook rejection
|
||||
- `test_webhook_requires_auth_for_management` - Tests auth enforcement
|
||||
- `test_receive_webhook_minimal_payload` - Tests minimal payload acceptance
|
||||
|
||||
### 3. `crates/api/tests/webhook_security_tests.rs`
|
||||
Comprehensive security feature tests (Phase 3).
|
||||
|
||||
**Coverage:**
|
||||
- HMAC signature verification (SHA256, SHA512, SHA1)
|
||||
- Rate limiting
|
||||
- IP whitelisting (IPv4, IPv6, CIDR)
|
||||
- Payload size limits
|
||||
- Event logging
|
||||
- Combined security features
|
||||
- Error scenarios
|
||||
|
||||
## Test Categories
|
||||
|
||||
### HMAC Signature Tests
|
||||
|
||||
#### `test_webhook_hmac_sha256_valid`
|
||||
Verifies SHA256 HMAC signature validation works correctly.
|
||||
- Enables HMAC with SHA256 algorithm
|
||||
- Generates valid signature
|
||||
- Confirms webhook is accepted (200 OK)
|
||||
|
||||
#### `test_webhook_hmac_sha512_valid`
|
||||
Verifies SHA512 HMAC signature validation.
|
||||
- Uses SHA512 algorithm
|
||||
- Tests stronger hashing algorithm support
|
||||
|
||||
#### `test_webhook_hmac_invalid_signature`
|
||||
Tests rejection of invalid signatures.
|
||||
- Sends webhook with malformed signature
|
||||
- Expects 401 Unauthorized response
|
||||
|
||||
#### `test_webhook_hmac_missing_signature`
|
||||
Tests rejection when signature is required but missing.
|
||||
- HMAC enabled but no signature header provided
|
||||
- Expects 401 Unauthorized response
|
||||
|
||||
#### `test_webhook_hmac_wrong_secret`
|
||||
Tests rejection when signature uses wrong secret.
|
||||
- Generates signature with incorrect secret
|
||||
- Expects 401 Unauthorized response
|
||||
|
||||
### Rate Limiting Tests
|
||||
|
||||
#### `test_webhook_rate_limit_enforced`
|
||||
Verifies rate limiting prevents excessive requests.
|
||||
- Configures limit of 3 requests per 60 seconds
|
||||
- Sends 3 successful requests
|
||||
- 4th request returns 429 Too Many Requests
|
||||
|
||||
#### `test_webhook_rate_limit_disabled`
|
||||
Confirms webhooks work without rate limiting.
|
||||
- Sends 10 consecutive requests
|
||||
- All succeed when rate limiting disabled
|
||||
|
||||
### IP Whitelisting Tests
|
||||
|
||||
#### `test_webhook_ip_whitelist_allowed`
|
||||
Tests IP whitelist allows configured IPs.
|
||||
- Configures whitelist with CIDR and exact IP
|
||||
- Tests both CIDR range match (192.168.1.100 in 192.168.1.0/24)
|
||||
- Tests exact IP match (10.0.0.1)
|
||||
- Both return 200 OK
|
||||
|
||||
#### `test_webhook_ip_whitelist_blocked`
|
||||
Tests IP whitelist blocks non-whitelisted IPs.
|
||||
- Sends request from IP not in whitelist (8.8.8.8)
|
||||
- Expects 403 Forbidden response
|
||||
|
||||
### Payload Size Limit Tests
|
||||
|
||||
#### `test_webhook_payload_size_limit_enforced`
|
||||
Verifies payload size limits are enforced.
|
||||
- Sets 1 KB limit
|
||||
- Sends 2 KB payload
|
||||
- Expects 400 Bad Request response
|
||||
|
||||
#### `test_webhook_payload_size_within_limit`
|
||||
Tests payloads within limit are accepted.
|
||||
- Sets 10 KB limit
|
||||
- Sends small payload
|
||||
- Expects 200 OK response
|
||||
|
||||
### Event Logging Tests
|
||||
|
||||
#### `test_webhook_event_logging_success`
|
||||
Verifies successful webhooks are logged.
|
||||
- Sends successful webhook
|
||||
- Checks log entry exists
|
||||
- Validates log contains status code, IP, user agent
|
||||
|
||||
#### `test_webhook_event_logging_failure`
|
||||
Verifies failed webhooks are logged.
|
||||
- Sends failing webhook (HMAC failure)
|
||||
- Checks log entry with error details
|
||||
- Validates failure reason recorded
|
||||
|
||||
### Combined Security Tests
|
||||
|
||||
#### `test_webhook_all_security_features_pass`
|
||||
Tests webhook passing all security checks.
|
||||
- Enables HMAC, rate limiting, IP whitelist, size limit
|
||||
- Sends properly authenticated, allowed webhook
|
||||
- Verifies all checks pass and event created
|
||||
- Validates log shows all features verified
|
||||
|
||||
#### `test_webhook_multiple_security_failures`
|
||||
Tests multiple security feature failures.
|
||||
- Enables multiple features
|
||||
- Sends webhook failing multiple checks
|
||||
- Verifies first failure prevents further processing
|
||||
|
||||
### Error Scenario Tests
|
||||
|
||||
#### `test_webhook_malformed_json`
|
||||
Tests handling of malformed JSON payloads.
|
||||
- Sends invalid JSON
|
||||
- Expects 400 Bad Request response
|
||||
|
||||
#### `test_webhook_empty_payload`
|
||||
Tests handling of empty payloads.
|
||||
- Sends empty body
|
||||
- Expects 400 Bad Request response
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Run All Tests
|
||||
```bash
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
### Run Specific Test Suite
|
||||
```bash
|
||||
# Repository tests
|
||||
cargo test -p attune-common webhook_tests
|
||||
|
||||
# API tests
|
||||
cargo test -p attune-api webhook_api_tests
|
||||
|
||||
# Security tests
|
||||
cargo test -p attune-api webhook_security_tests
|
||||
```
|
||||
|
||||
### Run Ignored Tests (Requires Database)
|
||||
```bash
|
||||
cargo test --workspace -- --ignored
|
||||
```
|
||||
|
||||
### Run Specific Test
|
||||
```bash
|
||||
cargo test -p attune-api test_webhook_hmac_sha256_valid -- --ignored
|
||||
```
|
||||
|
||||
## Test Environment Setup
|
||||
|
||||
Tests require:
|
||||
1. **PostgreSQL Database** - Running on localhost:5432 (or configured via `DATABASE_URL`)
|
||||
2. **Test User** - Username: `test_user`, Password: `test_password`
|
||||
3. **Migrations Applied** - All database migrations must be up to date
|
||||
|
||||
### Setup Commands
|
||||
```bash
|
||||
# Set database URL
|
||||
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/attune"
|
||||
|
||||
# Run migrations
|
||||
sqlx migrate run
|
||||
|
||||
# Create test user (if not exists)
|
||||
psql $DATABASE_URL -c "
|
||||
INSERT INTO attune.identity (username, email, password_hash, enabled)
|
||||
VALUES ('test_user', 'test@example.com', '$argon2id$...', true)
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
"
|
||||
```
|
||||
|
||||
## Test Coverage Summary
|
||||
|
||||
| Feature | Test Count | Status |
|
||||
|---------|-----------|--------|
|
||||
| Basic Webhook Management | 8 | ✅ Complete |
|
||||
| HMAC Verification | 5 | ✅ Complete |
|
||||
| Rate Limiting | 2 | ✅ Complete |
|
||||
| IP Whitelisting | 2 | ✅ Complete |
|
||||
| Payload Size Limits | 2 | ✅ Complete |
|
||||
| Event Logging | 2 | ✅ Complete |
|
||||
| Combined Security | 2 | ✅ Complete |
|
||||
| Error Scenarios | 2 | ✅ Complete |
|
||||
| **Total** | **25** | **✅ Complete** |
|
||||
|
||||
## Security Test Matrix
|
||||
|
||||
| HMAC | Rate Limit | IP Whitelist | Size Limit | Expected Result |
|
||||
|------|-----------|--------------|------------|-----------------|
|
||||
| ✅ Valid | ✅ OK | ✅ Allowed | ✅ OK | 200 OK |
|
||||
| ❌ Invalid | N/A | N/A | N/A | 401 Unauthorized |
|
||||
| ⚠️ Missing | N/A | N/A | N/A | 401 Unauthorized |
|
||||
| ✅ Valid | ❌ Exceeded | N/A | N/A | 429 Too Many Requests |
|
||||
| ✅ Valid | ✅ OK | ❌ Blocked | N/A | 403 Forbidden |
|
||||
| ✅ Valid | ✅ OK | ✅ Allowed | ❌ Too Large | 400 Bad Request |
|
||||
|
||||
## Known Test Limitations
|
||||
|
||||
1. **Rate Limit Window Tests** - Tests don't verify time-based window expiry (would require time manipulation)
|
||||
2. **Concurrent Rate Limiting** - No tests for concurrent request handling
|
||||
3. **IPv6 Whitelist** - Limited IPv6 testing coverage
|
||||
4. **Webhook Retry** - Not yet implemented (Phase 4 feature)
|
||||
5. **Performance Tests** - No load/stress tests included
|
||||
|
||||
## Future Test Additions
|
||||
|
||||
### Phase 4 Features (Planned)
|
||||
- Webhook retry logic tests
|
||||
- Payload transformation tests
|
||||
- Multiple webhook keys per trigger
|
||||
- Webhook health check tests
|
||||
- Analytics and metrics tests
|
||||
|
||||
### Additional Coverage Needed
|
||||
- Concurrent webhook processing
|
||||
- Database connection failure handling
|
||||
- Message queue failure scenarios
|
||||
- Performance benchmarks
|
||||
- Security penetration testing
|
||||
|
||||
## Debugging Failed Tests
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Test fails with "Failed to connect to database"**
|
||||
```bash
|
||||
# Check database is running
|
||||
pg_isready -h localhost -p 5432
|
||||
|
||||
# Verify DATABASE_URL
|
||||
echo $DATABASE_URL
|
||||
|
||||
# Test connection
|
||||
psql $DATABASE_URL -c "SELECT 1"
|
||||
```
|
||||
|
||||
**Test fails with "Trigger not found"**
|
||||
- Ensure migrations are up to date: `sqlx migrate run`
|
||||
- Check schema exists: `psql $DATABASE_URL -c "\dn"`
|
||||
|
||||
**Test fails with "Authentication required"**
|
||||
- Verify test user exists in database
|
||||
- Check JWT_SECRET environment variable is set
|
||||
|
||||
**Rate limit test fails unexpectedly**
|
||||
- Database state may have rate limit entries from previous tests
|
||||
- Clear webhook_event_log table between test runs
|
||||
|
||||
## Manual Testing
|
||||
|
||||
For manual testing instructions, see [webhook-manual-testing.md](webhook-manual-testing.md).
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Tests are configured to run in CI/CD pipeline with:
|
||||
- PostgreSQL service container
|
||||
- Test database initialization
|
||||
- Migration application
|
||||
- Test user creation
|
||||
- Parallel test execution
|
||||
|
||||
See `.github/workflows/test.yml` (if configured) for CI setup.
|
||||
|
||||
## Test Maintenance
|
||||
|
||||
### Adding New Tests
|
||||
1. Follow existing test structure and naming conventions
|
||||
2. Use test helpers (`setup_test_state`, `create_test_pack`, etc.)
|
||||
3. Clean up test data after test completion
|
||||
4. Mark as `#[ignore]` if requires external dependencies
|
||||
5. Document test purpose and expected behavior
|
||||
6. Add test to this documentation
|
||||
|
||||
### Updating Tests for New Features
|
||||
1. Update relevant test files
|
||||
2. Add new test categories if needed
|
||||
3. Update test coverage summary
|
||||
4. Update security test matrix if applicable
|
||||
5. Document any new test requirements
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-01-20
|
||||
**Test Suite Version:** 1.0
|
||||
**Phase Completion:** Phase 3 ✅
|
||||
Reference in New Issue
Block a user