fix(ipsec): убрать неподдерживаемый параметр при подписи сертификата
Docker images / prepare-release (push) Successful in 6s
Docker images / backend-test (push) Successful in 1m37s
Docker images / frontend-image (push) Successful in 2m17s
Docker images / updater-image (push) Successful in 38s
Docker images / backend-image (push) Successful in 2m20s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 9s
Docker images / prepare-release (push) Successful in 6s
Docker images / backend-test (push) Successful in 1m37s
Docker images / frontend-image (push) Successful in 2m17s
Docker images / updater-image (push) Successful in 38s
Docker images / backend-image (push) Successful in 2m20s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 9s
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -696,21 +696,32 @@ export class MikrotikClient {
|
|||||||
: new Error(`Не удалось скачать файл ${normalized} с RouterOS`)
|
: new Error(`Не удалось скачать файл ${normalized} с RouterOS`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Создание ключевой пары + заявки: /certificate add (поля common-name, key-size, key-usage…). */
|
/**
|
||||||
async addCertificate(body: Record<string, string>, timeoutMs = 30_000): Promise<unknown> {
|
* POST с деградацией по несовместимым параметрам: набор полей `/certificate/*` зависит от версии
|
||||||
// Набор параметров `/certificate/add` зависит от версии RouterOS (напр. `comment`).
|
* RouterOS (напр. `comment`, `days-valid`). При 400 «unknown parameter X» убираем X и повторяем.
|
||||||
// Деградируем: при 400 «unknown parameter X» убираем X из тела и повторяем.
|
*/
|
||||||
|
private async postTolerant(
|
||||||
|
path: string,
|
||||||
|
body: Record<string, string>,
|
||||||
|
timeoutMs: number,
|
||||||
|
maxAttempts = 4,
|
||||||
|
): Promise<unknown> {
|
||||||
const payload: Record<string, string> = { ...body }
|
const payload: Record<string, string> = { ...body }
|
||||||
for (let attempt = 0; attempt < 4; attempt += 1) {
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
||||||
try {
|
try {
|
||||||
return await this.post("/certificate/add", payload, timeoutMs)
|
return await this.post(path, payload, timeoutMs)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const param = error instanceof MikrotikError ? unknownParameterName(error) : undefined
|
const param = error instanceof MikrotikError ? unknownParameterName(error) : undefined
|
||||||
if (!param || !(param in payload)) throw error
|
if (!param || !(param in payload)) throw error
|
||||||
delete payload[param]
|
delete payload[param]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error(`RouterOS: не удалось добавить сертификат (несовместимые параметры): ${Object.keys(body).join(", ")}`)
|
throw new Error(`RouterOS: не удалось выполнить ${path} (несовместимые параметры): ${Object.keys(body).join(", ")}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Создание ключевой пары + заявки: /certificate add (поля common-name, key-size, key-usage…). */
|
||||||
|
async addCertificate(body: Record<string, string>, timeoutMs = 30_000): Promise<unknown> {
|
||||||
|
return this.postTolerant("/certificate/add", body, timeoutMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Подпись сертификата локальным CA; sign небыстрый — увеличенный таймаут. */
|
/** Подпись сертификата локальным CA; sign небыстрый — увеличенный таймаут. */
|
||||||
@@ -723,14 +734,14 @@ export class MikrotikClient {
|
|||||||
if (params.ca) body.ca = params.ca
|
if (params.ca) body.ca = params.ca
|
||||||
if (params.daysValid != null) body["days-valid"] = String(params.daysValid)
|
if (params.daysValid != null) body["days-valid"] = String(params.daysValid)
|
||||||
try {
|
try {
|
||||||
return await this.post("/certificate/sign", body, timeoutMs)
|
return await this.postTolerant("/certificate/sign", body, timeoutMs)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Некоторые версии REST принимают цель подписи только как .id.
|
// Некоторые версии REST принимают цель подписи только как .id.
|
||||||
const certs = await this.getCertificates()
|
const certs = await this.getCertificates()
|
||||||
const row = certs.find((c) => String(c.name ?? "") === params.name)
|
const row = certs.find((c) => String(c.name ?? "") === params.name)
|
||||||
const id = row?.[".id"]
|
const id = row?.[".id"]
|
||||||
if (!id) throw e
|
if (!id) throw e
|
||||||
return await this.post("/certificate/sign", { ".id": id, ...body }, timeoutMs)
|
return await this.postTolerant("/certificate/sign", { ".id": id, ...body }, timeoutMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,12 +755,12 @@ export class MikrotikClient {
|
|||||||
if (params.passphrase?.trim()) body["export-passphrase"] = params.passphrase.trim()
|
if (params.passphrase?.trim()) body["export-passphrase"] = params.passphrase.trim()
|
||||||
let raw: unknown
|
let raw: unknown
|
||||||
try {
|
try {
|
||||||
raw = await this.post("/certificate/export-certificate", body, timeoutMs)
|
raw = await this.postTolerant("/certificate/export-certificate", body, timeoutMs)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const certs = await this.getCertificates()
|
const certs = await this.getCertificates()
|
||||||
const id = certs.find((c) => String(c.name ?? "") === params.name)?.[".id"]
|
const id = certs.find((c) => String(c.name ?? "") === params.name)?.[".id"]
|
||||||
if (!id) throw e
|
if (!id) throw e
|
||||||
raw = await this.post("/certificate/export-certificate", { ".id": id, ...body }, timeoutMs)
|
raw = await this.postTolerant("/certificate/export-certificate", { ".id": id, ...body }, timeoutMs)
|
||||||
}
|
}
|
||||||
void raw
|
void raw
|
||||||
// RouterOS создаёт cert_export_<name>.p12 либо <name>.p12 — ищем по списку файлов.
|
// RouterOS создаёт cert_export_<name>.p12 либо <name>.p12 — ищем по списку файлов.
|
||||||
|
|||||||
Reference in New Issue
Block a user