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() }