This commit is contained in:
ZhuoQinghui 2024-10-31 16:26:55 +08:00
parent 191d14cd74
commit 5c2a435597
7 changed files with 143 additions and 71 deletions

View File

@ -4,8 +4,4 @@ import "acme-mana/src"
func main() {
src.Start()
//test.TestParseCert()
//test.TestValidExist()
//test.TestParseCertInfo()
}

View File

@ -27,12 +27,12 @@ func Apply(domain Domain) {
log.Fatal(err)
}
acmeUser := AcmeUser{
acmeUser := &AcmeUser{
Email: email,
key: privateKey,
}
config := lego.NewConfig(&acmeUser)
config := lego.NewConfig(acmeUser)
client, err := lego.NewClient(config)
if err != nil {

View File

@ -6,7 +6,7 @@ import (
"os"
)
// InitSocket /*
// InitSocket 初始化 socket 文件
func InitSocket() {
log.Println("Start listen command")
// 删除旧的 socket 文件

View File

@ -2,19 +2,22 @@ package src
import (
"acme-mana/src/crypto"
"bufio"
"fmt"
"github.com/go-acme/lego/v4/log"
"github.com/go-acme/lego/v4/platform/config/env"
"gopkg.in/yaml.v3"
"os"
"strings"
)
func ReadConfig() AppConfig {
func ReadConfig() *AppConfig {
InitConfig()
file, err := os.ReadFile(GetEnvConf().ConfFile)
if err != nil {
log.Fatal(err)
}
var conf AppConfig
var conf *AppConfig
err = yaml.Unmarshal(file, &conf)
if err != nil {
log.Fatal(err)
@ -31,7 +34,7 @@ func InitConfig() {
// 配置文件不存在,则创建一个
log.Infof("配置文件不存在,自动创建默认配置文件")
// 生成默认配置
conf := defaultConf()
conf := readNewConf()
// 创建一个默认的配置文件
file, err := os.Create(GetEnvConf().ConfFile)
if err != nil {
@ -50,6 +53,121 @@ func InitConfig() {
}
func readNewConf() *AppConfig {
conf := defaultConf()
log.Println("无配置文件, 生成配置文件")
conf.CertDir = scanConfDefault("请输入证书保存目录; 默认为 cert", "cert")
isGenMsg := "是否需要自动生成用于数据传输加密的RSA密钥对? \n请输入yes(Y)/no(N) 默认为 yes"
isGenErrMsg := "请输入yes(Y)/no(N)"
isGenValues := []string{"yes", "no", "Y", "N"}
isGenEncrypt := scanConfDefaultCheck(isGenMsg, "yes", isGenValues, isGenErrMsg)
if isGenEncrypt == "no" || isGenEncrypt == "N" {
conf.Encrypt.PriKey = scanConf("请输入RSA私钥", "请输入RSA私钥")
conf.Encrypt.PubKey = scanConf("请输入RSA公钥", "请输入RSA公钥")
}
codes := []string{"alidns", "tencentcloud", "cloudflare"}
msg := fmt.Sprintf("请输入DNS提供商; 当前支持的: %s", strings.Join(codes, ","))
errMsg := fmt.Sprintf("不支持的DNS提供商; 当前支持的: %s", strings.Join(codes, ","))
conf.Use = scanConfDefaultCheck(msg, "", codes, errMsg)
switch conf.Use {
case "alidns":
fmt.Printf("阿里云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/alidns/index.html")
fmt.Printf("阿里云令牌获取方式:\n%s\n", "https://usercenter.console.aliyun.com/#/manage/ak")
fmt.Printf("阿里云SDK客户端项目地址:\n%s\n", "https://github.com/aliyun/alibaba-cloud-sdk-go?tab=readme-ov-file")
conf.Provider.Ali.RegionID = scanConf("请输入阿里云Region ID", "请输入阿里云Region ID")
conf.Provider.Ali.APIKey = scanConf("请输入阿里云API Key", "请输入阿里云API Key")
conf.Provider.Ali.SecretKey = scanConf("请输入阿里云Secret Key", "请输入阿里云Secret Key")
case "tencentcloud":
fmt.Printf("腾讯云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/tencentcloud/index.html")
fmt.Printf("腾讯云令牌获取方式: \n%s\n", "https://console.cloud.tencent.com/cam/capi")
fmt.Printf("腾讯云SDK客户端项目地址: \n%s\n", "https://github.com/tencentcloud/tencentcloud-sdk-go?tab=readme-ov-file")
conf.Provider.Tencent.SecretId = scanConf("请输入腾讯云Secret Id", "请输入腾讯云Secret Id")
conf.Provider.Tencent.SecretKey = scanConf("请输入腾讯云Secret Key", "请输入腾讯云Secret Key")
case "cloudflare":
fmt.Printf("Cloudflare DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/tencentcloud/index.html")
fmt.Printf("Cloudflare 令牌获取方式: \n%s\n", "https://blog.cloudflare.com/zh-cn/api-tokens-general-availability/")
fmt.Printf("Cloudflare SDK客户端项目地址: \n%s\n", "https://github.com/cloudflare/cloudflare-go")
conf.Provider.CloudFlare.Token = scanConf("请输入CloudFlare DNS API Token", "请输入CloudFlare Token")
}
isAddDomainMsg := "是否需要添加证书获取配置?\n您可以在此处通过控制台交互添加;也可以在配置文件创建后,直接修改配置文件.\n请输入yes(Y)/no(N) 默认为 yes"
isAddDomain := scanConfDefaultCheck(isAddDomainMsg, "yes", isGenValues, isGenErrMsg)
if isAddDomain == "no" || isAddDomain == "N" {
fmt.Printf("您可以通过手动修改%s文件, 调整证书获取配置.", GetEnvConf().ConfFile)
conf.Domains = []Domain{}
return conf
}
conf.Domains = []Domain{}
for {
name := scanConf("请输入配置名称", "配置名称不能为空")
email := scanConf("请输入邮箱", "邮箱不能为空")
host := scanConf("请输入主机名;支持泛解析;\n支持多个域名,多个域名用,(英文逗号)分割;\n如: example.com,*.example.com\n", "主机名不能为空")
// 将host通过,分割为数组
hosts := strings.Split(host, ",")
conf.Domains = append(conf.Domains, Domain{
Name: name,
Email: email,
Host: hosts,
})
isAddNextDomainMsg := "是否需要继续添加证书获取配置?\n请输入yes(Y)/no(N) 默认为 yes"
isAddNextDomain := scanConfDefaultCheck(isAddNextDomainMsg, "yes", isGenValues, isGenErrMsg)
if isAddNextDomain == "no" || isAddNextDomain == "N" {
fmt.Printf("您后续可以通过手动修改%s文件, 调整证书获取配置.", GetEnvConf().ConfFile)
return conf
}
}
}
// 读取用户输入
func scanConf(msg string, errMsg string) string {
for {
log.Println(msg)
reader := bufio.NewReader(os.Stdin)
name, err := reader.ReadString('\n')
if err != nil {
fmt.Println("读取失败;", err)
continue
}
name = strings.Trim(name, "\r\n")
if name == "" {
fmt.Println(errMsg)
continue
}
return name
}
}
func scanConfDefault(msg string, defaultContent string) string {
for {
log.Println(msg)
reader := bufio.NewReader(os.Stdin)
name, err := reader.ReadString('\n')
if err != nil {
fmt.Println("读取失败;", err)
continue
}
name = strings.Trim(name, "\r\n")
if name == "" {
return defaultContent
}
return name
}
}
func scanConfDefaultCheck(msg string, defaultContent string, values []string, errMsg string) string {
for {
content := scanConfDefault(msg, defaultContent)
// 判断内容是否在values中
for _, value := range values {
if value == content {
return content
}
}
log.Println(errMsg)
}
}
func defaultConf() *AppConfig {
//priKey, pubKey, err := GenRsa()
priKey, pubKey, err := crypto.GenRSA()
@ -69,6 +187,9 @@ func defaultConf() *AppConfig {
SecretId: "secret_id",
SecretKey: "secret_key",
},
CloudFlare: CloudFlareProvider{
Token: "token",
},
},
Domains: []Domain{
{
@ -99,6 +220,7 @@ type AppConfig struct {
type AppProvider struct {
Ali AliProvider
Tencent TencentProvider
CloudFlare CloudFlareProvider
}
type AliProvider struct {
RegionID string
@ -109,6 +231,9 @@ type TencentProvider struct {
SecretId string
SecretKey string
}
type CloudFlareProvider struct {
Token string
}
type Domain struct {
Name string
Email string
@ -130,8 +255,8 @@ func (conf AppConfig) FindDomain(name string) *Domain {
const ENV_CONF_FILE = "ACME_MANA_CONF_FILE"
func InitRuntimeConf() EnvConf {
return EnvConf{
func InitRuntimeConf() *EnvConf {
return &EnvConf{
ConfFile: env.GetOrDefaultString(ENV_CONF_FILE, "config.yml"),
}
}

View File

@ -18,7 +18,6 @@ var stderr *os.File
// Start 启动/*
func Start() {
initLog()
log.Println("Run Acme Mana...")
args := os.Args
if len(args) <= 1 {
//daemonStart()
@ -79,6 +78,7 @@ func initLog() {
守护进程启动
*/
func daemonStart() {
GetAppConfig()
isDaemon := os.Getenv("GO_DAEMON")
log.Println("Run Daemon, DAEMON Is " + isDaemon)
if isDaemon != "1" {
@ -200,31 +200,15 @@ func showPubkey() {
log.Println(key)
}
/*
守护进程接收名称
*/
// 守护进程接收命令
func daemonCommand() {
log.Println("Sending command...")
//pid, err := readPID()
//if err != nil {
// log.Fatalf("Failed to send command: %v", err)
//}
//
//_, err = os.FindProcess(pid)
//if err != nil {
// log.Fatalf("Failed to find process: %v", err)
//}
//if len(os.Args) < 3 {
// log.Fatalf("No command specified")
//}
command := os.Args[2]
sendCommand(command)
}
/*
发送命令
*/
// 发送命令
func sendCommand(command string) {
conn, err := net.Dial("unix", SocketFile)
if err != nil {
@ -245,16 +229,8 @@ func sendCommand(command string) {
log.Printf("Sending command '%s' to daemon with PID: %d", command, 0)
}
/*
*
业务进程执行任务
*/
// 业务进程执行任务
func doTask() {
// 示例每隔10秒打印一条日志
//for {
// log.Println("Daemon is running...")
// time.Sleep(10 * time.Second)
//}
// 监听主进程下发的指令
go InitSocket()

View File

@ -1,25 +0,0 @@
package src
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
)
func GenRsa() (priKey string, pubKey string, err error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", "", err
}
publicKey := &privateKey.PublicKey
publicKeyBytes := x509.MarshalPKCS1PublicKey(publicKey)
pubKey = base64.StdEncoding.EncodeToString(publicKeyBytes)
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return "", "", err
}
priKey = base64.StdEncoding.EncodeToString(privateKeyBytes)
err = nil
return
}

View File

@ -7,15 +7,15 @@ const CertFileName = "fullchain.pem"
const KeyFileName = "privkey.pem"
const CertInfoFileName = "info.json"
var appConfig AppConfig = ReadConfig()
var appConfig *AppConfig = ReadConfig()
func GetAppConfig() AppConfig {
func GetAppConfig() *AppConfig {
return appConfig
}
var envConf EnvConf = InitRuntimeConf()
var envConf *EnvConf = InitRuntimeConf()
func GetEnvConf() EnvConf {
func GetEnvConf() *EnvConf {
return envConf
}