feat(update): обновления с сервера лицензий по лицензии установки

- по умолчанию https://lic.zetit.ru/updates; клиент артефактории передаёт лицензионный
  токен установки (Authorization: Bearer), сервер отдаёт модули по признакам лицензии
- компоненты получили признак лицензии (ядро и криптосервис — updates, ЛК — web-cabinet,
  НПР — npr, экспорт QUIK — quik-export)
- в bj зашит открытый ключ подписи релизов (закрытый хранится вне сервера лицензий)
- проверено сквозной установкой bj-lk 0.2.0 из канала beta

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zuevav
2026-09-15 20:43:56 +03:00
parent 2908697363
commit 8099e50ab2
4 changed files with 41 additions and 14 deletions
+15 -2
View File
@@ -20,6 +20,15 @@ type Client struct {
Channel string // "stable" | "beta"
Pub ed25519.PublicKey // публичный ключ издателя (зашит в bj-server)
HTTP *http.Client
// Token — лицензионный токен установки (Authorization: Bearer). Сервер обновлений на
// lic.zetit.ru отдаёт файлы только действующим лицензиям, модули — по признакам лицензии.
Token string
}
func (c *Client) authorize(req *http.Request) {
if c.Token != "" {
req.Header.Set("Authorization", "Bearer "+c.Token)
}
}
// NewClient собирает клиент. pubB64 — публичный ключ в base64 (зашитый).
@@ -51,13 +60,15 @@ func (c *Client) FetchSigned(ctx context.Context) (*SignedManifest, *Manifest, e
if err != nil {
return nil, nil, err
}
c.authorize(req)
resp, err := c.HTTP.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("release: запрос манифеста: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, nil, fmt.Errorf("release: манифест HTTP %d", resp.StatusCode)
msg, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
return nil, nil, fmt.Errorf("release: манифест HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(msg)))
}
var sm SignedManifest
if err := json.NewDecoder(io.LimitReader(resp.Body, 1<<20)).Decode(&sm); err != nil {
@@ -76,13 +87,15 @@ func (c *Client) DownloadArtifact(ctx context.Context, a Artifact, destDir strin
if err != nil {
return "", err
}
c.authorize(req)
resp, err := c.HTTP.Do(req)
if err != nil {
return "", fmt.Errorf("release: скачивание %s: %w", a.Name, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("release: %s HTTP %d", a.Name, resp.StatusCode)
msg, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
return "", fmt.Errorf("release: %s HTTP %d: %s", a.Name, resp.StatusCode, strings.TrimSpace(string(msg)))
}
tmp, err := os.CreateTemp(destDir, "."+a.File+".dl-*")