Сроки сертификатов — только по нашей организации

В справочнике ИШ — сертификаты всех участников обмена (на 9 — 351: ВТБ,
Сбербанк, ТБанк…). «Свой» был любой не НРД/биржа/НКЦ/УЦ, и приходило
«Сертификат ключа организации истекает сегодня» по сотруднику Сбербанка.
Теперь свой — ИНН в subject равен ИНН нашей организации; уведомления о
сроках — только по своим (сертификаты НРД приезжают с обновлением bj);
чужие сертификаты не показываются в шаге «Сертификаты».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-22 12:09:04 +03:00
parent 8afa84a499
commit ad6b52f5fa
2 changed files with 32 additions and 16 deletions
+25 -14
View File
@@ -2,11 +2,12 @@ package lkgateway
// Сроки сертификатов в справочнике ИШ (05.10.2026). Своих сертификатов bj напрямую не видит (ключи — в // Сроки сертификатов в справочнике ИШ (05.10.2026). Своих сертификатов bj напрямую не видит (ключи — в
// Валидате и ИШ), но знает содержимое справочника активного профиля ИШ: его раз в 6 часов читает сверка // Валидате и ИШ), но знает содержимое справочника активного профиля ИШ: его раз в 6 часов читает сверка
// сертификатов НРД (nsdcerts.go, NSDCerts.LastStore). Свой сертификат — тот, что не из комплекта НРД, // сертификатов НРД (nsdcerts.go, NSDCerts.LastStore). В справочнике — сертификаты всех участников
// не самоподписанный (не УЦ) и выдан не НРД, бирже или НКЦ. По нему же отмечается шаг «Сертификаты». // обмена (на 9 — 351: ВТБ, Сбербанк, ТБанк…). Свой — ИНН в subject равен ИНН нашей организации (22.10.2026;
// раньше «своим» был любой не НРД/биржа/НКЦ/УЦ). По нему же отмечается шаг «Сертификаты».
// //
// Уведомления: за 30, 14, 7, 3 и 1 день до окончания и в день окончания — для своего сертификата и для // Уведомления: за 30, 14, 7, 3 и 1 день до окончания и в день окончания — только по сертификатам нашей
// сертификатов НРД, если им нет замены с более поздним сроком. // организации (сертификаты НРД приезжают с обновлением bj).
import ( import (
"encoding/json" "encoding/json"
@@ -65,26 +66,35 @@ func bundleSerials() map[string]bool {
return out return out
} }
// storeCertKind — own (свой), counterpart (НРД/биржа/НКЦ), ca (УЦ) или "" (не сертификат). // storeCertKind — own (нашей организации), counterpart (НРД/биржа/НКЦ), other (другие участники обмена),
func storeCertKind(c NSDStoreCert, bundle map[string]bool) string { // ca (УЦ) или "" (не сертификат). ourINN — ИНН нашей организации; пусто (ещё не задан) — своим
// считается любой, кроме НРД/биржи/НКЦ/УЦ, как до 22.10.2026.
func storeCertKind(c NSDStoreCert, bundle map[string]bool, ourINN string) string {
if c.Kind != "x509" { if c.Kind != "x509" {
return "" return ""
} }
if c.SelfSigned || strings.Contains(c.SubjectCN, "УЦ") { if c.SelfSigned || strings.Contains(c.SubjectCN, "УЦ") {
return "ca" return "ca"
} }
if bundle[normSerial(c.Serial)] || counterpartINN[subjectINN(c.Subject)] != "" { inn := subjectINN(c.Subject)
if bundle[normSerial(c.Serial)] || counterpartINN[inn] != "" {
return "counterpart" return "counterpart"
} }
if ourINN = strings.TrimLeft(strings.TrimSpace(ourINN), "0"); ourINN != "" && inn != ourINN {
return "other"
}
return "own" return "own"
} }
// ourOrgINN — ИНН нашей организации для отбора своих сертификатов.
func ourOrgINN(s Settings) string { return orgINN(s) }
// ownStoreCerts — свои сертификаты в справочнике ИШ. // ownStoreCerts — свои сертификаты в справочнике ИШ.
func ownStoreCerts(s Settings) []NSDStoreCert { func ownStoreCerts(s Settings) []NSDStoreCert {
bundle := bundleSerials() bundle, our := bundleSerials(), ourOrgINN(s)
var out []NSDStoreCert var out []NSDStoreCert
for _, c := range s.NSDCerts.LastStore { for _, c := range s.NSDCerts.LastStore {
if storeCertKind(c, bundle) == "own" { if storeCertKind(c, bundle, our) == "own" {
out = append(out, c) out = append(out, c)
} }
} }
@@ -93,12 +103,12 @@ func ownStoreCerts(s Settings) []NSDStoreCert {
// storeCertsForUI — сертификаты справочника ИШ (кроме УЦ) для шага «Сертификаты»: свой — с отметкой «ключ есть». // storeCertsForUI — сертификаты справочника ИШ (кроме УЦ) для шага «Сертификаты»: свой — с отметкой «ключ есть».
func storeCertsForUI(s Settings) []cryptocli.Certificate { func storeCertsForUI(s Settings) []cryptocli.Certificate {
bundle := bundleSerials() bundle, our := bundleSerials(), ourOrgINN(s)
var out []cryptocli.Certificate var out []cryptocli.Certificate
seen := map[string]bool{} seen := map[string]bool{}
for _, c := range s.NSDCerts.LastStore { for _, c := range s.NSDCerts.LastStore {
k := storeCertKind(c, bundle) k := storeCertKind(c, bundle, our)
if k == "" || k == "ca" || seen[c.Serial] { if k == "" || k == "ca" || k == "other" || seen[c.Serial] { // чужие сертификаты участников — не наши
continue continue
} }
seen[c.Serial] = true seen[c.Serial] = true
@@ -136,9 +146,10 @@ func certExpiryTick(rc *RuntimeConfig) {
} }
} }
changed := false changed := false
our := ourOrgINN(s)
for _, c := range s.NSDCerts.LastStore { for _, c := range s.NSDCerts.LastStore {
kind := storeCertKind(c, bundle) kind := storeCertKind(c, bundle, our)
if kind != "own" && kind != "counterpart" { if kind != "own" { // только сертификаты нашей организации
continue continue
} }
until := storeNotAfter(c) until := storeNotAfter(c)
+7 -2
View File
@@ -45,11 +45,16 @@ func TestStoreCertKindAndExpiry(t *testing.T) {
own := NSDStoreCert{Kind: "x509", Subject: "O=Предприятие 1046,CN=Сотрудник 1046,INN=078000001046", SubjectCN: "Сотрудник 1046", IssuerCN: "Тестовый УЦ", Serial: "AA01"} own := NSDStoreCert{Kind: "x509", Subject: "O=Предприятие 1046,CN=Сотрудник 1046,INN=078000001046", SubjectCN: "Сотрудник 1046", IssuerCN: "Тестовый УЦ", Serial: "AA01"}
nsd := NSDStoreCert{Kind: "x509", Subject: "O=НКО АО НРД,CN=Петров,INN=007702165310", SubjectCN: "Петров", IssuerCN: "Тестовый УЦ", Serial: "BB02"} nsd := NSDStoreCert{Kind: "x509", Subject: "O=НКО АО НРД,CN=Петров,INN=007702165310", SubjectCN: "Петров", IssuerCN: "Тестовый УЦ", Serial: "BB02"}
ca := NSDStoreCert{Kind: "x509", SubjectCN: "Тестовый УЦ", SelfSigned: true} ca := NSDStoreCert{Kind: "x509", SubjectCN: "Тестовый УЦ", SelfSigned: true}
for c, want := range map[*NSDStoreCert]string{&own: "own", &nsd: "counterpart", &ca: "ca"} { // сотрудник другого участника обмена (в справочнике ИШ их сотни) — не наш сертификат
if got := storeCertKind(*c, bundle); got != want { sber := NSDStoreCert{Kind: "x509", Subject: "O=ПАО Сбербанк,CN=Исакова,INN=007707083893", SubjectCN: "Исакова", IssuerCN: "Корневой УЦ", Serial: "CC03"}
for c, want := range map[*NSDStoreCert]string{&own: "own", &nsd: "counterpart", &ca: "ca", &sber: "other"} {
if got := storeCertKind(*c, bundle, "078000001046"); got != want {
t.Errorf("%s: %s, want %s", c.SubjectCN, got, want) t.Errorf("%s: %s, want %s", c.SubjectCN, got, want)
} }
} }
if storeCertKind(sber, bundle, "") != "own" {
t.Error("ИНН организации не задан — как раньше, свой любой не НРД")
}
if subjectINN(nsd.Subject) != "7702165310" { if subjectINN(nsd.Subject) != "7702165310" {
t.Errorf("subjectINN: %q", subjectINN(nsd.Subject)) t.Errorf("subjectINN: %q", subjectINN(nsd.Subject))
} }