config
This commit is contained in:
parent
50b6b90f04
commit
63f3ac828f
163
main.go
163
main.go
|
@ -4,10 +4,12 @@ import (
|
|||
"acme-client/src"
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -56,31 +58,114 @@ func onCommand() {
|
|||
switch command {
|
||||
case "help":
|
||||
showHelp()
|
||||
case "list":
|
||||
showList()
|
||||
case "add":
|
||||
addConf()
|
||||
case "del":
|
||||
delConf()
|
||||
case "edit":
|
||||
editConf()
|
||||
case "get":
|
||||
getCert()
|
||||
case "-s":
|
||||
onServerCommand()
|
||||
default:
|
||||
log.Fatalf("Unknown command: %s", command)
|
||||
log.Fatalf("不支持的指令: %s\n您可以使用 help 查看帮助", command)
|
||||
}
|
||||
}
|
||||
|
||||
// 帮助
|
||||
func showHelp() {
|
||||
log.Printf("help\t查看帮助")
|
||||
log.Printf("list\t查看配置列表")
|
||||
log.Printf("add\t添加配置")
|
||||
log.Printf("del\t删除配置")
|
||||
log.Printf("edit\t编辑配置")
|
||||
log.Printf("-s list\t查看服务端已配置的Domain名称")
|
||||
fmt.Printf("help\t查看帮助\n")
|
||||
fmt.Printf("list\t查看配置列表\n")
|
||||
fmt.Printf("add\t添加配置\n")
|
||||
fmt.Printf("del\t删除配置\n")
|
||||
fmt.Printf("edit\t修改配置\n")
|
||||
fmt.Printf("get\t从获取端获取证书,会自动判断有效期\n")
|
||||
fmt.Printf("\t[-f]\t从获取端获取证书,不判断有效期\n")
|
||||
fmt.Printf("-s list\t查看服务端已配置的Domain名称\n")
|
||||
}
|
||||
|
||||
// 显示配置列表
|
||||
func showList() {
|
||||
for i := range src.GetClientConfig().Domains {
|
||||
domain := src.GetClientConfig().Domains[i]
|
||||
log.Printf("- %s", domain.Name)
|
||||
log.Printf(" - cert: %s", domain.CertFile)
|
||||
log.Printf(" - key: %s", domain.KeyFile)
|
||||
log.Println()
|
||||
domains := src.GetClientConfig().Domains
|
||||
if len(domains) == 0 {
|
||||
fmt.Println("暂无配置; 您可以使用 add 命令添加配置")
|
||||
return
|
||||
}
|
||||
for i := range domains {
|
||||
domain := domains[i]
|
||||
fmt.Printf("%d. %s\n", i, domain.Name)
|
||||
fmt.Printf(" - 证书文件: %s\n", domain.CertFile)
|
||||
fmt.Printf(" - 密钥文件: %s\n", domain.KeyFile)
|
||||
fmt.Printf(" - 详情文件: %s\n", domain.InfoFile)
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
// 添加配置
|
||||
func addConf() {
|
||||
domain := &src.Domain{}
|
||||
name := scanConf("请输入服务端已配置名称;可以通过 -s list 查看", "名称不能为空")
|
||||
domain.Name = name
|
||||
domain.CertFile = scanConf("请输入证书文件存放全路径;如: /data/cert/fullchain.pem", "证书文件路径不能为空")
|
||||
domain.KeyFile = scanConf("请输入私钥文件存放全路径;如: /data/cert/privkey.pem", "私钥文件路径不能为空")
|
||||
domain.InfoFile = scanConf("请输入详情文件存放全路径;如: /data/cert/info.json", "详情文件路径不能为空")
|
||||
config := src.GetClientConfig()
|
||||
config.Domains = append(config.Domains, *domain)
|
||||
src.WriteConfig()
|
||||
fmt.Println("添加成功")
|
||||
showList()
|
||||
}
|
||||
|
||||
// 删除配置
|
||||
func delConf() {
|
||||
fmt.Println("当前配置: ")
|
||||
showList()
|
||||
indexInt, _ := selectDomain("请输入要删除的序号")
|
||||
config := src.GetClientConfig()
|
||||
config.Domains = append(config.Domains[:indexInt], config.Domains[indexInt+1:]...)
|
||||
src.WriteConfig()
|
||||
fmt.Println("删除成功")
|
||||
showList()
|
||||
}
|
||||
|
||||
// 修改配置
|
||||
func editConf() {
|
||||
fmt.Println("当前配置")
|
||||
showList()
|
||||
_, domain := selectDomain("请输入要修改的序号")
|
||||
msg := fmt.Sprintf("请输入服务端已配置名称;可以通过 -s list 查看\n当前配置: %s\n", domain.Name)
|
||||
domain.Name = scanConf(msg, "名称不能为空")
|
||||
certFile := fmt.Sprintf("请输入证书文件存放全路径;如: /data/cert/fullchain.pem\n当前配置: %s\n", domain.CertFile)
|
||||
domain.CertFile = scanConf(certFile, "证书文件路径不能为空")
|
||||
msg = fmt.Sprintf("请输入私钥文件存放全路径;如: /data/cert/privkey.pem\n当前配置: %s\n", domain.KeyFile)
|
||||
domain.KeyFile = scanConf(msg, "私钥文件路径不能为空")
|
||||
msg = fmt.Sprintf("请输入详情文件存放全路径;如: /data/cert/info.json\n当前配置: %s\n", domain.InfoFile)
|
||||
domain.InfoFile = scanConf(msg, "详情文件路径不能为空")
|
||||
src.WriteConfig()
|
||||
fmt.Println("修改成功")
|
||||
showList()
|
||||
}
|
||||
|
||||
func getCert() {
|
||||
_, domain := selectDomain("请选择要获取证书的配置编号")
|
||||
args := os.Args
|
||||
isDoGet := len(args) >= 3 && args[3] == "-f"
|
||||
if !isDoGet {
|
||||
infoFile := domain.InfoFile
|
||||
os.Stat(infoFile)
|
||||
//info, err := os.ReadFile(infoFile)
|
||||
//keyFile := domain.KeyFile
|
||||
}
|
||||
|
||||
//config := src.GetClientConfig()
|
||||
//domains := config.Domains
|
||||
//config.FindDomain(args[2])
|
||||
}
|
||||
|
||||
// 服务端命令
|
||||
func onServerCommand() {
|
||||
args := os.Args
|
||||
if len(args) < 3 {
|
||||
|
@ -95,13 +180,14 @@ func onServerCommand() {
|
|||
}
|
||||
}
|
||||
|
||||
// 从服务端获取域名列表
|
||||
func showServerList() {
|
||||
server := src.GetClientConfig().Server
|
||||
token, encryptToken := src.GenToken()
|
||||
url := server + "/api/v1/domain/list?token=" + encryptToken
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatal("获取服务端数据失败, 请检查 server 地址是否正确")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
|
@ -118,5 +204,52 @@ func showServerList() {
|
|||
}
|
||||
data := result.Data
|
||||
text := src.DecryptByToken(token, data)
|
||||
println(text)
|
||||
d := &[]src.SDomain{}
|
||||
err = json.Unmarshal([]byte(text), d)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for i := range *d {
|
||||
domain := (*d)[i]
|
||||
fmt.Printf("- %s\n", domain.Name)
|
||||
fmt.Printf("\t认证域名: [ ")
|
||||
for j := range domain.Host {
|
||||
host := domain.Host[j]
|
||||
fmt.Printf("%s ", host)
|
||||
}
|
||||
fmt.Printf("]\n")
|
||||
}
|
||||
}
|
||||
|
||||
// 读取用户输入
|
||||
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 selectDomain(msg string) (int, *src.Domain) {
|
||||
index := scanConf(msg, "序号不能为空")
|
||||
indexInt, err := strconv.Atoi(index)
|
||||
if err != nil {
|
||||
log.Fatal("序号错误")
|
||||
}
|
||||
config := src.GetClientConfig()
|
||||
if indexInt >= len(config.Domains) || indexInt < 0 {
|
||||
log.Fatal("序号超出范围")
|
||||
}
|
||||
return indexInt, &config.Domains[indexInt]
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ type Domain struct {
|
|||
Name string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
InfoFile string
|
||||
}
|
||||
|
||||
func (conf *ClientConfig) FindDomain(name string) *Domain {
|
||||
|
@ -93,14 +94,3 @@ func (conf *ClientConfig) FindDomain(name string) *Domain {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (conf *ClientConfig) SetServer(server string) *ClientConfig {
|
||||
// conf.Server = server
|
||||
// WriteConfig()
|
||||
// return conf
|
||||
//}
|
||||
//func (conf *ClientConfig) SetPubKey(pubkey string) *ClientConfig {
|
||||
// conf.RsaPublicKey = pubkey
|
||||
// WriteConfig()
|
||||
// return conf
|
||||
//}
|
||||
|
|
39
src/token.go
39
src/token.go
|
@ -2,8 +2,6 @@ package src
|
|||
|
||||
import (
|
||||
"acme-client/src/crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
|
@ -30,47 +28,16 @@ func GenToken() (token string, encryptToken string) {
|
|||
if err != nil {
|
||||
log.Fatal("Error encrypting data:", err)
|
||||
}
|
||||
//encryptToken = base64.StdEncoding.EncodeToString(tokenBytes)
|
||||
encryptToken = hex.EncodeToString(tokenBytes)
|
||||
|
||||
//keyBytes, err := base64.StdEncoding.DecodeString(key)
|
||||
//if err != nil {
|
||||
// log.Fatal("Error decoding public key:", err)
|
||||
//}
|
||||
//pubKey, err := x509.ParsePKCS1PublicKey(keyBytes)
|
||||
//if err != nil {
|
||||
// log.Fatal("Error parsing public key:", err)
|
||||
//}
|
||||
//
|
||||
//enToken, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pubKey, []byte(token), nil)
|
||||
//if err != nil {
|
||||
// log.Fatal("Error encrypting data:", err)
|
||||
//}
|
||||
//encryptToken = base64.StdEncoding.EncodeToString(enToken)
|
||||
return
|
||||
}
|
||||
|
||||
func DecryptByToken(token string, data string) string {
|
||||
// 使用 token 进行 DES 解密
|
||||
key := []byte(token)
|
||||
dataBytes, err := base64.StdEncoding.DecodeString(data)
|
||||
content, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
log.Fatal("Error decoding data:", err)
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
log.Fatal("Error creating cipher:", err)
|
||||
}
|
||||
|
||||
if len(dataBytes) < aes.BlockSize {
|
||||
log.Fatal("ciphertext too short")
|
||||
}
|
||||
|
||||
iv := dataBytes[:aes.BlockSize]
|
||||
dataBytes = dataBytes[aes.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(dataBytes, dataBytes)
|
||||
return string(dataBytes)
|
||||
res := crypto.DecryptAES([]byte(token), content)
|
||||
return string(res)
|
||||
}
|
||||
|
|
|
@ -15,3 +15,9 @@ type Result struct {
|
|||
Msg string
|
||||
Data string
|
||||
}
|
||||
|
||||
type SDomain struct {
|
||||
Name string
|
||||
Email string
|
||||
Host []string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user