mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-04 13:34:52 +00:00
feat: support specified format on deployment to local/ssh
This commit is contained in:
@@ -2,12 +2,15 @@ package deployer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"software.sslmate.com/src/go-pkcs12"
|
||||
|
||||
"github.com/usual2970/certimate/internal/applicant"
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
@@ -180,3 +183,32 @@ func getDeployVariables(conf domain.DeployConfig) map[string]string {
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
func convertPemToPfx(certificate string, privateKey string, password string) ([]byte, error) {
|
||||
// TODO: refactor
|
||||
|
||||
certBlock, _ := pem.Decode([]byte(certificate))
|
||||
if certBlock == nil {
|
||||
return nil, fmt.Errorf("failed to decode pem")
|
||||
}
|
||||
cert, err := x509.ParseCertificate(certBlock.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse pem: %w", err)
|
||||
}
|
||||
|
||||
privkeyBlock, _ := pem.Decode([]byte(privateKey))
|
||||
if privkeyBlock == nil {
|
||||
return nil, fmt.Errorf("failed to decode pem")
|
||||
}
|
||||
privkey, err := x509.ParsePKCS1PrivateKey(privkeyBlock.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse pem: %w", err)
|
||||
}
|
||||
|
||||
pfxData, err := pkcs12.LegacyRC2.Encode(privkey, cert, nil, password)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode as pfx %w", err)
|
||||
}
|
||||
|
||||
return pfxData, nil
|
||||
}
|
||||
|
@@ -51,10 +51,6 @@ func (d *LocalDeployer) Deploy(ctx context.Context) error {
|
||||
|
||||
// 写入证书和私钥文件
|
||||
switch d.option.DeployConfig.GetConfigOrDefaultAsString("format", "pem") {
|
||||
case "pfx":
|
||||
// TODO: pfx
|
||||
return fmt.Errorf("not implemented")
|
||||
|
||||
case "pem":
|
||||
if err := fs.WriteFileString(d.option.DeployConfig.GetConfigAsString("certPath"), d.option.Certificate.Certificate); err != nil {
|
||||
return fmt.Errorf("failed to save certificate file: %w", err)
|
||||
@@ -67,6 +63,18 @@ func (d *LocalDeployer) Deploy(ctx context.Context) error {
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("保存私钥成功", nil))
|
||||
|
||||
case "pfx":
|
||||
pfxData, err := convertPemToPfx(d.option.Certificate.Certificate, d.option.Certificate.PrivateKey, d.option.DeployConfig.GetConfigAsString("pfxPassword"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert pem to pfx %w", err)
|
||||
}
|
||||
|
||||
if err := fs.WriteFile(d.option.DeployConfig.GetConfigAsString("certPath"), pfxData); err != nil {
|
||||
return fmt.Errorf("failed to save certificate file: %w", err)
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("保存证书成功", nil))
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
@@ -87,15 +95,15 @@ func (d *LocalDeployer) execCommand(command string) (string, string, error) {
|
||||
var cmd *exec.Cmd
|
||||
|
||||
switch d.option.DeployConfig.GetConfigAsString("shell") {
|
||||
case "sh":
|
||||
cmd = exec.Command("sh", "-c", command)
|
||||
|
||||
case "cmd":
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
|
||||
case "powershell":
|
||||
cmd = exec.Command("powershell", "-Command", command)
|
||||
|
||||
case "sh":
|
||||
cmd = exec.Command("sh", "-c", command)
|
||||
|
||||
case "":
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
|
@@ -60,20 +60,34 @@ func (d *SSHDeployer) Deploy(ctx context.Context) error {
|
||||
d.infos = append(d.infos, toStr("SSH 执行前置命令成功", stdout))
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
if err := d.uploadFile(client, d.option.Certificate.Certificate, d.option.DeployConfig.GetConfigAsString("certPath")); err != nil {
|
||||
return fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
// 上传证书和私钥文件
|
||||
switch d.option.DeployConfig.GetConfigOrDefaultAsString("format", "pem") {
|
||||
case "pem":
|
||||
if err := d.writeSftpFileString(client, d.option.DeployConfig.GetConfigAsString("certPath"), d.option.Certificate.Certificate); err != nil {
|
||||
return fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("SSH 上传证书成功", nil))
|
||||
|
||||
if err := d.writeSftpFileString(client, d.option.DeployConfig.GetConfigAsString("keyPath"), d.option.Certificate.PrivateKey); err != nil {
|
||||
return fmt.Errorf("failed to upload private key file: %w", err)
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("SSH 上传私钥成功", nil))
|
||||
|
||||
case "pfx":
|
||||
pfxData, err := convertPemToPfx(d.option.Certificate.Certificate, d.option.Certificate.PrivateKey, d.option.DeployConfig.GetConfigAsString("pfxPassword"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert pem to pfx %w", err)
|
||||
}
|
||||
|
||||
if err := d.writeSftpFile(client, d.option.DeployConfig.GetConfigAsString("certPath"), pfxData); err != nil {
|
||||
return fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("SSH 上传证书成功", nil))
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("SSH 上传证书成功", nil))
|
||||
|
||||
// 上传私钥
|
||||
if err := d.uploadFile(client, d.option.Certificate.PrivateKey, d.option.DeployConfig.GetConfigAsString("keyPath")); err != nil {
|
||||
return fmt.Errorf("failed to upload private key file: %w", err)
|
||||
}
|
||||
|
||||
d.infos = append(d.infos, toStr("SSH 上传私钥成功", nil))
|
||||
|
||||
// 执行命令
|
||||
command := d.option.DeployConfig.GetConfigAsString("command")
|
||||
if command != "" {
|
||||
@@ -133,7 +147,11 @@ func (d *SSHDeployer) sshExecCommand(client *ssh.Client, command string) (string
|
||||
return stdoutBuf.String(), stderrBuf.String(), err
|
||||
}
|
||||
|
||||
func (d *SSHDeployer) uploadFile(client *ssh.Client, path string, content string) error {
|
||||
func (d *SSHDeployer) writeSftpFileString(client *ssh.Client, path string, content string) error {
|
||||
return d.writeSftpFile(client, path, []byte(content))
|
||||
}
|
||||
|
||||
func (d *SSHDeployer) writeSftpFile(client *ssh.Client, path string, data []byte) error {
|
||||
sftpCli, err := sftp.NewClient(client)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create sftp client: %w", err)
|
||||
@@ -150,7 +168,7 @@ func (d *SSHDeployer) uploadFile(client *ssh.Client, path string, content string
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.Write([]byte(content))
|
||||
_, err = file.Write(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to remote file: %w", err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user