sso.dgov.mn — Нэгдсэн нэвтрэлт
Репо:
gerege-systems/sso-dgov-mn· Байрлуулалт:/opt/sso-dgov-mn/· Брэнд: Засгийн газрын нэгдсэн нэвтрэлт
Цахим Засгийн 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.6.0
Энэ репо нэмдэг зүйл нь дөрвөн модуль ба тэднийг бүртгэх мөр:
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 код.
Дөрвөн модуль
| Модуль | ID | API |
|---|---|---|
| Federation | io.gerege.nexus.sso_federation |
/api/v1/sso/federation/providers |
| Sessions | io.gerege.nexus.sso_sessions |
/api/v1/sso/sessions |
| Access Review | io.gerege.nexus.sso_access_review |
/api/v1/sso/reviews |
| Provisioning | io.gerege.nexus.sso_provisioning |
/api/v1/sso/scim |
Нээлттэй (session-гүй) зам нэг ч байхгүй — route_policy_test.go үүнийг
барина. Хэн нэвтрэх эрхтэйг шийддэг бүтээгдэхүүн бол санамсаргүйгээр
баталгаажуулалтгүй endpoint ургуулах хамгийн сүүлийн газар.
Federation
Тенант бүр өөрийн итгэх гадны IdP-үүдээ бүртгэнэ: issuer, client id, шифрлэгдсэн
secret, scope, claim-ийн зураглал. Secret нь буцаж уншигдахгүй — API нь
has_secret гэж л хариулна.
Sessions
Холбогдсон бүх аппын идэвхтэй сессүүд: хэн, хаанаас, хэзээ сүүлд харагдсан. Нэг
сесс эсвэл нэг хүний бүх сессийг таслана. Таслалт бүр хэн тасалсан, яагаад
гэдгийг sso_session_events-д бичнэ. Хүний бүх сессийг таслахад шалтгаан
заавал — тэр хүнд хэлэх хариулт байх ёстой.
Access Review
Кампанит ажил нээгдэх агшинд RBAC-ийн төлөвийг хуулж авна. Дараа нь эрх өөрчлөгдсөн ч хянагдаж байсан зүйл өөрчлөгдөхгүй — амьдаар уншдаг байсан бол Мягмар гарагт хийсэн засвар Даваа гарагт хэн нэгний баталгаажуулсан зүйлийг чимээгүй дахин бичих байв.
draft → open → closed, буцах зам байхгүй. Хаагдсан кампанит ажлыг дахин нээвэл
эцсийн гэж мэдээлсэн шийдвэр өөрчлөгдөх боломжтой болно.
Кампанит ажил цөмийн өгөгдмөл user ролийн эрхүүдийг ч хамруулна — гишүүн бүрт
автоматаар олгогддог тэр роль хэний ч гараар өгөгдөөгүй эрх учраас яг л
хянагдах ёстой зүйл.
Provisioning
SCIM 2.0-оор нэг чиглэлд түлхэнэ. Дараалал нь FOR UPDATE SKIP LOCKED-оор
уншигдаж, амжилтгүй ажил exponential backoff-оор 6 удаа давтагдаад бүртгэл
үлдээж зогсоно. Ажиллуулагч нь энэ процесс дотор goroutine-оор явна — тусад нь
deploy хийх зүйл бол deploy хийхээ мартах бас нэг зүйл.
Стек
| Контейнер | Образ | Порт (зөвхөн loopback) |
|---|---|---|
dgov_sso_postgres |
postgres:16-alpine |
5438 |
dgov_sso_backend |
sso-dgov:latest (хост дээр баригдана) |
8096 |
dgov_sso_web |
…/frontend:<commit> (GHCR) |
3016 |
Хажуугийн open.dgov.mn-ээс нэг ялгаа: тэр репод код байхгүй тул образ
татдаг, энд бинар нь хост дээр баригдана. Цөм нь go.mod-ын нэг мөрөөр
түгжигдэж ирнэ; цөмийг шинэчлэх нь тэр мөрийг өсгөх ажил — Dependabot PR нээнэ.
Бүрхүүл нь эсрэгээрээ цөмийн нийтэлсэн образ, .env-ийн WEB_IMAGE дээр
тодорхой commit-оор түгжигдсэн.
Тохиргоо
Цөмийнхөөс гадна энэ бүтээгдэхүүн нэгийг л нэмнэ:
| Хувьсагч | Юу хийх |
|---|---|
SSO_SECRET_KEY |
base64, 32 байт. Federation client secret ба SCIM токеныг шифрлэнэ. Байхгүй бол бүтээгдэхүүн асна, харин итгэмжлэл хадгалах бичилт татгалзана — цэвэр текстээр хадгалахаас татгалзсан нь дээр. |
openssl rand -base64 32
Түлхүүрээ солих нь хадгалагдсан итгэмжлэлүүд задрахаа болино гэсэн үг.
Байрлуулалтын хувьд чухал мөрүүд: PUBLIC_ORIGIN=https://sso.dgov.mn (discovery
ба токены iss эндээс гарна), OAUTH_REDIRECT_HOSTS=open.dgov.mn,
BRAND_NAME=Засгийн газрын нэгдсэн нэвтрэлт, WEB_IMAGE (бүрхүүлийн түгжээ).
Схем
db/migrations/ бол энэ репогийн түүх. Бүх хүснэгт sso_ угтвартай,
цөмийн эзэмшдэг хүснэгтэд ALTER хийдэггүй — цөмийн түүх энэ файлуудын тухай
юу ч мэдэхгүй.
Нэг өгөгдлийн санд хоёр түүх байх тул MIGRATIONS_TABLE сонголт биш:
MIGRATIONS_DIR=db/migrations MIGRATIONS_TABLE=goose_db_version_sso migrate up
Row-level security-г хүснэгт бүрт өөрөө тавьдаг: цөмийн 00029-ийн бүх
хүснэгтийг гүйдэг давталт нэг удаа ажилласан бөгөөд өөр репогийн дараа үүсгэсэн
хүснэгтэд хүрч чадахгүй.
Каталог ба цөмийн хувилбар
catalog/ дотор энэ бүтээгдэхүүний дөрвөн модуль, тэдгээрийн хажууд суудаг
цөмийн гурван апп (sso-clients, organisation, egov) байна. Сүүлийн гурав нь
хуулбар — кодыг нь цөм эзэмшдэг, энд зөвхөн каталогийн бичлэг байна.
sso-clients— OAuth2 клиентийн бүртгэл. Энэ бүтээгдэхүүний гол хэсэг.organisation— хэн байдгийн лавлагаа.egov— SSO-гийн сэдэв биш. Гэхдээ цөмийн асалтын шалгалт (appinstaller.DefaultApps)organisationбаegovхоёрыг каталогт байхыг шаарддаг: байхгүй бол платформ огт асахгүй. Каталогт байх нь суулгасан гэсэн үг биш — тенант бүртdisableхийвэл цэсэнд гарахгүй, энэ суулгац яг тэгсэн.
Платформ өөрийнхөө компилдсэн модулиудтай зөрчилдсөн каталог дээр асахаа
болино. Тиймээс цөмийн шинэ tag тэдгээр аппын нэр, хувилбарыг өөрчилвөл энэ
хуулбар хоцорч, образ баригдаад, deploy болоод, дараа нь асахаа болино. Бодит
жишээ: backend/v1.5.0 дээр io.gerege.nexus.organisation нь
"Organisation & People" 1.0.0-аас "Directory" 2.0.0 болсон.
catalog_test.go нь энэ репогийн эзэмшдэг талыг барина: дөрвөн модулийн
компилдсэн нэр, хувилбар каталогийнхтойгоо тэнцүү эсэх, мөн компилдсэн модуль
бүр каталогт байгаа эсэх. Цөмийг bump хийхдээ catalog/apps.json,
catalog/manifests/, catalog/chronicle/ доторх хуулбар бичлэгүүдийг
цөмийнхтэй тааруулах нь bump-ийн нэг хэсэг.
Цөм рүү шаардлагатай гурван PR
Эдгээрийг нуувал хожим гайхах болно. Гурвуулаа кодод ponytail: тэмдэглэлтэй.
Federation нь жинхэнэ login-д холбогдоогүй. Цөмийн
platform/ssoclientитгэх issuer-ээSSO_CLIENT_ISSUERenv-ээс уншдаг ба эдгээр мөрийн тухай юу ч мэдэхгүй. Хэрэгтэй нь:platform.OptionsдээрFederationSource. Тэр болтол энэ модуль бол бүртгэл — байгууллага юунд итгэхээ зарласан бичиг.Sessions ба access review цөмийн схемийг шууд уншина.
nexus.DBдурын SQL зөвшөөрдөг тул ажиллана, гэхдээ цөмийн багана шилжвэл чимээгүй эвдэрнэ. Хэрэгтэй нь:pkg/nexusдээрSessionStoreбаRoleStore. Тэр болтол бүх SQL модуль тус бүрийнstore.goдотор нэг газар.SCIM дараалалд зөвхөн resync л ажил нэмнэ. Цөмд хэрэглэгчийн амьдралын мөчлөгийн event байхгүй тул хоёр resync-ийн хооронд хийсэн өөрчлөлт зорилтот систем рүү очихгүй.
UI
Дөрвөн модулийн цэсний бичлэг цөмийн бүрхүүл дээр каталогоор гарна, харин хуудас
нь одоогоор [app]/[feature]-ийн "coming soon". Жинхэнэ хуудсууд цөмийн
frontend/app/module/ дотор амьдардаг бөгөөд тэдгээрийг нэмэх нь цөм рүү явах
дараагийн PR.
Ажиллуулах ба шинэчлэх
go build ./... && go test ./...
DB-тэй тестүүд (эдгээргүйгээр хамгийн чухал шалгалтууд чимээгүй алгасагдана):
SSO_TEST_DATABASE_URL=postgres://... go test -race -count=1 ./...
Серверийг шинэчлэх:
ssh root@38.180.243.138
cd /opt/sso-dgov-mn && git pull
cd deploy && REGISTRY_USER=<github-хэрэглэгч> REGISTRY_TOKEN=<read:packages> ./deploy.sh
Дэлгэрэнгүйг Ажиллагаа-аас.
Дүрмүүд
Цөмийн CONTRIBUTING энд мөрдөгдөнө. Хамгийн чухал хоёр нь:
- Upstream-first — цөмд засвар хэрэгтэй бол цөм рүү PR. Энд хуулбарлаж засахыг хориглоно; энэ репо яг тэр алдааны төлөө нэг удаа бүхэлдээ дахин баригдсан (2026-08-15 хүртэл 698 файлын зөрүүтэй fork байв).
- Бизнес логик зөвхөн модуль хэлбэрээр —
main.goдотор custom код бичихгүй.