Files
WddSuperAgent/agent-wdd/cmd/CertManager.go

242 lines
6.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"agent-wdd/cert_manager_wdd"
"agent-wdd/log"
"fmt"
"os"
"strings"
"text/tabwriter"
"github.com/spf13/cobra"
)
const (
// 证书管理命令选项
cfAPIToken = "T7LxBemfe8SNGWkT9uz2XIc1e22ifAbBv_POJvDP"
certDir = "/root/wdd/cert_manager_wdd/"
emailAddr = "wdd@gmail.com"
caServer = "zerossl"
daysRenewal = 30
)
// 初始化证书管理配置
func initCertManagerConfig() *cert_manager_wdd.CertManager {
// 创建证书管理器
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) {
// 申请证书命令
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()
}