refactor: auto-generate session key and store in database
All checks were successful
check / check (push) Successful in 57s
All checks were successful
check / check (push) Successful in 57s
Remove SESSION_KEY env var requirement. On first startup, a cryptographically secure 32-byte key is generated and stored in a new settings table. Subsequent startups load the key from the database. - Add Setting model (key-value table) for application config - Add Database.GetOrCreateSessionKey() method - Session manager initializes in OnStart after database is connected - Remove DevSessionKey constant and SESSION_KEY env var handling - Remove prod validation requiring SESSION_KEY - Update README: config table, Docker instructions, security notes - Update config.yaml.example - Update all tests to remove SessionKey references Addresses owner feedback on issue #15.
This commit is contained in:
41
README.md
41
README.md
@@ -68,12 +68,15 @@ Configuration is resolved in this order (highest priority first):
|
||||
| `PORT` | HTTP listen port | `8080` |
|
||||
| `DBURL` | SQLite connection string (main app DB) | *(required)* |
|
||||
| `DATA_DIR` | Directory for per-webhook event DBs | `./data` (dev) / `/data/events` (prod) |
|
||||
| `SESSION_KEY` | Base64-encoded 32-byte session key | *(required in prod)* |
|
||||
| `DEBUG` | Enable debug logging | `false` |
|
||||
| `METRICS_USERNAME` | Basic auth username for `/metrics` | `""` |
|
||||
| `METRICS_PASSWORD` | Basic auth password for `/metrics` | `""` |
|
||||
| `SENTRY_DSN` | Sentry error reporting DSN | `""` |
|
||||
|
||||
On first startup, webhooker automatically generates a cryptographically
|
||||
secure session encryption key and stores it in the database. This key
|
||||
persists across restarts — no manual key management is needed.
|
||||
|
||||
On first startup in development mode, webhooker creates an `admin` user
|
||||
with a randomly generated password and logs it to stdout. This password
|
||||
is only displayed once.
|
||||
@@ -86,7 +89,6 @@ docker run -d \
|
||||
-v /path/to/data:/data \
|
||||
-e DBURL="file:/data/webhooker.db?cache=shared&mode=rwc" \
|
||||
-e DATA_DIR="/data/events" \
|
||||
-e SESSION_KEY="<base64-encoded-32-byte-key>" \
|
||||
-e WEBHOOKER_ENVIRONMENT=prod \
|
||||
webhooker:latest
|
||||
```
|
||||
@@ -196,6 +198,10 @@ tier** (event ingestion, delivery, and logging).
|
||||
│ │ │ └──────────┘ └──────────────┘ │
|
||||
│ │ │──1:N──│ APIKey │ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ ┌──────────┐ │
|
||||
│ │ Setting │ (key-value application config) │
|
||||
│ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
@@ -208,6 +214,22 @@ tier** (event ingestion, delivery, and logging).
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Setting
|
||||
|
||||
A key-value pair for application-level configuration that is
|
||||
auto-managed rather than user-provided. Used to store the session
|
||||
encryption key and any future auto-generated settings.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------- | ------ | ----------- |
|
||||
| `key` | string | Primary key (setting name) |
|
||||
| `value` | text | Setting value |
|
||||
|
||||
Currently stored settings:
|
||||
|
||||
- **`session_key`** — Base64-encoded 32-byte session encryption key,
|
||||
auto-generated on first startup.
|
||||
|
||||
#### User
|
||||
|
||||
A registered user of the webhooker service.
|
||||
@@ -397,16 +419,19 @@ webhooker uses **separate SQLite database files**: a main application
|
||||
database for configuration data and per-webhook databases for event
|
||||
storage.
|
||||
|
||||
**Main Application Database** (`DBURL`) — stores configuration only:
|
||||
**Main Application Database** (`DBURL`) — stores configuration and
|
||||
application state:
|
||||
|
||||
- **Settings** — auto-managed key-value config (e.g. session encryption
|
||||
key)
|
||||
- **Users** — accounts and Argon2id password hashes
|
||||
- **Webhooks** — webhook configurations
|
||||
- **Entrypoints** — receiver URL definitions
|
||||
- **Targets** — delivery destination configurations
|
||||
- **APIKeys** — programmatic access credentials
|
||||
|
||||
On first startup the main database is auto-migrated and an `admin` user
|
||||
is created.
|
||||
On first startup the main database is auto-migrated, a session
|
||||
encryption key is generated and stored, and an `admin` user is created.
|
||||
|
||||
**Per-Webhook Event Databases** (`DATA_DIR`) — each webhook gets its own
|
||||
dedicated SQLite file named `events-{webhook_uuid}.db`, containing:
|
||||
@@ -565,6 +590,7 @@ webhooker/
|
||||
│ │ ├── base_model.go # BaseModel with UUID primary keys
|
||||
│ │ ├── database.go # GORM connection, migrations, admin seed
|
||||
│ │ ├── models.go # AutoMigrate for config-tier models
|
||||
│ │ ├── model_setting.go # Setting entity (key-value app config)
|
||||
│ │ ├── model_user.go # User entity
|
||||
│ │ ├── model_webhook.go # Webhook entity
|
||||
│ │ ├── model_entrypoint.go # Entrypoint entity
|
||||
@@ -625,7 +651,7 @@ Components are wired via Uber fx in this order:
|
||||
5. `database.NewWebhookDBManager` — Per-webhook event database
|
||||
lifecycle manager
|
||||
6. `healthcheck.New` — Health check service
|
||||
7. `session.New` — Cookie-based session manager
|
||||
7. `session.New` — Cookie-based session manager (key from database)
|
||||
8. `handlers.New` — HTTP handlers
|
||||
9. `middleware.New` — HTTP middleware
|
||||
10. `delivery.New` — Event-driven delivery engine
|
||||
@@ -665,7 +691,8 @@ Applied to all routes in this order:
|
||||
|
||||
- Passwords hashed with Argon2id (64 MB memory cost)
|
||||
- Session cookies are HttpOnly, SameSite Lax, Secure (prod only)
|
||||
- Session key must be a 32-byte base64-encoded value
|
||||
- Session key is a 32-byte value auto-generated on first startup and
|
||||
stored in the database
|
||||
- Prometheus metrics behind basic auth
|
||||
- Static assets embedded in binary (no filesystem access needed at
|
||||
runtime)
|
||||
|
||||
Reference in New Issue
Block a user