259 lines
6.8 KiB
Go
259 lines
6.8 KiB
Go
package cmd
|
||
|
||
import (
|
||
"agent-wdd/cert_manager_wdd"
|
||
"agent-wdd/log"
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
"text/tabwriter"
|
||
|
||
"github.com/spf13/cobra"
|
||
)
|
||
|
||
var (
|
||
// 证书管理命令选项
|
||
cfAPIToken string
|
||
certDir string
|
||
emailAddr string
|
||
caServer string
|
||
daysRenewal int
|
||
)
|
||
|
||
// 初始化证书管理配置
|
||
func initCertManagerConfig() *cert_manager_wdd.CertManager {
|
||
// 如果未指定API令牌,提示用户
|
||
if cfAPIToken == "" {
|
||
log.Error("未指定Cloudflare API令牌,请使用--token参数设置")
|
||
os.Exit(1)
|
||
}
|
||
|
||
// 如果未指定邮箱地址,使用默认值
|
||
if emailAddr == "" {
|
||
emailAddr = "cert@example.com"
|
||
log.Warning("未指定邮箱地址,使用默认值: %s", emailAddr)
|
||
}
|
||
|
||
// 创建证书管理器
|
||
certManager := cert_manager_wdd.NewCertManager(certDir, cfAPIToken, emailAddr)
|
||
|
||
// 设置证书更新阈值天数
|
||
if daysRenewal > 0 {
|
||
certManager.DaysBeforeRenewal = daysRenewal
|
||
}
|
||
|
||
// 设置CA服务器
|
||
if caServer != "" {
|
||
switch strings.ToLower(caServer) {
|
||
case "letsencrypt":
|
||
certManager.SetCAServer(cert_manager_wdd.LetsEncryptCA)
|
||
case "zerossl":
|
||
certManager.SetCAServer(cert_manager_wdd.ZeroSSLCA)
|
||
default:
|
||
log.Warning("未知的CA服务器: %s,使用默认值", caServer)
|
||
}
|
||
}
|
||
|
||
return certManager
|
||
}
|
||
|
||
// 添加证书管理命令
|
||
func addCertManagerSubcommands(cmd *cobra.Command) {
|
||
// 全局标志
|
||
cmd.PersistentFlags().StringVar(&cfAPIToken, "token", "", "Cloudflare API令牌")
|
||
cmd.PersistentFlags().StringVar(&certDir, "cert-dir", "", "证书保存目录")
|
||
cmd.PersistentFlags().StringVar(&emailAddr, "email", "", "申请证书使用的邮箱")
|
||
cmd.PersistentFlags().StringVar(&caServer, "ca", "letsencrypt", "CA服务器 (letsencrypt, zerossl)")
|
||
cmd.PersistentFlags().IntVar(&daysRenewal, "days", 30, "证书更新阈值天数")
|
||
|
||
// 申请证书命令
|
||
applyCmd := &cobra.Command{
|
||
Use: "apply [域名]",
|
||
Short: "申请SSL证书",
|
||
Args: cobra.ExactArgs(1),
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
domain := args[0]
|
||
log.Info("开始为域名 %s 申请证书", domain)
|
||
|
||
certManager := initCertManagerConfig()
|
||
certInfo, err := certManager.ApplyCertificate(domain)
|
||
if err != nil {
|
||
log.Error("证书申请失败: %v", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
printCertificateInfo(certInfo)
|
||
log.Info("证书申请成功")
|
||
},
|
||
}
|
||
|
||
// 列出证书命令
|
||
listCmd := &cobra.Command{
|
||
Use: "list",
|
||
Short: "列出所有证书",
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
log.Info("列出所有证书")
|
||
|
||
certManager := initCertManagerConfig()
|
||
certs, err := certManager.GetAllCerts()
|
||
if err != nil {
|
||
log.Error("获取证书列表失败: %v", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
if len(certs) == 0 {
|
||
log.Info("未找到任何证书")
|
||
return
|
||
}
|
||
|
||
printCertificatesList(certs)
|
||
},
|
||
}
|
||
|
||
// 查看证书命令
|
||
showCmd := &cobra.Command{
|
||
Use: "show [域名]",
|
||
Short: "查看指定证书的详细信息",
|
||
Args: cobra.ExactArgs(1),
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
domain := args[0]
|
||
log.Info("查看域名 %s 的证书信息", domain)
|
||
|
||
certManager := initCertManagerConfig()
|
||
certs, err := certManager.GetAllCerts()
|
||
if err != nil {
|
||
log.Error("获取证书列表失败: %v", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
var targetCert *cert_manager_wdd.CertInfo
|
||
for _, cert := range certs {
|
||
if cert.Domain == domain {
|
||
targetCert = &cert
|
||
break
|
||
}
|
||
}
|
||
|
||
if targetCert == nil {
|
||
log.Error("未找到域名 %s 的证书", domain)
|
||
os.Exit(1)
|
||
}
|
||
|
||
printCertificateDetailInfo(targetCert)
|
||
},
|
||
}
|
||
|
||
// 更新证书命令
|
||
renewCmd := &cobra.Command{
|
||
Use: "renew [域名]",
|
||
Short: "更新指定证书",
|
||
Args: cobra.ExactArgs(1),
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
domain := args[0]
|
||
log.Info("更新域名 %s 的证书", domain)
|
||
|
||
certManager := initCertManagerConfig()
|
||
certInfo, err := certManager.RenewCertificate(domain)
|
||
if err != nil {
|
||
log.Error("证书更新失败: %v", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
printCertificateInfo(certInfo)
|
||
log.Info("证书更新成功")
|
||
},
|
||
}
|
||
|
||
// 更新所有需要更新的证书
|
||
renewAllCmd := &cobra.Command{
|
||
Use: "renew-all",
|
||
Short: "更新所有需要更新的证书",
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
log.Info("更新所有需要更新的证书")
|
||
|
||
certManager := initCertManagerConfig()
|
||
certs, err := certManager.GetAllCerts()
|
||
if err != nil {
|
||
log.Error("获取证书列表失败: %v", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
needRenewalCount := 0
|
||
for _, cert := range certs {
|
||
if cert.NeedsRenewal {
|
||
needRenewalCount++
|
||
log.Info("证书 %s 需要更新 (剩余 %d 天)", cert.Domain, cert.DaysRemaining)
|
||
certInfo, err := certManager.RenewCertificate(cert.Domain)
|
||
if err != nil {
|
||
log.Error("更新证书 %s 失败: %v", cert.Domain, err)
|
||
continue
|
||
}
|
||
log.Info("证书 %s 更新成功", certInfo.Domain)
|
||
}
|
||
}
|
||
|
||
if needRenewalCount == 0 {
|
||
log.Info("没有需要更新的证书")
|
||
} else {
|
||
log.Info("共更新 %d 个证书", needRenewalCount)
|
||
}
|
||
},
|
||
}
|
||
|
||
// 将所有子命令添加到主命令
|
||
cmd.AddCommand(applyCmd, listCmd, showCmd, renewCmd, renewAllCmd)
|
||
}
|
||
|
||
// 打印证书信息
|
||
func printCertificateInfo(certInfo *cert_manager_wdd.CertInfo) {
|
||
fmt.Printf("域名: %s\n", certInfo.Domain)
|
||
fmt.Printf("注册时间: %s\n", certInfo.RegisteredAt.Format("2006-01-02 15:04:05"))
|
||
fmt.Printf("到期时间: %s\n", certInfo.ExpiresAt.Format("2006-01-02 15:04:05"))
|
||
fmt.Printf("剩余天数: %d\n", certInfo.DaysRemaining)
|
||
fmt.Printf("证书路径: %s\n", certInfo.CertPath)
|
||
fmt.Printf("密钥路径: %s\n", certInfo.KeyPath)
|
||
fmt.Printf("CA服务器: %s\n", certInfo.CAName)
|
||
fmt.Printf("是否需要更新: %v\n", certInfo.NeedsRenewal)
|
||
fmt.Printf("是否为通配符证书: %v\n", certInfo.WildcardCert)
|
||
}
|
||
|
||
// 打印证书详细信息
|
||
func printCertificateDetailInfo(certInfo *cert_manager_wdd.CertInfo) {
|
||
fmt.Printf("=============== 证书详情 ===============\n")
|
||
printCertificateInfo(certInfo)
|
||
fmt.Printf("=======================================\n")
|
||
|
||
// 打印证书内容(可选)
|
||
fmt.Printf("\n证书内容:\n")
|
||
certContent, err := os.ReadFile(certInfo.CertPath)
|
||
if err == nil {
|
||
fmt.Println(string(certContent))
|
||
} else {
|
||
fmt.Printf("无法读取证书内容: %v\n", err)
|
||
}
|
||
}
|
||
|
||
// 打印证书列表
|
||
func printCertificatesList(certs []cert_manager_wdd.CertInfo) {
|
||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||
fmt.Fprintln(w, "域名\t到期时间\t剩余天数\t需要更新\tCA服务器")
|
||
fmt.Fprintln(w, "------\t--------\t--------\t--------\t--------")
|
||
|
||
for _, cert := range certs {
|
||
needsRenewal := "否"
|
||
if cert.NeedsRenewal {
|
||
needsRenewal = "是"
|
||
}
|
||
|
||
expiresAt := cert.ExpiresAt.Format("2006-01-02")
|
||
fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\n",
|
||
cert.Domain,
|
||
expiresAt,
|
||
cert.DaysRemaining,
|
||
needsRenewal,
|
||
cert.CAName)
|
||
}
|
||
|
||
w.Flush()
|
||
}
|