mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-12 07:29:51 +00:00
feat: support ssh key passphrase
This commit is contained in:
parent
79dce124a7
commit
71f43c5bd4
@ -18,11 +18,12 @@ type ssh struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sshAccess struct {
|
type sshAccess struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Username string `json:"username"`
|
Port string `json:"port"`
|
||||||
Password string `json:"password"`
|
Username string `json:"username"`
|
||||||
Key string `json:"key"`
|
Password string `json:"password"`
|
||||||
Port string `json:"port"`
|
Key string `json:"key"`
|
||||||
|
KeyPassphrase string `json:"keyPassphrase"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSSH(option *DeployerOption) (Deployer, error) {
|
func NewSSH(option *DeployerOption) (Deployer, error) {
|
||||||
@ -45,6 +46,7 @@ func (s *ssh) Deploy(ctx context.Context) error {
|
|||||||
if err := json.Unmarshal([]byte(s.option.Access), access); err != nil {
|
if err := json.Unmarshal([]byte(s.option.Access), access); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接
|
// 连接
|
||||||
client, err := s.getClient(access)
|
client, err := s.getClient(access)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +59,7 @@ func (s *ssh) Deploy(ctx context.Context) error {
|
|||||||
// 执行前置命令
|
// 执行前置命令
|
||||||
preCommand := getDeployString(s.option.DeployConfig, "preCommand")
|
preCommand := getDeployString(s.option.DeployConfig, "preCommand")
|
||||||
if preCommand != "" {
|
if preCommand != "" {
|
||||||
err, stdout, stderr := s.sshExecCommand(client, preCommand)
|
stdout, stderr, err := s.sshExecCommand(client, preCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdout, stderr)
|
return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdout, stderr)
|
||||||
}
|
}
|
||||||
@ -78,7 +80,7 @@ func (s *ssh) Deploy(ctx context.Context) error {
|
|||||||
s.infos = append(s.infos, toStr("ssh上传私钥成功", nil))
|
s.infos = append(s.infos, toStr("ssh上传私钥成功", nil))
|
||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
err, stdout, stderr := s.sshExecCommand(client, getDeployString(s.option.DeployConfig, "command"))
|
stdout, stderr, err := s.sshExecCommand(client, getDeployString(s.option.DeployConfig, "command"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdout, stderr)
|
return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdout, stderr)
|
||||||
}
|
}
|
||||||
@ -88,18 +90,19 @@ func (s *ssh) Deploy(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ssh) sshExecCommand(client *sshPkg.Client, command string) (error, string, string) {
|
func (s *ssh) sshExecCommand(client *sshPkg.Client, command string) (string, string, error) {
|
||||||
session, err := client.NewSession()
|
session, err := client.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create ssh session: %w", err), "", ""
|
return "", "", fmt.Errorf("failed to create ssh session: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
var stdoutBuf bytes.Buffer
|
var stdoutBuf bytes.Buffer
|
||||||
session.Stdout = &stdoutBuf
|
session.Stdout = &stdoutBuf
|
||||||
var stderrBuf bytes.Buffer
|
var stderrBuf bytes.Buffer
|
||||||
session.Stderr = &stderrBuf
|
session.Stderr = &stderrBuf
|
||||||
err = session.Run(command)
|
err = session.Run(command)
|
||||||
return err, stdoutBuf.String(), stderrBuf.String()
|
return stdoutBuf.String(), stderrBuf.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ssh) upload(client *sshPkg.Client, content, path string) error {
|
func (s *ssh) upload(client *sshPkg.Client, content, path string) error {
|
||||||
@ -131,7 +134,15 @@ func (s *ssh) getClient(access *sshAccess) (*sshPkg.Client, error) {
|
|||||||
var authMethod sshPkg.AuthMethod
|
var authMethod sshPkg.AuthMethod
|
||||||
|
|
||||||
if access.Key != "" {
|
if access.Key != "" {
|
||||||
signer, err := sshPkg.ParsePrivateKey([]byte(access.Key))
|
var signer sshPkg.Signer
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if access.KeyPassphrase != "" {
|
||||||
|
signer, err = sshPkg.ParsePrivateKeyWithPassphrase([]byte(access.Key), []byte(access.KeyPassphrase))
|
||||||
|
} else {
|
||||||
|
signer, err = sshPkg.ParsePrivateKey([]byte(access.Key))
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
324
ui/dist/assets/index-DipHpsma.js
vendored
324
ui/dist/assets/index-DipHpsma.js
vendored
File diff suppressed because one or more lines are too long
2
ui/dist/index.html
vendored
2
ui/dist/index.html
vendored
@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DipHpsma.js"></script>
|
<script type="module" crossorigin src="/assets/index-DIhd7QG6.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CV_7sKTK.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CV_7sKTK.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background">
|
<body class="bg-background">
|
||||||
|
@ -66,17 +66,21 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
.max(5, t("common.errmsg.string_max", { max: 5 })),
|
.max(5, t("common.errmsg.string_max", { max: 5 })),
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "username.not.empty")
|
.min(1, "access.authorization.form.ssh_username.placeholder")
|
||||||
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(0, "password.not.empty")
|
.min(0, "access.authorization.form.ssh_password.placeholder")
|
||||||
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
key: z
|
key: z
|
||||||
.string()
|
.string()
|
||||||
.min(0, "access.authorization.form.ssh_key.placeholder")
|
.min(0, "access.authorization.form.ssh_key.placeholder")
|
||||||
.max(20480, t("common.errmsg.string_max", { max: 20480 })),
|
.max(20480, t("common.errmsg.string_max", { max: 20480 })),
|
||||||
keyFile: z.any().optional(),
|
keyFile: z.any().optional(),
|
||||||
|
keyPassphrase: z
|
||||||
|
.string()
|
||||||
|
.min(0, "access.authorization.form.ssh_key_passphrase.placeholder")
|
||||||
|
.max(2048, t("common.errmsg.string_max", { max: 2048 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: SSHConfig = {
|
let config: SSHConfig = {
|
||||||
@ -86,6 +90,7 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
password: "",
|
password: "",
|
||||||
key: "",
|
key: "",
|
||||||
keyFile: "",
|
keyFile: "",
|
||||||
|
keyPassphrase: "",
|
||||||
};
|
};
|
||||||
if (data) config = data.config as SSHConfig;
|
if (data) config = data.config as SSHConfig;
|
||||||
|
|
||||||
@ -102,6 +107,7 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
password: config.password,
|
password: config.password,
|
||||||
key: config.key,
|
key: config.key,
|
||||||
keyFile: config.keyFile,
|
keyFile: config.keyFile,
|
||||||
|
keyPassphrase: config.keyPassphrase,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -121,6 +127,7 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
username: data.username,
|
username: data.username,
|
||||||
password: data.password,
|
password: data.password,
|
||||||
key: data.key,
|
key: data.key,
|
||||||
|
keyPassphrase: data.keyPassphrase,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -322,9 +329,9 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
name="username"
|
name="username"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("access.authorization.form.username.label")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.ssh_username.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t("access.authorization.form.username.placeholder")} {...field} />
|
<Input placeholder={t("access.authorization.form.ssh_username.placeholder")} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -337,9 +344,9 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
name="password"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("access.authorization.form.password.label")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.ssh_password.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t("access.authorization.form.password.placeholder")} {...field} type="password" />
|
<Input placeholder={t("access.authorization.form.ssh_password.placeholder")} {...field} type="password" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -390,6 +397,21 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="keyPassphrase"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.ssh_key_passphrase.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.ssh_key_passphrase.placeholder")} {...field} type="password" />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
|
@ -100,6 +100,7 @@ export type SSHConfig = {
|
|||||||
password?: string;
|
password?: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
keyFile?: string;
|
keyFile?: string;
|
||||||
|
keyPassphrase?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WebhookConfig = {
|
export type WebhookConfig = {
|
||||||
|
@ -46,9 +46,15 @@
|
|||||||
"access.authorization.form.ssh_host.placeholder": "Please enter Host",
|
"access.authorization.form.ssh_host.placeholder": "Please enter Host",
|
||||||
"access.authorization.form.ssh_port.label": "SSH Port",
|
"access.authorization.form.ssh_port.label": "SSH Port",
|
||||||
"access.authorization.form.ssh_port.placeholder": "Please enter Port",
|
"access.authorization.form.ssh_port.placeholder": "Please enter Port",
|
||||||
"access.authorization.form.ssh_key.label": "Key (Log in using private key)",
|
"access.authorization.form.ssh_username.label": "Username",
|
||||||
|
"access.authorization.form.ssh_username.placeholder": "Please enter username",
|
||||||
|
"access.authorization.form.ssh_password.label": "Password (Log-in using password)",
|
||||||
|
"access.authorization.form.ssh_password.placeholder": "Please enter password",
|
||||||
|
"access.authorization.form.ssh_key.label": "Key (Log-in using private key)",
|
||||||
"access.authorization.form.ssh_key.placeholder": "Please enter Key",
|
"access.authorization.form.ssh_key.placeholder": "Please enter Key",
|
||||||
"access.authorization.form.ssh_key_file.placeholder": "Please select file",
|
"access.authorization.form.ssh_key_file.placeholder": "Please select file",
|
||||||
|
"access.authorization.form.ssh_key_passphrase.label": "Key Passphrase (Log-in using private key)",
|
||||||
|
"access.authorization.form.ssh_key_passphrase.placeholder": "Please enter Key Passphrase",
|
||||||
"access.authorization.form.ssh_key_path.label": "Private Key Save Path",
|
"access.authorization.form.ssh_key_path.label": "Private Key Save Path",
|
||||||
"access.authorization.form.ssh_key_path.placeholder": "Please enter private key save path",
|
"access.authorization.form.ssh_key_path.placeholder": "Please enter private key save path",
|
||||||
"access.authorization.form.ssh_cert_path.label": "Certificate Save Path",
|
"access.authorization.form.ssh_cert_path.label": "Certificate Save Path",
|
||||||
|
@ -46,10 +46,15 @@
|
|||||||
"access.authorization.form.ssh_host.placeholder": "请输入 Host",
|
"access.authorization.form.ssh_host.placeholder": "请输入 Host",
|
||||||
"access.authorization.form.ssh_port.label": "SSH 端口",
|
"access.authorization.form.ssh_port.label": "SSH 端口",
|
||||||
"access.authorization.form.ssh_port.placeholder": "请输入 Port",
|
"access.authorization.form.ssh_port.placeholder": "请输入 Port",
|
||||||
|
"access.authorization.form.ssh_username.label": "用户名",
|
||||||
|
"access.authorization.form.ssh_username.placeholder": "请输入用户名",
|
||||||
|
"access.authorization.form.ssh_password.label": "密码(使用密码登录)",
|
||||||
|
"access.authorization.form.ssh_password.placeholder": "请输入密码",
|
||||||
"access.authorization.form.ssh_key.label": "Key(使用私钥登录)",
|
"access.authorization.form.ssh_key.label": "Key(使用私钥登录)",
|
||||||
"access.authorization.form.ssh_key.placeholder": "请输入 Key",
|
"access.authorization.form.ssh_key.placeholder": "请输入 Key",
|
||||||
"access.authorization.form.ssh_key_file.placeholder": "请选择文件",
|
"access.authorization.form.ssh_key_file.placeholder": "请选择文件",
|
||||||
"access.authorization.form.ssh_key.label.passphrase": "私钥密码",
|
"access.authorization.form.ssh_key_passphrase.label": "Key 口令(使用私钥登录)",
|
||||||
|
"access.authorization.form.ssh_key_passphrase.placeholder": "请输入 Key 口令",
|
||||||
"access.authorization.form.ssh_key_path.label": "私钥保存路径",
|
"access.authorization.form.ssh_key_path.label": "私钥保存路径",
|
||||||
"access.authorization.form.ssh_key_path.placeholder": "请输入私钥保存路径",
|
"access.authorization.form.ssh_key_path.placeholder": "请输入私钥保存路径",
|
||||||
"access.authorization.form.ssh_cert_path.label": "证书保存路径",
|
"access.authorization.form.ssh_cert_path.label": "证书保存路径",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user