feat(admin): авто-загрузка сертификатов УЦ НРД + ежесуточное обновление

Новый раздел /admin/setup → «Сертификаты УЦ» (и в шаге 3 wizard'а): список
URL .cer-файлов УЦ (одна ссылка на строку). По кнопке «Скачать сейчас»
система качает каждый URL, парсит X.509, и через certmgr -inst импортирует
в mroot (если cert == issuer, т.е. корневой) или uRoot (промежуточный).

Дедуп по SHA-256: если файл по URL не изменился — повторного импорта нет.
В runtime-конфиге сохраняется журнал FetchedCerts (CN/SHA-256/срок/статус)
для отображения в UI.

Чекбокс «Авто-обновление раз в сутки» включает фоновую горутину
StartCACertsAutoUpdater — стартует через 30 сек после bj-server, потом
тикает раз в 24 часа. При изменении сертификата он переустанавливается
без участия оператора.

Mastered tasks: #44.
This commit is contained in:
fontvielle
2026-05-14 15:50:06 +03:00
parent cb0f7efd4c
commit 2142c4f586
6 changed files with 376 additions and 0 deletions
+34
View File
@@ -24,10 +24,35 @@ type Settings struct {
Crypto CryptoSettings `json:"crypto"`
NSD NSDSettings `json:"nsd"`
LK LKSettings `json:"lk"`
CACerts CACertsSettings `json:"ca_certs"`
LastTest *TestRunResult `json:"last_test,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
// CACertsSettings — URL'ы для авто-загрузки сертификатов УЦ НРД и нашего
// УЦ. Список редактируется пользователем; раз в сутки фоновая горутина
// перекачивает каждый URL и переустанавливает сертификат, если он
// поменялся. Все сертификаты идут в mroot/uRoot хранилища КриптоПро.
type CACertsSettings struct {
URLs []string `json:"urls"`
AutoUpdate bool `json:"auto_update"`
LastFetch time.Time `json:"last_fetch"`
LastFetchLog string `json:"last_fetch_log"`
FetchedCerts []FetchedCACert `json:"fetched_certs"`
}
// FetchedCACert — информация о последнем удачно скачанном сертификате.
type FetchedCACert struct {
URL string `json:"url"`
SHA256 string `json:"sha256"`
SubjectCN string `json:"subject_cn"`
IssuerCN string `json:"issuer_cn"`
NotAfter time.Time `json:"not_after"`
Store string `json:"store"`
FetchedAt time.Time `json:"fetched_at"`
Error string `json:"error,omitempty"`
}
// PostgresSettings — DSN для подключения к БД (M2-шаг-3).
type PostgresSettings struct {
DSN string `json:"dsn"`
@@ -126,6 +151,15 @@ func (r *RuntimeConfig) UpdateNSD(s NSDSettings) error {
}
// UpdateLK сохраняет LK callback URL.
// UpdateCACerts сохраняет настройки авто-загрузки сертификатов УЦ.
func (r *RuntimeConfig) UpdateCACerts(s CACertsSettings) error {
r.mu.Lock()
r.data.CACerts = s
r.data.UpdatedAt = time.Now()
r.mu.Unlock()
return r.save()
}
func (r *RuntimeConfig) UpdateLK(s LKSettings) error {
r.mu.Lock()
r.data.LK = s