Files
solution-erp/docs/guides/security-checklist.md
pqhuy1987 f3fb3fd565 [CLAUDE] Phase5 prep: production infra + deploy scripts + 4 guides + FE refresh token
Backend production infra:
- Packages: Serilog.Sinks.File, HealthChecks.EntityFrameworkCore (RateLimiting built-in .NET 10)
- appsettings.Production.json MOI: placeholder __SET_VIA_SECRETS__, AllowedOrigins, Serilog File sink rolling daily retention 30d, RateLimit config
- appsettings.json + Development.json: them Serilog WriteTo Console
- Program.cs REWRITE:
  - Serilog ReadFrom.Configuration (prod file / dev console)
  - Rate limiter: policy auth-login 5/min/IP (AuthController.Login) + GlobalLimiter 300/min/IP
  - Health checks: /health/live liveness (empty predicate) + /health/ready DB probe (AddDbContextCheck)
  - HSTS production 1 year
  - CORS origins from config AllowedOrigins (default dev 2 localhost)
- AuthController.Login gắn [EnableRateLimiting("auth-login")]

Deploy scripts:
- scripts/deploy-iis.ps1: stop pool → backup current → clean+extract artifact → start pool → health check loop 30s timeout → rollback instruction if fail
- scripts/backup-sql.ps1: BACKUP DATABASE voi INIT+COMPRESSION+CHECKSUM + retention 30d auto cleanup
- .gitea/workflows/deploy.yml MOI: 4 job build BE (Windows) + build 2 FE (Ubuntu, pin .nvmrc 20) + deploy-iis qua WinRM PSSession (secrets IIS_HOST/USER/PASSWORD/JWT_SECRET/DB_CONNECTION)

Docs guides MOI (4 file):
- deployment-iis.md: prereqs (IIS features, Hosting Bundle, SQL, WinRM) + setup lan dau (app pool, 3 site, HTTPS win-acme, user-secrets) + deploy hang ngay (CI/CD + manual) + rollback + monitoring + troubleshooting + SPA web.config sample
- cicd.md: pipeline overview 4 job, secrets setup, runner Windows+Ubuntu, branch strategy, build optimizations, common CI/CD issues
- security-checklist.md: OWASP top 10 2021 mapping voi status + pre go-live checklist + incident response
- runbook.md: daily ops (health/logs), restart/rollback, DB backup/restore/migration revert, user management (reset password, unlock, disable), monitoring (CPU/disk/connection pool), deployment checklist, common gotcha

Frontend refresh token (ca 2 app fe-admin + fe-user):
- lib/api.ts REWRITE: them REFRESH_KEY, axios response interceptor 401 → POST /auth/refresh → retry request goc. Queue pattern cho nhieu request song song chi 1 refresh call chay. Skip retry /auth/login + /auth/refresh tranh infinite loop. _retry flag tren original config.
- contexts/AuthContext.tsx: luu+xoa REFRESH_KEY trong login/logout

E2E verified:
- GET /health/live → 200 Healthy
- GET /health/ready → 200 Healthy (DB probe)
- Rate limit flood 7 POST /auth/login → #1-5 HTTP 400 (cred sai) + #6-7 HTTP 429 Too Many Requests 
- TS check fe-admin + fe-user → pass
- dotnet build → 0 errors

Docs updates:
- docs/STATUS.md: Phase 5 prep done, next Phase 5 deploy production + Phase 5.1 security hardening, cumulative stats 8 commits
- docs/HANDOFF.md: phase table them Phase 5 prep row, file tree update voi guides + scripts + workflows, git state commit 8
- docs/changelog/migration-todos.md: tick Phase 5 prep items (12 items done) + Phase 5 deploy items remaining + Phase 5.1 security hardening list
- docs/changelog/sessions/2026-04-21-1530-phase5-prep.md: session log chi tiet

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:57:12 +07:00

6.4 KiB

Security Checklist — SOLUTION_ERP

OWASP Top 10 2021 + best practices production. Review trước Phase 5 go-live.

Current status (sau Phase 5 prep)

Item Status Nơi kiểm
HTTPS enforce (HSTS 365d) Program.csapp.UseHsts() production
JWT expiry 1h + refresh 7d appsettings.json Jwt section
Password hash PBKDF2 ASP.NET Identity default
Rate limit /auth/login 5/min/IP Program.cs [EnableRateLimiting("auth-login")]
Rate limit global 300/min/IP Program.cs GlobalLimiter
CORS whitelist 2 origin prod appsettings.Production.json AllowedOrigins
JWT secret from user-secrets prod 🔲 Cần set khi deploy — xem deployment-iis.md §2.4
DB connection user least privilege 🔲 solutionerp_app cần chỉ db_owner trên DB chính, không sysadmin
Audit log writes 🟡 ContractApprovals cho workflow, chưa có global audit
SQL injection via EF parameterized EF Core mặc định parameterize
Input validation FluentValidation mọi command
XSS protection ⚠️ React auto-escape OK, nhưng TextArea notes có thể render raw nếu dev viết dangerouslySetInnerHTML
CSRF protection 🔲 JWT localStorage + sameOrigin — không vulnerable CSRF theo classic (không dùng cookie)
Dependencies scan 🔲 Chưa có — thêm dotnet list package --vulnerable + npm audit vào CI

OWASP Top 10 2021 mapping

A01:2021 — Broken Access Control

Guard: [Authorize] default trên mọi controller, policy {Menu}.{Action} cho granular check. FE guard: <PermissionGuard> + usePermission() — nhưng BE là source of truth (403 từ BE nếu FE bypass).

Check trước go-live:

  • Test user role Drafter → không access được endpoint /api/permissions, /api/users
  • Test IDOR: user A không truy cập được HĐ user B qua /api/contracts/{id}HIỆN CHƯA CHECK. Phase 5 cần thêm check "user tham gia HĐ" (DrafterUserId hoặc có role giữ phase hiện tại).

A02:2021 — Cryptographic Failures

HTTPS + HSTS production. JWT HS256 với secret 64+ chars (random). 🔲 Password policy min 8 chars + mixed case + digit + symbol. Prod strong password tối thiểu 12.

A03:2021 — Injection

EF Core parameterized queries (no raw SQL). Input validation FluentValidation. ⚠️ File upload: chưa implement upload endpoint; khi làm phải validate MIME + magic bytes + path traversal.

A04:2021 — Insecure Design

Workflow state machine với explicit adjacency — không cho skip phase bypass rule. Audit trail qua ContractApprovals. 🔲 Business rule: ai được tạo HĐ? Hiện default Drafter role, Phase 5 nên limit theo dept.

A05:2021 — Security Misconfiguration

appsettings.Production.json template có placeholder __SET_VIA_USER_SECRETS_OR_ENV__ — không có secret thật commit. appsettings.Development.json với dev-only secret. 🔲 IIS hardening: disable server banner header, disable X-Powered-By. 🔲 Swagger chỉ bật dev.

Thêm vào web.config hoặc Program.cs:

app.Use(async (ctx, next) =>
{
    ctx.Response.Headers.Remove("Server");
    ctx.Response.Headers.Remove("X-Powered-By");
    ctx.Response.Headers["X-Content-Type-Options"] = "nosniff";
    ctx.Response.Headers["X-Frame-Options"] = "DENY";
    ctx.Response.Headers["Referrer-Policy"] = "strict-origin-when-cross-origin";
    ctx.Response.Headers["Content-Security-Policy"] = "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'";
    await next();
});

A06:2021 — Vulnerable Components

🔲 CI thêm dotnet list package --vulnerable --include-transitive 🔲 CI thêm npm audit --audit-level=high 🔲 Monthly update: patch minor versions, major khi LTS cần

A07:2021 — Authentication Failures

Rate limit login 5/min/IP. PBKDF2 hash. 🔲 Account lockout sau N lần sai password (config UserLockout trong Identity — chưa bật). 🔲 MFA — Phase 6+ nếu cần.

Bật account lockout:

services.AddIdentityCore<User>(options =>
{
    // ...
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;
});

A08:2021 — Software + Data Integrity Failures

EF migrations versioned trong source. Git commits signed (optional — set user.signingkey). 🔲 CI artifact SHA256 verify trước deploy.

A09:2021 — Logging + Monitoring Failures

Serilog structured → file rolling daily retention 30d prod. Request log qua UseSerilogRequestLogging. 🔲 Alert khi có /api/auth/login fail >10/min/IP (SIEM hoặc manual grep log). 🔲 Alert khi /api/contracts/{id}/transitions fail role guard >5/min (suspicious activity).

A10:2021 — SSRF

Không áp dụng — app không fetch URL do user cung cấp.

Pre go-live checklist

  • JWT_SECRET production ≥ 64 random chars
  • Connection string dùng SQL user solutionerp_app với password mạnh
  • appsettings.Production.json đã set AllowedOrigins chính xác
  • HTTPS cert valid + auto-renew (win-acme scheduled task)
  • HSTS preload list (optional)
  • Security headers middleware added
  • Account lockout enabled (5 fail → lock 15min)
  • Password policy min 12 chars prod
  • Backup SQL chạy (test restore)
  • Log retention 30d verified
  • Rate limit test: flood 10 req → 429 từ request thứ 6
  • IDOR check: user Drafter A không xem được HĐ tôi của user B
  • CSP header prevent inline script
  • Run OWASP ZAP scan → no critical finding
  • Dependencies: dotnet list package --vulnerable + npm audit → clean
  • Admin account mặc định admin@solutionerp.local — đổi password production hoặc disable

Incident response

Suspected compromise:

  1. Rotate JWT secret → mọi user bị logout
  2. Disable account lockout temporarily để admin login được
  3. Check ContractApprovals last 24h cho activity bất thường
  4. Restore SQL backup nếu có data corruption
  5. Report CERT team

Liên quan