feat(managed-ne): add bastion SSH protocol proxy hop type

Support composite-username bastion login for automated connect-test and exec, with bastion-managed or manual target credential modes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-06-05 10:47:52 +08:00
parent e62f4f2c74
commit d3d7f62a02
15 changed files with 348 additions and 19 deletions

View file

@ -2,9 +2,19 @@
import { ciscoHopTemplate, huaweiHopTemplate, isAutoHopTemplate, zteHopTemplate } from "./zteHop";
export type HopVendor = "zte" | "huawei" | "cisco" | "linux";
export type HopVendor = "zte" | "huawei" | "cisco" | "linux" | "bastion";
export const HOP_VENDORS: HopVendor[] = ["zte", "huawei", "cisco", "linux"];
export type HopTargetAuthMode = "bastion_managed" | "manual";
export const HOP_VENDORS: HopVendor[] = ["zte", "huawei", "cisco", "linux", "bastion"];
export function bastionHopTemplate(): string {
return "{hop_user}@{target_user}@{target_ip}@{hop_host}";
}
export function isBastionHopVendor(vendor: string): boolean {
return String(vendor || "").toLowerCase() === "bastion";
}
export function isLinuxHopVendor(vendor: string): boolean {
return String(vendor || "").toLowerCase() === "linux";
@ -20,16 +30,34 @@ export function defaultHopTemplate(vendor: string, protocol: string, vrf: string
if (v === "huawei") return huaweiHopTemplate(protocol, vrf);
if (v === "cisco") return ciscoHopTemplate(protocol, vrf);
if (v === "linux") return "";
if (v === "bastion") return bastionHopTemplate();
return zteHopTemplate(protocol, vrf);
}
export function patchHopVendorChange(
vendor: HopVendor,
prev: { hop_protocol: string; hop_vrf: string; hop_command_template: string; hop_vendor?: string },
): { hop_vendor: HopVendor; hop_protocol: string; hop_vrf: string; hop_command_template: string } {
): {
hop_vendor: HopVendor;
hop_protocol: string;
hop_vrf: string;
hop_command_template: string;
hop_port?: number;
hop_target_auth_mode?: HopTargetAuthMode;
} {
if (vendor === "linux") {
return { hop_vendor: "linux", hop_protocol: "ssh", hop_vrf: "", hop_command_template: "" };
}
if (vendor === "bastion") {
return {
hop_vendor: "bastion",
hop_protocol: "ssh",
hop_port: 22,
hop_vrf: "",
hop_command_template: bastionHopTemplate(),
hop_target_auth_mode: "bastion_managed" as HopTargetAuthMode,
};
}
const protocol = prev.hop_protocol || "ssh";
const vrf = prev.hop_vrf || "";
return {

View file

@ -42,5 +42,6 @@ export function isAutoHopTemplate(
if (v === "huawei") return t === huaweiHopTemplate(protocol, vrf);
if (v === "cisco") return t === ciscoHopTemplate(protocol, vrf);
if (v === "linux") return t === "";
if (v === "bastion") return t === "{hop_user}@{target_user}@{target_ip}@{hop_host}";
return t === zteHopTemplate(protocol, vrf);
}