ЦЗ Цахим Засаг
GitHub Нэвтрэх

sso.dgov.mn — Нэгдсэн нэвтрэлт

Репо: gerege-systems/sso-dgov-mn · Байрлуулалт: /opt/sso-dgov-mn/ · Брэнд: Засгийн газрын нэгдсэн нэвтрэлт / Government Single Sign-On

Цахим Засгийн identity-гийн эх сурвалж. Federation, сесс, эрхийн хяналт, хэрэглэгч нийлүүлэлт. Gerege Nexus цөмийн дээр баригдсан Түвшин 2 distribution — sso-gerege-nexus-ийн fork бөгөөд ялгаа нь зөвхөн deploy/: домэйн, портууд, nginx, орчны хувьсагчид.

Бүтээгдэхүүний код энд салбарлаж эхэлбэл upstream-ийн засварыг авдаг git merge upstream/main гэсэн нэг мөр зөрчлийн жагсаалт болно — засвар нь upstream руу PR.

Энд юу байгаа, юу байхгүй вэ

Платформын код нэг ч мөр байхгүй. Нэвтрэлт, тенант, өгөгдлийн сан ба түүний тусгаарлалт, OAuth2/OIDC сервер, ДАН ба E-ID, RBAC, аудит, аппын gate, цэс, HTTP сервер бүгд цөмийнх (бүрэн жагсаалт) бөгөөд go.mod-ын нэг мөрөөр tag-аар ирнэ:

require github.com/gerege-systems/open-gerege-nexus/backend v1.9.1

Энэ репо нэмдэг зүйл нь дөрвөн модуль ба тэднийг бүртгэх мөр:

main.go                платформыг асааж, дөрвөн модулиа бүртгэнэ
modules/federation     итгэсэн гадны IdP-ууд
modules/sessions       идэвхтэй сесс, алсаас таслах
modules/accessreview   эрхийн дахин баталгаажуулалт
modules/provisioning   SCIM 2.0 гадагш түлхэлт
internal/secret        хадгалагдсан итгэмжлэлийн шифрлэлт (AES-GCM)
catalog/               энэ бүтээгдэхүүний апп багц + manifest
db/migrations/         энэ репогийн эзэмшдэг схем

Эдгээр дөрөв нь dgov.mn экосистем дэх өөрийн Go кодын нэг тал — нөгөө тал нь open.dgov.mn-ий zarlal.

Иргэн юу хардаг вэ

Дэлгэц Хаяг Хэн
Нэвтрэх /login Хүн бүр — eID, ДАН, нууц үг
Зөвшөөрөл /oauth/consent Клиент анх хандахад: аль scope-ыг өгөх вэ
Профайл /profile Нэвтэрсэн хүн — өөрийн мэдээлэл, холбоосууд
Нэвтрэлтийн клиентүүд /sso-clients Админ — OAuth2 клиент бүртгэх, нууц эргүүлэх
Дөрвөн модулийн дэлгэц /module/sso-* Эрхтэй хүн

Нээлттэй (session-гүй) зам нэг ч байхгүй — route_policy_test.go үүнийг барина. Хэн нэвтрэх эрхтэйг шийддэг бүтээгдэхүүн бол санамсаргүйгээр баталгаажуулалтгүй endpoint ургуулах хамгийн сүүлийн газар.

Дөрвөн модуль

Модуль ID API үндэс Эрх
Federation io.gerege.nexus.sso_federation /api/v1/sso/federation sso_federation.read / .manage
Sessions io.gerege.nexus.sso_sessions /api/v1/sso/sessions sso_sessions.read / .manage
Access Review io.gerege.nexus.sso_access_review /api/v1/sso/reviews .read / .manage / .decide
Provisioning io.gerege.nexus.sso_provisioning /api/v1/sso/scim sso_provisioning.read / .manage

Federation — итгэсэн гадны IdP

Тенант бүр өөрийн итгэх гадны identity провайдеруудаа бүртгэнэ: issuer, client id, шифрлэгдсэн secret, scope, claim-ийн зураглал. Хэрэглэгч тэдгээрээр дамжин орж ирэхэд холбоос (link) үүсч, хэн хаанаас ирснийг харуулна.

GET    /api/v1/sso/federation/providers            бүртгэгдсэн IdP-ууд
POST   /api/v1/sso/federation/providers            шинээр бүртгэх
PUT    /api/v1/sso/federation/providers/{id}       засах
PUT    /api/v1/sso/federation/providers/{id}/enabled   асаах / унтраах
DELETE /api/v1/sso/federation/providers/{id}       устгах
GET    /api/v1/sso/federation/providers/{id}/links тэр IdP-ээр орсон хүмүүс
GET    /api/v1/sso/federation/links                бүх холбоос

Secret нь буцаж уншигдахгүй — API нь has_secret гэж л хариулна. Хадгалахдаа SSO_SECRET_KEY-ээр AES-GCM шифрлэнэ; түлхүүр байхгүй бол бүтээгдэхүүн асна, харин итгэмжлэл хадгалах бичилт татгалзана — цэвэр текстээр хадгалахаас татгалзсан нь дээр.

Sessions — идэвхтэй сесс, алсаас таслах

Холбогдсон бүх аппын идэвхтэй сессүүд нэг жагсаалтад: хэн, хаанаас, хэзээ сүүлд харагдсан.

GET    /api/v1/sso/sessions                идэвхтэй сессүүд
GET    /api/v1/sso/sessions/events         таслалтын түүх
GET    /api/v1/sso/sessions/users/{userID} нэг хүний сессүүд
DELETE /api/v1/sso/sessions/{id}           нэг сесс таслах
DELETE /api/v1/sso/sessions/users/{userID} тэр хүний бүх сесс — шалтгаан заавал

Таслалт бүр хэн тасалсан, яагаад гэдгийг sso_session_events-д бичнэ. Хүний бүх сессийг таслахад шалтгаан заавал — тэр хүнд хэлэх хариулт байх ёстой. Хулгайлагдсан утас, ажлаас гарсан хүн: хариу үйлдэл нь систем бүрээр тойрох биш, нэг товч.

Access Review — эрхийн дахин баталгаажуулалт

Кампанит ажил нээгдэх агшинд RBAC-ийн төлөвийг хуулж авна. Дараа нь эрх өөрчлөгдсөн ч хянагдаж байсан зүйл өөрчлөгдөхгүй — амьдаар уншдаг байсан бол Мягмар гарагт хийсэн засвар Даваа гарагт хэн нэгний баталгаажуулсан зүйлийг чимээгүй дахин бичих байв.

GET  /api/v1/sso/reviews/queue                 надад ирсэн шийдвэрүүд
GET  /api/v1/sso/reviews/campaigns             кампанит ажлууд
GET  /api/v1/sso/reviews/campaigns/{id}        нэгийнх нь дэлгэрэнгүй
GET  /api/v1/sso/reviews/campaigns/{id}/items  хянагдах эрхүүд
POST /api/v1/sso/reviews/campaigns             үүсгэх (draft)
POST /api/v1/sso/reviews/campaigns/{id}/open   нээх — энэ агшинд төлөв хуулагдана
POST /api/v1/sso/reviews/campaigns/{id}/close  хаах
PUT  /api/v1/sso/reviews/items/{id}            шийдвэр: үлдээх / хасах

draft → open → closed, буцах зам байхгүй. Хаагдсан кампанит ажлыг дахин нээвэл эцсийн гэж мэдээлсэн шийдвэр өөрчлөгдөх боломжтой болно.

Кампанит ажил цөмийн өгөгдмөл user ролийн эрхүүдийг ч хамруулна — гишүүн бүрт автоматаар олгогддог тэр роль хэний ч гараар өгөгдөөгүй эрх учраас яг л хянагдах ёстой зүйл.

Provisioning — SCIM 2.0 түлхэлт

Хүний бүртгэлийг холбогдсон систем рүү нэг чиглэлд түлхэнэ.

GET    /api/v1/sso/scim/targets              зорилтууд
POST   /api/v1/sso/scim/targets              нэмэх
PUT    /api/v1/sso/scim/targets/{id}         засах
DELETE /api/v1/sso/scim/targets/{id}         устгах
POST   /api/v1/sso/scim/targets/{id}/test    холболт шалгах
POST   /api/v1/sso/scim/targets/{id}/resync  бүгдийг дахин түлхэх
GET    /api/v1/sso/scim/runs                 ажлын түүх

Дараалал нь FOR UPDATE SKIP LOCKED-оор уншигдаж, амжилтгүй ажил exponential backoff-оор 6 удаа давтагдаад бүртгэл үлдээж зогсоно. Ажиллуулагч нь энэ процесс дотор goroutine-оор явна — тусад нь deploy хийх зүйл бол deploy хийхээ мартах бас нэг зүйл. SCIM токен нь мөн SSO_SECRET_KEY-ээр шифрлэгдэнэ.

Каталог

Энэ суулгацын каталогт долоон апп: дөрвөн SSO модуль ба цөмийн гурав — sso-clients (OAuth2 клиентийн бүртгэл), organisation (хүмүүсийн лавлагаа), egov (цөмийн асалтын шалгалт шаарддаг тул каталогт байна, тенант дээр унтраалттай).

Цөмийн шинэ tag авах бүрд эдгээр хуулбар бичлэгүүдийг цөмийнхтэй тааруулах нь bump-ийн нэг хэсэг: платформ өөрийн компилдсэн модулиудтай зөрчилдсөн каталог дээр асахаа болино. Жишээ нь v1.7.0 дээр organisation нь «Directory» 2.0.0- оос «Байгууллага» 3.0.0 болсон.

Стек

Контейнер Образ Порт (зөвхөн loopback)
dgov_sso_postgres postgres:16-alpine 5438
dgov_sso_backend sso-dgov:latest (хост дээр баригдана) 8096
dgov_sso_web …/frontend:<commit> (GHCR) 3016

Бинар нь хост дээр баригдана — энэ репод нийтлэгдсэн образ байхгүй. Цөм нь go.mod-ын нэг мөрөөр түгжигдэж ирнэ; түүнийг өсгөх PR-ыг Dependabot нээдэг. Бүрхүүл нь эсрэгээрээ цөмийн нийтэлсэн образ, docker-compose.yml дотор тодорхой commit-оор түгжигдсэн.

Пин нь compose дотор байдаг, серверийн .env дотор биш. 2026-08-17-нд тэр хоёр газарт байсны үр дүн: репо шинэ бүрхүүл заасан атал суулгац хуучин образаа үргэлжлүүлэн ажиллуулсан — серверийн хуулбар хождог.

Тохиргоо

Цөмийнхөөс гадна энэ бүтээгдэхүүн нэгийг л нэмнэ:

Хувьсагч Юу хийх
SSO_SECRET_KEY base64, 32 байт. Federation client secret ба SCIM токеныг шифрлэнэ
openssl rand -base64 32

Түлхүүрээ солих нь хадгалагдсан итгэмжлэлүүд задрахаа болино гэсэн үг.

Байрлуулалтын хувьд чухал мөрүүд:

Хаана Мөр Тайлбар
.env PUBLIC_ORIGIN=https://sso.dgov.mn discovery ба токены iss эндээс гарна
.env SSO_DEFAULT_CLIENT_SECRET Байхгүй бол production дээр цөм асахаас татгалзана
.env SSO_SECRET_KEY Дээрх
.env EID_RP_UUID / EID_RP_SECRET eID-ийн RP итгэмжлэл — энд байх ёстой, хөрш дээр биш
.env EID_JIT_TENANT_SLUG=dgov eID-ээр баталгаажсан ч бүртгэлгүй иргэнийг аль байгууллагад үүсгэх
compose OAUTH_REDIRECT_HOSTS Зөвшөөрөгдсөн redirect хостууд — клиент бүр нэрлэгдэнэ
compose WEB_IMAGE Бүрхүүлийн түгжээ (commit)
compose BRAND_DOCS_URL=https://docs.dgov.mn/ Цэсний «Баримт бичиг» — энэ сайт

EID_JIT_TENANT_SLUG дангаараа хангалтгүй: платформын platform.access_mode тохиргоо public байх ёстой. Тэр нь env биш, өгөгдлийн сан дахь мөр — «танихгүй хүнд данс үүсгэх үү» гэдэг нь дахин асаахад өөрчлөгддөг зүйл биш, шийдвэр.

Шинэчлэх

Гараар хийх зүйл алга. main руу орсон commit бүр дээр CI ажиллаж, ногоон болмогц deploy.yml SSH-ээр орж git pull && ./deploy/deploy.sh хийнэ. Улаан CI бол роллаут байхгүй. Дэлгэрэнгүйг Ажиллагаа.

Цөмийг өсгөх нь go.mod-ын нэг мөр — Dependabot PR нээнэ, CI ногоон бол merge, цаашдын бүх зүйл автомат.