feat(update): независимые обновления компонентов bj
- internal/release/components.go: список компонентов (ядро bj-server, криптосервис, bj-lk, bj-npr, bj-quikexport) с путём и службой, установленные версии в components.json, расчёт обновлений по версии каждого файла и sha256 (без отката, модули — только если уже установлены на сервере) - cmd/bj-component-install: root-установщик — сам перепроверяет подпись манифеста ключом /etc/bj/update.pub и sha256, копия прежнего файла, перезапуск только затронутых служб - updater: bj-server (без прав root) скачивает в update-staging и передаёт установку root-воркеру (действие component-install); установка в фоне - настройки: таблица компонентов с версиями, «Обновить» и «Обновить всё» - bj-release: версия файла из <файл>.version; bj-keymedia-worker: component-install Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,24 +39,32 @@ func NewClient(baseURL, channel, pubB64 string) (*Client, error) {
|
||||
// FetchManifest скачивает /v1/<channel>/manifest.json и проверяет подпись.
|
||||
// Возвращает доверенный Manifest (или ошибку, если подпись не сошлась).
|
||||
func (c *Client) FetchManifest(ctx context.Context) (*Manifest, error) {
|
||||
_, m, err := c.FetchSigned(ctx)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// FetchSigned — подписанный манифест как есть (для повторной проверки root-установщиком) и
|
||||
// проверенный Manifest.
|
||||
func (c *Client) FetchSigned(ctx context.Context) (*SignedManifest, *Manifest, error) {
|
||||
url := fmt.Sprintf("%s/v1/%s/manifest.json", c.BaseURL, c.Channel)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
resp, err := c.HTTP.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("release: запрос манифеста: %w", err)
|
||||
return nil, nil, fmt.Errorf("release: запрос манифеста: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("release: манифест HTTP %d", resp.StatusCode)
|
||||
return nil, nil, fmt.Errorf("release: манифест HTTP %d", resp.StatusCode)
|
||||
}
|
||||
var sm SignedManifest
|
||||
if err := json.NewDecoder(resp.Body).Decode(&sm); err != nil {
|
||||
return nil, fmt.Errorf("release: разбор манифеста: %w", err)
|
||||
if err := json.NewDecoder(io.LimitReader(resp.Body, 1<<20)).Decode(&sm); err != nil {
|
||||
return nil, nil, fmt.Errorf("release: разбор манифеста: %w", err)
|
||||
}
|
||||
return Verify(&sm, c.Pub) // здесь проверяется подпись
|
||||
m, err := Verify(&sm, c.Pub) // здесь проверяется подпись
|
||||
return &sm, m, err
|
||||
}
|
||||
|
||||
// DownloadArtifact скачивает артефакт в destDir, проверяет sha256/размер по
|
||||
|
||||
Reference in New Issue
Block a user