179 lines
4.3 KiB
Markdown
179 lines
4.3 KiB
Markdown
|
|
# BOC Härdning — Checklista
|
||
|
|
|
||
|
|
> **Datum:** 2026-08-04 22:46 UTC
|
||
|
|
> **Status:** ⚠️ KRÄVER MANUELL ÅTGÄRD
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔴 KRITISKT — HTTPS/TLS
|
||
|
|
|
||
|
|
**Problem:** BOC kör på HTTP (port 9096), all trafik är okrypterad.
|
||
|
|
|
||
|
|
**Åtgärd:** Konfigurera nginx reverse proxy med Let's Encrypt:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Installera certbot
|
||
|
|
sudo dnf install certbot python3-certbot-nginx
|
||
|
|
|
||
|
|
# 2. Skapa nginx-konfig för BOC
|
||
|
|
sudo tee /etc/nginx/conf.d/boc.conf << 'EOF'
|
||
|
|
server {
|
||
|
|
listen 443 ssl http2;
|
||
|
|
server_name boc.aamos.com;
|
||
|
|
|
||
|
|
ssl_certificate /etc/letsencrypt/live/boc.aamos.com/fullchain.pem;
|
||
|
|
ssl_certificate_key /etc/letsencrypt/live/boc.aamos.com/privkey.pem;
|
||
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||
|
|
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
|
||
|
|
|
||
|
|
location / {
|
||
|
|
proxy_pass http://localhost:9096;
|
||
|
|
proxy_set_header Host $host;
|
||
|
|
proxy_set_header X-Real-IP $remote_addr;
|
||
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
server {
|
||
|
|
listen 80;
|
||
|
|
server_name boc.aamos.com;
|
||
|
|
return 301 https://$server_name$request_uri;
|
||
|
|
}
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# 3. Skaffa certifikat
|
||
|
|
sudo certbot --nginx -d boc.aamos.com
|
||
|
|
|
||
|
|
# 4. Starta om nginx
|
||
|
|
sudo systemctl restart nginx
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🟡 HÖG PRIORITET
|
||
|
|
|
||
|
|
### 2. Rate Limiting (finns redan i koden!)
|
||
|
|
|
||
|
|
**Status:** ✅ Redan implementerat i `middleware/security.go`
|
||
|
|
|
||
|
|
**Aktivera:** Lägg till i `main.go`:
|
||
|
|
|
||
|
|
```go
|
||
|
|
// Efter r := chi.NewRouter()
|
||
|
|
rateLimiter := middleware.NewRateLimiter()
|
||
|
|
r.Use(middleware.RateLimit(rateLimiter))
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. CORS — Begränsa origins
|
||
|
|
|
||
|
|
**Fil:** `middleware/cors.go` (skapa om den saknas)
|
||
|
|
|
||
|
|
```go
|
||
|
|
package middleware
|
||
|
|
|
||
|
|
import "net/http"
|
||
|
|
|
||
|
|
func CORS(next http.Handler) http.Handler {
|
||
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
allowedOrigins := map[string]bool{
|
||
|
|
"https://boc.aamos.com": true,
|
||
|
|
"https://admin.landvex.com": true,
|
||
|
|
"https://landvex.com": true,
|
||
|
|
"http://localhost:3000": true, // Dev only
|
||
|
|
}
|
||
|
|
|
||
|
|
origin := r.Header.Get("Origin")
|
||
|
|
if allowedOrigins[origin] {
|
||
|
|
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||
|
|
}
|
||
|
|
|
||
|
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||
|
|
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||
|
|
w.Header().Set("Access-Control-Max-Age", "86400")
|
||
|
|
|
||
|
|
if r.Method == "OPTIONS" {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
next.ServeHTTP(w, r)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Auth — RS256 (redan fixat!)
|
||
|
|
|
||
|
|
**Status:** ✅ Fungerar — returnerar 401 utan token
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🟢 MEDEL PRIORITET
|
||
|
|
|
||
|
|
### 5. Connection Pooling
|
||
|
|
|
||
|
|
**Fil:** `db/db.go`
|
||
|
|
|
||
|
|
Lägg till efter `sql.Open`:
|
||
|
|
|
||
|
|
```go
|
||
|
|
db.SetMaxOpenConns(25)
|
||
|
|
db.SetMaxIdleConns(10)
|
||
|
|
db.SetConnMaxLifetime(5 * time.Minute)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. Miljövariabler — Secrets
|
||
|
|
|
||
|
|
**Nuvarande:** Lösenord i `.env`
|
||
|
|
|
||
|
|
**Bör vara:** Använd AWS Secrets Manager eller HashiCorp Vault:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Hämta secret vid runtime
|
||
|
|
export DB_PASSWORD=$(aws secretsmanager get-secret-value --secret-id boc/db-password --query SecretString --output text)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 7. Swagger UI
|
||
|
|
|
||
|
|
**Status:** ✅ JSON finns, UI saknas
|
||
|
|
|
||
|
|
**Fix:** Lägg till i `main.go`:
|
||
|
|
|
||
|
|
```go
|
||
|
|
r.Get("/swagger.json", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
http.ServeFile(w, r, "./docs/swagger.json")
|
||
|
|
})
|
||
|
|
r.Get("/docs", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
http.ServeFile(w, r, "./docs/index.html")
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 SAMMANSTÄLLNING
|
||
|
|
|
||
|
|
| # | Fix | Status | Fil |
|
||
|
|
|---|-----|--------|-----|
|
||
|
|
| 1 | HTTPS/TLS | ❌ Kräver nginx + certbot | Server-konfig |
|
||
|
|
| 2 | Rate limiting | ✅ Klar (finns i koden) | `middleware/security.go` |
|
||
|
|
| 3 | CORS | ⚠️ Kräver uppdatering | `middleware/cors.go` |
|
||
|
|
| 4 | RS256 Auth | ✅ Klar | `auth/rs256.go` |
|
||
|
|
| 5 | Connection pool | ⚠️ Enkel fix | `db/db.go` |
|
||
|
|
| 6 | Secrets | ⚠️ Kräver AWS/Vault | `.env` |
|
||
|
|
| 7 | Swagger UI | ⚠️ Lägg till route | `main.go` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 REKOMMENDATION
|
||
|
|
|
||
|
|
**Gör #1 (HTTPS) först** — det är den enda kritiska säkerhetsbristen. Resten kan vänta.
|
||
|
|
|
||
|
|
**Tidsuppskattning:**
|
||
|
|
- HTTPS: 30 minuter
|
||
|
|
- Rate limiting: 5 minuter (redan klart)
|
||
|
|
- CORS: 10 minuter
|
||
|
|
- Connection pool: 5 minuter
|
||
|
|
- Swagger UI: 10 minuter
|
||
|
|
|
||
|
|
**Totalt: ~1 timme**
|