feat(docker-watcher): phase 2 - crypto & config seed loader
AES-256-GCM encryption for credential storage, YAML seed config parser with validation, and transactional import into SQLite. Credentials (registry tokens, NPM password) encrypted before storage.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Phase 2: Crypto & Config Seed Loader
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Status:** ✅ Complete
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
@@ -9,14 +9,14 @@ Implement AES-256 encryption for credential storage and the YAML seed config par
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Implement AES-256-GCM encrypt/decrypt functions using Go stdlib `crypto/aes` + `crypto/cipher`
|
||||
- [ ] Task 2: Key derivation from ENCRYPTION_KEY env var (SHA-256 hash to get 32 bytes)
|
||||
- [ ] Task 3: Define YAML config structs matching the seed format from PLAN.md
|
||||
- [ ] Task 4: Implement YAML parser — read and validate seed file
|
||||
- [ ] Task 5: Implement seed importer — checks if DB is empty, if so imports YAML into SQLite via store CRUD
|
||||
- [ ] Task 6: Encrypt credential fields (registry tokens, NPM password) during import
|
||||
- [ ] Task 7: Create `docker-watcher.example.yaml` with documented example config
|
||||
- [ ] Task 8: Wire seed import into `cmd/server/main.go` startup sequence
|
||||
- [x] Task 1: Implement AES-256-GCM encrypt/decrypt functions using Go stdlib `crypto/aes` + `crypto/cipher`
|
||||
- [x] Task 2: Key derivation from ENCRYPTION_KEY env var (SHA-256 hash to get 32 bytes)
|
||||
- [x] Task 3: Define YAML config structs matching the seed format from PLAN.md
|
||||
- [x] Task 4: Implement YAML parser — read and validate seed file
|
||||
- [x] Task 5: Implement seed importer — checks if DB is empty, if so imports YAML into SQLite via store CRUD
|
||||
- [x] Task 6: Encrypt credential fields (registry tokens, NPM password) during import
|
||||
- [x] Task 7: Create `docker-watcher.example.yaml` with documented example config
|
||||
- [x] Task 8: Wire seed import into `cmd/server/main.go` startup sequence
|
||||
|
||||
## Files to Modify/Create
|
||||
- `internal/crypto/crypto.go` — AES-256-GCM encrypt/decrypt
|
||||
@@ -40,11 +40,22 @@ Implement AES-256 encryption for credential storage and the YAML seed config par
|
||||
- The example YAML should have placeholder values, not real credentials
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Crypto uses secure practices (random nonce, GCM, no ECB)
|
||||
- [ ] No hardcoded keys or secrets
|
||||
- [ ] YAML parsing validates required fields
|
||||
- [ ] Import is transactional
|
||||
- [x] All tasks completed
|
||||
- [x] Crypto uses secure practices (random nonce, GCM, no ECB)
|
||||
- [x] No hardcoded keys or secrets
|
||||
- [x] YAML parsing validates required fields
|
||||
- [x] Import is transactional
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in by the implementation agent after completing this phase. -->
|
||||
|
||||
- `crypto.Encrypt(key, plaintext)` and `crypto.Decrypt(key, ciphertextHex)` handle AES-256-GCM encryption; ciphertext is hex-encoded with prepended nonce
|
||||
- `crypto.KeyFromEnv()` derives a `[32]byte` key from the `ENCRYPTION_KEY` env var via SHA-256
|
||||
- `crypto.EncryptIfNotEmpty(key, value)` is a convenience wrapper that passes through empty strings unchanged
|
||||
- `config.ImportSeed(db, seedPath)` is the single entry point for seed import — called from `main.go` at startup
|
||||
- Import is idempotent: skipped if the DB already has projects or registries
|
||||
- Import is transactional: all inserts happen within a single SQLite transaction (rollback on any failure)
|
||||
- Registry `token` and settings `npm_password` are now stored encrypted in SQLite — later phases that read these fields must decrypt with `crypto.Decrypt(key, value)`
|
||||
- `store.DB()` method was added to expose the underlying `*sql.DB` for transaction use
|
||||
- Seed file path is configurable via `SEED_FILE` env var (default: `./docker-watcher.yaml`)
|
||||
- YAML validation ensures: `global.domain` is required, every project needs `image`, project registry references must exist, stages need `tag_pattern`
|
||||
- `go.sum` still does not exist — run `go mod tidy` when Go toolchain is available
|
||||
|
||||
Reference in New Issue
Block a user