迁移并重构项目,优化了执行流程
This commit is contained in:
18
internal/Func/CheckNodes.go
Normal file
18
internal/Func/CheckNodes.go
Normal file
@ -0,0 +1,18 @@
|
||||
package Func
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/class/SafeLine"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CheckNodes(nodes []SafeLine.Nodes, n int) []SafeLine.Nodes {
|
||||
var need []SafeLine.Nodes
|
||||
date := time.Now()
|
||||
for _, node := range nodes {
|
||||
days := int(node.ValidBefore.Sub(date).Hours() / 24)
|
||||
if days <= n {
|
||||
need = append(need, node)
|
||||
}
|
||||
}
|
||||
return need
|
||||
}
|
||||
20
internal/Func/ChooseProvider.go
Normal file
20
internal/Func/ChooseProvider.go
Normal file
@ -0,0 +1,20 @@
|
||||
package Func
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"SafeLine-Acme/internal/class/Acme"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
)
|
||||
|
||||
func ChooseProvider(config Acme.Object) ([]challenge.Provider, bool) {
|
||||
providers, errors := config.DNSProvider.Choose()
|
||||
for _, e := range errors {
|
||||
logger.Error.Println(e)
|
||||
}
|
||||
if len(providers) == 0 {
|
||||
logger.Error.Println()
|
||||
return nil, true
|
||||
}
|
||||
return providers, false
|
||||
}
|
||||
19
internal/Func/UpdateCheck.go
Normal file
19
internal/Func/UpdateCheck.go
Normal file
@ -0,0 +1,19 @@
|
||||
package Func
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"SafeLine-Acme/internal/class/SafeLine"
|
||||
"log"
|
||||
)
|
||||
|
||||
func UpdateCertCheck(server SafeLine.Object, days int) ([]SafeLine.Nodes, bool) {
|
||||
nodes := server.GetCertNodes()
|
||||
needUpdate := CheckNodes(nodes, days)
|
||||
if len(needUpdate) != 0 {
|
||||
log.Printf("本次需要更新证书数量有 %s%d%s 个,现在开始更新...", logger.Yellow, len(needUpdate), logger.Reset)
|
||||
} else {
|
||||
log.Print("本次无需更新证书,即将退出本程序。")
|
||||
return nil, true
|
||||
}
|
||||
return needUpdate, false
|
||||
}
|
||||
34
internal/app/logger/logger.go
Normal file
34
internal/app/logger/logger.go
Normal file
@ -0,0 +1,34 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
Reset = "\033[0m"
|
||||
Red = "\033[31m"
|
||||
Green = "\033[32m"
|
||||
Yellow = "\033[33m"
|
||||
Blue = "\033[34m"
|
||||
Magenta = "\033[35m"
|
||||
Cyan = "\033[36m"
|
||||
White = "\033[37m"
|
||||
)
|
||||
|
||||
var (
|
||||
Success *log.Logger
|
||||
Error *log.Logger
|
||||
Warning *log.Logger
|
||||
)
|
||||
|
||||
func LogInit() {
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetFlags(log.Ldate | log.Ltime)
|
||||
log.SetPrefix(fmt.Sprintf("%s[INFO]%s ", Cyan, Reset))
|
||||
|
||||
Success = log.New(os.Stdout, fmt.Sprintf("%s[SUCCESS]%s ", Green, Reset), log.Ldate|log.Ltime)
|
||||
Error = log.New(os.Stdout, fmt.Sprintf("%s[ERROR]%s ", Red, Reset), log.Ldate|log.Ltime)
|
||||
Warning = log.New(os.Stdout, fmt.Sprintf("%s[WARNING]%s ", Yellow, Reset), log.Ldate|log.Ltime)
|
||||
}
|
||||
57
internal/class/Acme/Check.go
Normal file
57
internal/class/Acme/Check.go
Normal file
@ -0,0 +1,57 @@
|
||||
package Acme
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (acme *Object) CheckFile() bool {
|
||||
var flag = true
|
||||
if acme.Email == "" {
|
||||
logger.Warning.Printf("未设置 %s证书申请邮箱%s: 请检查配置文件中的 %sAcme.Email%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(acme.DNSProvider)
|
||||
var dns = true
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
if field.Kind() == reflect.Struct {
|
||||
for ii := 0; ii < field.NumField(); ii++ {
|
||||
if field.Field(ii).String() != "" {
|
||||
dns = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if dns {
|
||||
logger.Warning.Printf("未设置 %sDNS服务提供商%s: 请检查配置文件中的 %sAcme.DNSProvider%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
}
|
||||
return flag
|
||||
}
|
||||
|
||||
func (acme *Object) CheckCommand() bool {
|
||||
var flag = true
|
||||
if acme.Email == "" {
|
||||
logger.Warning.Printf("未设置 %s证书申请邮箱%s: 请检查命令中的 %s-e%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(acme.DNSProvider).Elem()
|
||||
|
||||
var dns = true
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
if field.Kind() == reflect.Struct {
|
||||
for ii := 0; ii < field.NumField(); ii++ {
|
||||
if field.Field(ii).String() != "" {
|
||||
dns = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if dns {
|
||||
logger.Warning.Printf("未设置 %sDNS服务提供商%s: 请检查命令中的 %s-k%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
}
|
||||
return flag
|
||||
}
|
||||
20
internal/class/Acme/Method.go
Normal file
20
internal/class/Acme/Method.go
Normal file
@ -0,0 +1,20 @@
|
||||
package Acme
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (acme *Object) EmailVerify() bool {
|
||||
var EmailRegex = regexp.MustCompile(`^[a-zA-Z0-9.!#$%&'*+/=?^_{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$`)
|
||||
email := strings.TrimSpace(acme.Email)
|
||||
if len(email) < 3 || len(email) > 254 {
|
||||
return false
|
||||
}
|
||||
return EmailRegex.MatchString(email)
|
||||
}
|
||||
|
||||
func (acme *Object) DNSProviderVerify() bool {
|
||||
acme.DNSProvider.Choose()
|
||||
return true
|
||||
}
|
||||
10
internal/class/Acme/Object.go
Normal file
10
internal/class/Acme/Object.go
Normal file
@ -0,0 +1,10 @@
|
||||
package Acme
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/class/DNSProvider"
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
Email string `json:"Email"`
|
||||
DNSProvider DNSProvider.Object `json:"DNSProvider"`
|
||||
}
|
||||
107
internal/class/Config/Method.go
Normal file
107
internal/class/Config/Method.go
Normal file
@ -0,0 +1,107 @@
|
||||
package Config
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"SafeLine-Acme/internal/class/Acme"
|
||||
"SafeLine-Acme/internal/class/DNSProvider"
|
||||
"SafeLine-Acme/internal/class/SafeLine"
|
||||
"SafeLine-Acme/pkg/utils"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (config *Object) Read(path string) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
logger.Error.Printf("配置文件读取失败: %s%s%s", logger.Red, err, logger.Reset)
|
||||
os.Exit(0)
|
||||
}
|
||||
err = json.Unmarshal(data, &config)
|
||||
if err != nil {
|
||||
logger.Error.Printf("配置文件读取失败: %s%s%s", logger.Red, err, logger.Reset)
|
||||
os.Exit(0)
|
||||
}
|
||||
config.CheckFile()
|
||||
}
|
||||
func (config *Object) Write(path string) {
|
||||
data, _ := json.MarshalIndent(config, "", " ")
|
||||
_ = os.WriteFile(path, data, 0644)
|
||||
}
|
||||
|
||||
func (config *Object) Command() {
|
||||
var host, apiToken, email *string
|
||||
var days, concurrency *int
|
||||
|
||||
host = flag.String("h", "172.22.222.4:1443", "-h <host>")
|
||||
apiToken = flag.String("t", "", "-t <apiToken>")
|
||||
days = flag.Int("d", 30, "-t <days>")
|
||||
concurrency = flag.Int("c", 3, "-c <concurrency>")
|
||||
email = flag.String("e", "", "-e <email>")
|
||||
kvp := flag.String("kv", "", "-kv <key=value>,<key=value>...")
|
||||
flag.Parse()
|
||||
|
||||
var KVP = make(utils.KVPair)
|
||||
if *kvp != "" {
|
||||
KVP.Set(*kvp)
|
||||
}
|
||||
|
||||
config.Days = *days
|
||||
config.Concurrency = *concurrency
|
||||
config.Server = SafeLine.Object{
|
||||
Host: *host,
|
||||
ApiToken: *apiToken,
|
||||
}
|
||||
config.Acme = Acme.Object{
|
||||
Email: *email,
|
||||
DNSProvider: DNSProvider.Object{
|
||||
TencentCloud: DNSProvider.TencentCloud{
|
||||
SecretID: KVP["SecretID"],
|
||||
SecretKey: KVP["SecretKey"],
|
||||
},
|
||||
AliCloud: DNSProvider.AliCloud{
|
||||
AccessKeyId: KVP["AccessKeyId"],
|
||||
AccessKeySecret: KVP["AccessKeySecret"],
|
||||
RAMRole: KVP["RAMRole"],
|
||||
STSToken: KVP["STSToken"],
|
||||
},
|
||||
HuaweiCloud: DNSProvider.HuaweiCloud{
|
||||
AccessKeyId: KVP["AccessKeyId"],
|
||||
Region: KVP["Region"],
|
||||
SecretAccessKey: KVP["SecretAccessKey"],
|
||||
},
|
||||
WestCN: DNSProvider.WestCN{
|
||||
Username: KVP["Username"],
|
||||
Password: KVP["Password"],
|
||||
},
|
||||
RainYun: DNSProvider.RainYun{
|
||||
ApiKey: KVP["ApiKey"],
|
||||
},
|
||||
Dode: DNSProvider.Dode{
|
||||
Token: KVP["Token"],
|
||||
},
|
||||
},
|
||||
}
|
||||
config.CheckCommand()
|
||||
}
|
||||
|
||||
func (config *Object) CheckFile() {
|
||||
a := config.Server.CheckFile()
|
||||
b := config.Acme.CheckFile()
|
||||
if !a || !b {
|
||||
log.Printf("配置检查完毕,请检查相关配置后重新运行!")
|
||||
os.Exit(0)
|
||||
}
|
||||
log.Printf("配置检查完毕,即将开始更新证书!")
|
||||
}
|
||||
|
||||
func (config *Object) CheckCommand() {
|
||||
a := config.Server.CheckCommand()
|
||||
b := config.Acme.CheckCommand()
|
||||
if !a || !b {
|
||||
log.Printf("配置检查完毕,请检查相关配置后重新运行!")
|
||||
os.Exit(0)
|
||||
}
|
||||
log.Printf("配置检查完毕,即将开始更新证书!")
|
||||
}
|
||||
13
internal/class/Config/Object.go
Normal file
13
internal/class/Config/Object.go
Normal file
@ -0,0 +1,13 @@
|
||||
package Config
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/class/Acme"
|
||||
"SafeLine-Acme/internal/class/SafeLine"
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
Concurrency int `json:"Concurrency"`
|
||||
Days int `json:"Days"`
|
||||
Server SafeLine.Object `json:"Server"`
|
||||
Acme Acme.Object `json:"Acme"`
|
||||
}
|
||||
49
internal/class/Config/default.go
Normal file
49
internal/class/Config/default.go
Normal file
@ -0,0 +1,49 @@
|
||||
package Config
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/class/Acme"
|
||||
"SafeLine-Acme/internal/class/DNSProvider"
|
||||
"SafeLine-Acme/internal/class/SafeLine"
|
||||
)
|
||||
|
||||
func (config *Object) Default() {
|
||||
a := Object{
|
||||
Concurrency: 3,
|
||||
Days: 15,
|
||||
Server: SafeLine.Object{
|
||||
Host: "192.168.1.4:1443",
|
||||
ApiToken: "xxx",
|
||||
},
|
||||
Acme: Acme.Object{
|
||||
Email: "xxx",
|
||||
DNSProvider: DNSProvider.Object{
|
||||
TencentCloud: DNSProvider.TencentCloud{
|
||||
SecretID: "xxx",
|
||||
SecretKey: "xxx",
|
||||
},
|
||||
AliCloud: DNSProvider.AliCloud{
|
||||
AccessKeyId: "xxx",
|
||||
AccessKeySecret: "xxx",
|
||||
RAMRole: "xxx(可选)",
|
||||
STSToken: "xxx(可选)",
|
||||
},
|
||||
HuaweiCloud: DNSProvider.HuaweiCloud{
|
||||
AccessKeyId: "xxx",
|
||||
Region: "xxx",
|
||||
SecretAccessKey: "xxx",
|
||||
},
|
||||
WestCN: DNSProvider.WestCN{
|
||||
Username: "xxx",
|
||||
Password: "xxx",
|
||||
},
|
||||
RainYun: DNSProvider.RainYun{
|
||||
ApiKey: "xxx",
|
||||
},
|
||||
Dode: DNSProvider.Dode{
|
||||
Token: "xxx",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
a.Write("./config.json")
|
||||
}
|
||||
60
internal/class/DNSProvider/Method.go
Normal file
60
internal/class/DNSProvider/Method.go
Normal file
@ -0,0 +1,60 @@
|
||||
package DNSProvider
|
||||
|
||||
import (
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/dode"
|
||||
"github.com/go-acme/lego/v4/providers/dns/huaweicloud"
|
||||
"github.com/go-acme/lego/v4/providers/dns/rainyun"
|
||||
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
|
||||
"github.com/go-acme/lego/v4/providers/dns/westcn"
|
||||
)
|
||||
|
||||
func (tencent TencentCloud) Provider() (challenge.Provider, error) {
|
||||
cfg := tencentcloud.NewDefaultConfig()
|
||||
cfg.SecretID = tencent.SecretID
|
||||
cfg.SecretKey = tencent.SecretKey
|
||||
p, err := tencentcloud.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (ali AliCloud) Provider() (challenge.Provider, error) {
|
||||
cfg := alidns.NewDefaultConfig()
|
||||
cfg.SecurityToken = ali.STSToken
|
||||
cfg.SecretKey = ali.AccessKeySecret
|
||||
cfg.RAMRole = ali.RAMRole
|
||||
cfg.APIKey = ali.AccessKeyId
|
||||
p, err := alidns.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (huawei HuaweiCloud) Provider() (challenge.Provider, error) {
|
||||
cfg := huaweicloud.NewDefaultConfig()
|
||||
cfg.Region = huawei.Region
|
||||
cfg.AccessKeyID = huawei.AccessKeyId
|
||||
cfg.SecretAccessKey = huawei.SecretAccessKey
|
||||
p, err := huaweicloud.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (west WestCN) Provider() (challenge.Provider, error) {
|
||||
cfg := westcn.NewDefaultConfig()
|
||||
cfg.Username = west.Username
|
||||
cfg.Password = west.Password
|
||||
p, err := westcn.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (rain RainYun) Provider() (challenge.Provider, error) {
|
||||
cfg := rainyun.NewDefaultConfig()
|
||||
cfg.APIKey = rain.ApiKey
|
||||
p, err := rainyun.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (Dode Dode) Provider() (challenge.Provider, error) {
|
||||
cfg := dode.NewDefaultConfig()
|
||||
cfg.Token = Dode.Token
|
||||
p, err := dode.NewDNSProviderConfig(cfg)
|
||||
return p, err
|
||||
}
|
||||
43
internal/class/DNSProvider/Object.go
Normal file
43
internal/class/DNSProvider/Object.go
Normal file
@ -0,0 +1,43 @@
|
||||
package DNSProvider
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
TencentCloud TencentCloud `json:"TencentCloud,omitempty"`
|
||||
AliCloud AliCloud `json:"AliCloud,omitempty"`
|
||||
HuaweiCloud HuaweiCloud `json:"HuaweiCloud,omitempty"`
|
||||
WestCN WestCN `json:"WestCN,omitempty"`
|
||||
RainYun RainYun `json:"RainYun,omitempty"`
|
||||
Dode Dode `json:"Dode,omitempty"`
|
||||
}
|
||||
|
||||
func (dnsProvider *Object) Choose() ([]challenge.Provider, []error) {
|
||||
|
||||
var Providers []challenge.Provider
|
||||
var Errors []error
|
||||
v := reflect.ValueOf(dnsProvider).Elem()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
if field.Kind() == reflect.Struct {
|
||||
for ii := 0; ii < field.NumField(); ii++ {
|
||||
if field.Field(ii).String() != "" {
|
||||
method, _ := field.Type().MethodByName("Provider")
|
||||
results := method.Func.Call([]reflect.Value{field})
|
||||
err, _ := results[1].Interface().(error)
|
||||
if err != nil {
|
||||
Errors = append(Errors, err)
|
||||
} else {
|
||||
Providers = append(Providers, results[0].Interface().(challenge.Provider))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Providers, Errors
|
||||
}
|
||||
32
internal/class/DNSProvider/Objects.go
Normal file
32
internal/class/DNSProvider/Objects.go
Normal file
@ -0,0 +1,32 @@
|
||||
package DNSProvider
|
||||
|
||||
type TencentCloud struct {
|
||||
SecretID string `json:"SecretId,omitempty"`
|
||||
SecretKey string `json:"SecretKey,omitempty"`
|
||||
}
|
||||
|
||||
type AliCloud struct {
|
||||
AccessKeyId string `json:"AccessKeyId,omitempty"`
|
||||
AccessKeySecret string `json:"AccessKeySecret,omitempty"`
|
||||
RAMRole string `json:"RAMRole,omitempty"`
|
||||
STSToken string `json:"STSToken,omitempty"`
|
||||
}
|
||||
|
||||
type HuaweiCloud struct {
|
||||
AccessKeyId string `json:"AccessKeyId,omitempty"`
|
||||
Region string `json:"Region,omitempty"`
|
||||
SecretAccessKey string `json:"SecretAccessKey,omitempty"`
|
||||
}
|
||||
|
||||
type WestCN struct {
|
||||
Username string `json:"Username,omitempty"`
|
||||
Password string `json:"Password,omitempty"`
|
||||
}
|
||||
|
||||
type RainYun struct {
|
||||
ApiKey string `json:"ApiKey,omitempty"`
|
||||
}
|
||||
|
||||
type Dode struct {
|
||||
Token string `json:"Token,omitempty"`
|
||||
}
|
||||
42
internal/class/SafeLine/Cert.go
Normal file
42
internal/class/SafeLine/Cert.go
Normal file
@ -0,0 +1,42 @@
|
||||
package SafeLine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type UpdateReq struct {
|
||||
Acme struct {
|
||||
Domains []string `json:"domains"`
|
||||
Email string `json:"email"`
|
||||
} `json:"acme"`
|
||||
Id int `json:"id"`
|
||||
Manual struct {
|
||||
Crt string `json:"crt"`
|
||||
Key string `json:"key"`
|
||||
} `json:"manual"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
func (updateReq *UpdateReq) Create(Certificate, PrivateKey []byte, domains []string, email string, id, Type int) {
|
||||
updateReq.Acme.Domains = domains
|
||||
updateReq.Acme.Email = email
|
||||
updateReq.Manual.Crt = string(Certificate)
|
||||
updateReq.Manual.Key = string(PrivateKey)
|
||||
updateReq.Id = id
|
||||
updateReq.Type = Type
|
||||
}
|
||||
|
||||
func (updateReq *UpdateReq) Marshal() []byte {
|
||||
data, _ := json.Marshal(updateReq)
|
||||
return data
|
||||
}
|
||||
|
||||
type UpdateResp struct {
|
||||
Data int `json:"data"`
|
||||
Err interface{} `json:"err"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func (updateResp *UpdateResp) Unmarshal(data []byte) {
|
||||
_ = json.Unmarshal(data, &updateResp)
|
||||
}
|
||||
29
internal/class/SafeLine/CheckMethod.go
Normal file
29
internal/class/SafeLine/CheckMethod.go
Normal file
@ -0,0 +1,29 @@
|
||||
package SafeLine
|
||||
|
||||
import "SafeLine-Acme/internal/app/logger"
|
||||
|
||||
func (safeLine *Object) CheckFile() bool {
|
||||
var flag = true
|
||||
if safeLine.Host == "" {
|
||||
logger.Warning.Printf("未设置 %s服务器主机%s: 请检查配置文件中的 %sServer.Host%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
if safeLine.ApiToken == "" {
|
||||
logger.Warning.Printf("未设置 %sSafeLine API Token%s : 请检查配置文件中的 %sServer.ApiToken%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
return flag
|
||||
}
|
||||
|
||||
func (safeLine *Object) CheckCommand() bool {
|
||||
var flag = true
|
||||
if safeLine.Host == "" {
|
||||
logger.Warning.Printf("未设置 %s服务器主机%s: 请检查命令中的 %s-h%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
if safeLine.ApiToken == "" {
|
||||
logger.Warning.Printf("未设置 %sSafeLine API Token%s : 请检查命令中的 %s-t%s 参数", logger.Cyan, logger.Reset, logger.Yellow, logger.Reset)
|
||||
flag = false
|
||||
}
|
||||
return flag
|
||||
}
|
||||
52
internal/class/SafeLine/Method.go
Normal file
52
internal/class/SafeLine/Method.go
Normal file
@ -0,0 +1,52 @@
|
||||
package SafeLine
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"SafeLine-Acme/pkg/utils"
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (safeLine *Object) GetCertNodes() []Nodes {
|
||||
header := http.Header{
|
||||
"X-SLCE-API-TOKEN": []string{safeLine.ApiToken},
|
||||
}
|
||||
resp, err := utils.Request("GET", safeLine.SSLCertUrl(), nil, header)
|
||||
if err != nil {
|
||||
logger.Error.Printf("请求接口 %s/api/open/cert%s 时发生错误: %s%s%s", logger.Cyan, logger.Reset, logger.Red, err, logger.Reset)
|
||||
os.Exit(0)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, _ := io.ReadAll(resp.Body)
|
||||
var listResp ListResp
|
||||
listResp.Unmarshal(data)
|
||||
return listResp.Data.Nodes
|
||||
}
|
||||
|
||||
func (safeLine *Object) UpdateCert(email string, Certificate, PrivateKey []byte, cert Nodes) ([]string, []string) {
|
||||
|
||||
header := http.Header{
|
||||
"X-SLCE-API-TOKEN": []string{safeLine.ApiToken},
|
||||
"Content-Type": []string{"application/json"},
|
||||
}
|
||||
var updateReq UpdateReq
|
||||
updateReq.Create(Certificate, PrivateKey, cert.Domains, email, cert.Id, cert.Type)
|
||||
resp, err := utils.Request("POST", safeLine.SSLCertUrl(), bytes.NewReader(updateReq.Marshal()), header)
|
||||
if err != nil {
|
||||
logger.Error.Printf("更新证书时发生错误: %s%s%s", logger.Red, err, logger.Reset)
|
||||
return nil, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, _ := io.ReadAll(resp.Body)
|
||||
var updateResp UpdateResp
|
||||
updateResp.Unmarshal(data)
|
||||
if updateResp.Msg != "" {
|
||||
logger.Error.Printf("域名 %s%s%s 证书更新失败: %s%s%s", logger.Cyan, cert.Domains, logger.Reset, logger.Red, updateResp.Msg, logger.Reset)
|
||||
return nil, cert.Domains
|
||||
}
|
||||
logger.Success.Printf("域名 %s%s%s 证书更新成功!", logger.Cyan, cert.Domains, logger.Reset)
|
||||
return cert.Domains, nil
|
||||
|
||||
}
|
||||
6
internal/class/SafeLine/Object.go
Normal file
6
internal/class/SafeLine/Object.go
Normal file
@ -0,0 +1,6 @@
|
||||
package SafeLine
|
||||
|
||||
type Object struct {
|
||||
Host string `json:"Host"`
|
||||
ApiToken string `json:"ApiToken"`
|
||||
}
|
||||
33
internal/class/SafeLine/Other.go
Normal file
33
internal/class/SafeLine/Other.go
Normal file
@ -0,0 +1,33 @@
|
||||
package SafeLine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ListResp struct {
|
||||
Data struct {
|
||||
Nodes []Nodes `json:"nodes"`
|
||||
Total int `json:"total"`
|
||||
} `json:"data"`
|
||||
Err string `json:"err"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
type Nodes struct {
|
||||
Id int `json:"id"`
|
||||
Domains []string `json:"domains"`
|
||||
Issuer string `json:"issuer"`
|
||||
SelfSignature bool `json:"self_signature"`
|
||||
Trusted bool `json:"trusted"`
|
||||
Revoked bool `json:"revoked"`
|
||||
Expired bool `json:"expired"`
|
||||
Type int `json:"type"`
|
||||
AcmeMessage string `json:"acme_message"`
|
||||
ValidBefore time.Time `json:"valid_before"`
|
||||
RelatedSites []string `json:"related_sites"`
|
||||
}
|
||||
|
||||
func (listResp *ListResp) Unmarshal(data []byte) {
|
||||
_ = json.Unmarshal(data, &listResp)
|
||||
}
|
||||
42
internal/class/SafeLine/VerifyMethod.go
Normal file
42
internal/class/SafeLine/VerifyMethod.go
Normal file
@ -0,0 +1,42 @@
|
||||
package SafeLine
|
||||
|
||||
import (
|
||||
"SafeLine-Acme/internal/app/logger"
|
||||
"SafeLine-Acme/pkg/utils"
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (safeLine *Object) Verify() bool {
|
||||
err := safeLine.ServerVerify()
|
||||
if err != nil {
|
||||
logger.Error.Printf("请求服务端时发生错误: %s%s%s", logger.Red, err.Error(), logger.Reset)
|
||||
return false
|
||||
}
|
||||
|
||||
err = safeLine.AuthTokenVerify()
|
||||
if err != nil {
|
||||
logger.Warning.Printf("%sSafeLine API Token%s 验证失败,请检查后重试", logger.Cyan, logger.Reset)
|
||||
return false
|
||||
}
|
||||
|
||||
logger.Success.Printf("%sSafeLine%s 相关配置检验完成!", logger.Cyan, logger.Reset)
|
||||
return true
|
||||
}
|
||||
|
||||
func (safeLine *Object) ServerVerify() error {
|
||||
_, err := utils.Request("GET", safeLine.Url().String(), nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (safeLine *Object) AuthTokenVerify() error {
|
||||
header := http.Header{
|
||||
"X-SLCE-API-TOKEN": []string{safeLine.ApiToken},
|
||||
}
|
||||
|
||||
resp, err := utils.Request("GET", safeLine.AuthTokenUrl(), nil, header)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
return errors.New("token 验证失败")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
26
internal/class/SafeLine/url.go
Normal file
26
internal/class/SafeLine/url.go
Normal file
@ -0,0 +1,26 @@
|
||||
package SafeLine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func (safeLine *Object) Url() *url.URL {
|
||||
var u *url.URL
|
||||
u, _ = url.Parse(fmt.Sprintf("https://%s", safeLine.Host))
|
||||
return u
|
||||
}
|
||||
|
||||
func (safeLine *Object) AuthTokenUrl() string {
|
||||
path := "/api/open/auth/token"
|
||||
u := safeLine.Url()
|
||||
u.Path = path
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func (safeLine *Object) SSLCertUrl() string {
|
||||
path := "/api/open/cert"
|
||||
u := safeLine.Url()
|
||||
u.Path = path
|
||||
return u.String()
|
||||
}
|
||||
1
internal/moudle/UpdateCert.go
Normal file
1
internal/moudle/UpdateCert.go
Normal file
@ -0,0 +1 @@
|
||||
package moudle
|
||||
Reference in New Issue
Block a user