Аюулгүй байдал¶
Хэрэгжсэн хяналтууд, тэдгээрийн хаана амьдардаг, ба яагаад тэр байдлаар шийдэгдсэн.
Давхаргууд¶
graph TD
A["Edge nginx — TLS · HSTS · rate limit"] --> B["Next.js BFF — httpOnly cookie · CSRF"]
B --> C["Go API — JWT · RBAC · rate limit · timeout"]
C --> D["PostgreSQL — Row-Level Security"]
C --> E["Audit log — hash chain"]
Аль нэг давхарга алдвал дараагийнх барина. Жишээ: XSS гарсан ч токен httpOnly cookie-д тул алдагдахгүй; SQL нөхцөл мартагдсан ч RLS өөр хэрэглэгчийн мөрийг буцаахгүй.
Танилт ба session¶
| Хяналт | Хэрэгжилт |
|---|---|
| Нууц үг байхгүй | Identity зөвхөн eID / Google / SSO-оос |
| Токен эргэлт | Refresh бүрд хос сэлгэгдэнэ |
kind claim guard |
Refresh токеныг access болгон ашиглах боломжгүй |
| Цуцлалтын cutoff | TokensRevokedBefore-оос өмнөх токен татгалзана |
| Logout | Refresh цуцлана + access deny-list (Redis) |
| Lockout | Амжилтгүй оролдлого login_events-д, түгжинэ |
| Super admin MFA | TOTP заавал; secret AES-256-GCM-ээр шифрлэгдсэн |
Эрх олголт¶
- Хоёр давхарга: HTTP дээр JWT role/permission, DB дээр RLS.
RequirePermissionнь resolver алдвал fail-closed.- Super admin гадаргуу тусдаа middleware-ээр хаагдана.
- Дэлгэрэнгүй: RBAC ба super admin.
Security header-ууд¶
Backend бүх хариунд дараах толгойг тавина:
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'
Permissions-Policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(),
magnetometer=(), microphone=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Cross-Origin-Embedder-Policy: require-corp
Strict-Transport-Security: max-age=31536000; includeSubDomains ← зөвхөн production HTTPS
API-д default-src 'none' яагаад вэ?
API нь зөвхөн JSON буцаадаг — юу ч ачаалах шаардлагагүй. Хамгийн хатуу CSP нь энд ямар ч зардалгүй.
Frontend талын толгойнууд next.config.mjs-д тодорхойлогдож,
securityHeaders.test.ts-ээр батлагдана. Микрофон нь AI дуут чат / орчуулгад
хэрэгтэй тул frontend-ийн Permissions-Policy дээр self-ээр нээгддэг —
backend-ийнх хаалттай хэвээр.
CSRF¶
Давхар хамгаалалт (BFF давхаргад):
- Custom header
x-dgov-csrf— cross-site form илгээлт тавьж чадахгүй. - Origin / Referer шалгалт (
checkOrigin).
Мутаци хийдэг бүх browser дуудлага lib/client.ts-ийн sendJSON /
postJSON-оор явна.
Rate limit ба timeout¶
| Гадаргуу | Хязгаар |
|---|---|
/v1/auth/* |
~5/мин, body cap 4 KiB |
/v1/ai/* |
~20/мин (burst 5), timeout 50с |
/v1/public/ai/* |
~6/мин (burst 3), мессеж ≤1000 тэмдэгт |
| eID poll | ~60/мин (burst 30) |
| gov / assets / gspace бичих | ~30/мин (burst 15) |
| Бусад | Server timeout 30с |
Edge nginx дээр давхар хязгаар: нэвтрэлтийн замуудад 5r/s, аппын бусад замд 50r/s.
SQL ба input¶
- ORM байхгүй — бүх query гар бичмэл, параметржүүлсэн. String concatenation-аар query угсрахгүй.
- DTO бүр
validators.ValidatePayloads-ээр struct tag-аар шалгагдана. - Body size limit global + route тус бүр.
SSRF хамгаалалт¶
Гадаад asset татах client нь дотоод сүлжээ рүү хандахыг хориглоно
(isDisallowedFetchIP): loopback, private, link-local муж бүгд хаалттай.
OIDC provider нь request / request_uri (JAR)-ыг зориудаар дэмжихгүй —
SSRF-ийн гадаргуу нэмдэг.
Шифрлэлт¶
| Юу | Хэрхэн |
|---|---|
| Интеграцын OAuth токен | AES-256-GCM (INTEGRATION_ENC_KEY) |
| Super admin TOTP secret | AES-256-GCM (ижил түлхүүр) |
| Сэргээх кодууд | Hash |
| Client secret | Hash (pkg/secrethash) — тэгш хэмт хадгалалт байхгүй |
| Admin API key | Hash; олгох үед л ил харагдана |
| Webhook secret | Платформ тус бүрт 64 hex тэмдэгт |
Audit¶
audit_log нь hash-chain холбоост, зөвхөн-нэмэх бүртгэл. Мөр бүр өмнөх
мөрийн hash-ыг агуулна.
| Endpoint | Юу |
|---|---|
GET /v1/audit/ |
Бүртгэл унших (admin) |
GET /v1/audit/verify |
Гинжний бүрэн бүтэн байдлыг шалгах |
Дунд мөрийг өөрчилвөл гинж таарахаа болино. Дэлгэрэнгүйг Ажиглалт ба аудит-аас үз.
Boot-үеийн guard¶
Production дээр зөрчил илэрвэл API асахгүй:
| Guard | Шалгах зүйл |
|---|---|
| RLS enforceability | DB role superuser / BYPASSRLS биш |
| TLS | DSN sslmode=verify-full |
| Түлхүүрийн урт | JWT_SECRET ≥32, SSO_STATE_KEY ≥32, INTEGRATION_ENC_KEY ≥16 |
| Document-Signer | Гэрчилгээ + түлхүүр байх |
| CORS | * хориотой |
Яагаад асахгүй байх нь зөв вэ?
Чимээгүй сул горимд орох нь хамгийн аюултай — оператор бүх зүйл хэвийн гэж итгэсээр байх болно. Хатуу зогсолт нь асуудлыг deploy-ийн үед илрүүлнэ.
Secret менежмент¶
.env,backend.envнь gitignore-д; хост дээрopenssl rand-аар үүснэ.- CI-д gitleaks секрет сканнер ажиллана.
- CI-ийн deploy SSH түлхүүр нь операторын хувийн түлхүүрээс тусдаа.
Мэдэгдэх зүйл¶
| Асуудал | Төлөв |
|---|---|
| TSA (цагийн тэмдэг) гарын үсэгт | Дараагийн үе шат — одоогоор PAdES-T |
Pairwise subject_type |
Хэрэгжүүлээгүй (бүх client public) |
golangci-lint |
Go 1.26 дэмжигдэх хүртэл түр хасагдсан; go vet + gofmt ажиллана |
Эмзэг байдал мэдээлэх журам: репо-гийн SECURITY.md.