Harden API security: input validation, safe auth extraction, new tests, and deploy config
Comprehensive security hardening from audit findings: - Add validation tags to all DTO request structs (max lengths, ranges, enums) - Replace unsafe type assertions with MustGetAuthUser helper across all handlers - Remove query-param token auth from admin middleware (prevents URL token leakage) - Add request validation calls in handlers that were missing c.Validate() - Remove goroutines in handlers (timezone update now synchronous) - Add sanitize middleware and path traversal protection (path_utils) - Stop resetting admin passwords on migration restart - Warn on well-known default SECRET_KEY - Add ~30 new test files covering security regressions, auth safety, repos, and services - Add deploy/ config, audit digests, and AUDIT_FINDINGS documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
deploy/README.md
Normal file
134
deploy/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Deploy Folder
|
||||
|
||||
This folder is the full production deploy toolkit for `myCribAPI-go`.
|
||||
|
||||
Run deploy with:
|
||||
|
||||
```bash
|
||||
./.deploy_prod
|
||||
```
|
||||
|
||||
The script will refuse to run until all required values are set.
|
||||
|
||||
## First-Time Prerequisite: Create The Swarm Cluster
|
||||
|
||||
You must do this once before `./.deploy_prod` can work.
|
||||
|
||||
1. SSH to manager #1 and initialize Swarm:
|
||||
|
||||
```bash
|
||||
docker swarm init --advertise-addr <manager1-private-ip>
|
||||
```
|
||||
|
||||
2. On manager #1, get join commands:
|
||||
|
||||
```bash
|
||||
docker swarm join-token manager
|
||||
docker swarm join-token worker
|
||||
```
|
||||
|
||||
3. SSH to each additional node and run the appropriate `docker swarm join ...` command.
|
||||
|
||||
4. Verify from manager #1:
|
||||
|
||||
```bash
|
||||
docker node ls
|
||||
```
|
||||
|
||||
## Security Requirements Before Public Launch
|
||||
|
||||
Use this as a mandatory checklist before you route production traffic.
|
||||
|
||||
### 1) Firewall Rules (Node-Level)
|
||||
|
||||
Apply firewall rules to all Swarm nodes:
|
||||
|
||||
- SSH port (for example `2222/tcp`): your IP only
|
||||
- `80/tcp`, `443/tcp`: Hetzner LB only (or Cloudflare IP ranges only if no LB)
|
||||
- `2377/tcp`: Swarm nodes only
|
||||
- `7946/tcp,udp`: Swarm nodes only
|
||||
- `4789/udp`: Swarm nodes only
|
||||
- Everything else: blocked
|
||||
|
||||
### 2) SSH Hardening
|
||||
|
||||
On each node, harden `/etc/ssh/sshd_config`:
|
||||
|
||||
```text
|
||||
Port 2222
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
PubkeyAuthentication yes
|
||||
AllowUsers deploy
|
||||
```
|
||||
|
||||
### 3) Cloudflare Origin Lockdown
|
||||
|
||||
- Keep public DNS records proxied (orange cloud on).
|
||||
- Point Cloudflare to LB, not node IPs.
|
||||
- Do not publish Swarm node IPs in DNS.
|
||||
- Enforce firewall source restrictions so public traffic cannot bypass Cloudflare/LB.
|
||||
|
||||
### 4) Secrets Policy
|
||||
|
||||
- Keep runtime secrets in Docker Swarm secrets only.
|
||||
- Do not put production secrets in git or plain `.env` files.
|
||||
- `./.deploy_prod` already creates versioned Swarm secrets from files in `deploy/secrets/`.
|
||||
- Rotate secrets after incidents or credential exposure.
|
||||
|
||||
### 5) Data Path Security
|
||||
|
||||
- Neon/Postgres: `DB_SSLMODE=require`, strong DB password, Neon IP allowlist limited to node IPs.
|
||||
- Backblaze B2: HTTPS only, scoped app keys (not master key), least-privilege bucket access.
|
||||
- Swarm overlay: encrypted network enabled in stack (`driver_opts.encrypted: "true"`).
|
||||
|
||||
### 6) Dozzle Hardening
|
||||
|
||||
- Keep Dozzle private (no public DNS/ingress).
|
||||
- Put auth/SSO in front (Cloudflare Access or equivalent).
|
||||
- Prefer a Docker socket proxy with restricted read-only scope.
|
||||
|
||||
### 7) Backup + Restore Readiness
|
||||
|
||||
- Postgres PITR path tested in staging.
|
||||
- Redis persistence enabled and restore path tested.
|
||||
- Written runbook for restore and secret rotation.
|
||||
- Named owner for incident response.
|
||||
|
||||
## Files You Fill In
|
||||
|
||||
Paste your values into these files:
|
||||
|
||||
- `deploy/cluster.env`
|
||||
- `deploy/registry.env`
|
||||
- `deploy/prod.env`
|
||||
- `deploy/secrets/postgres_password.txt`
|
||||
- `deploy/secrets/secret_key.txt`
|
||||
- `deploy/secrets/email_host_password.txt`
|
||||
- `deploy/secrets/fcm_server_key.txt`
|
||||
- `deploy/secrets/apns_auth_key.p8`
|
||||
|
||||
If one is missing, the deploy script auto-copies it from its `.example` template and exits so you can fill it.
|
||||
|
||||
## What `./.deploy_prod` Does
|
||||
|
||||
1. Validates all required config files and credentials.
|
||||
2. Builds and pushes `api`, `worker`, and `admin` images.
|
||||
3. Uploads deploy bundle to your Swarm manager over SSH.
|
||||
4. Creates versioned Docker secrets on the manager.
|
||||
5. Deploys the stack with `docker stack deploy --with-registry-auth`.
|
||||
6. Waits until service replicas converge.
|
||||
7. Runs an HTTP health check (if `DEPLOY_HEALTHCHECK_URL` is set).
|
||||
|
||||
## Useful Flags
|
||||
|
||||
Environment flags:
|
||||
|
||||
- `SKIP_BUILD=1 ./.deploy_prod` to deploy already-pushed images.
|
||||
- `SKIP_HEALTHCHECK=1 ./.deploy_prod` to skip final URL check.
|
||||
- `DEPLOY_TAG=<tag> ./.deploy_prod` to deploy a specific image tag.
|
||||
|
||||
## Important
|
||||
|
||||
- `deploy/shit_deploy_cant_do.md` lists the manual tasks this script cannot automate.
|
||||
- Keep real credentials and secret files out of git.
|
||||
Reference in New Issue
Block a user