chore: remove unused code
This commit is contained in:
@@ -1,213 +0,0 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/usual2970/certimate/internal/applicant"
|
||||
"github.com/usual2970/certimate/internal/deployer"
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/utils/app"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/utils/x509"
|
||||
)
|
||||
|
||||
type Phase string
|
||||
|
||||
const (
|
||||
checkPhase Phase = "check"
|
||||
applyPhase Phase = "apply"
|
||||
deployPhase Phase = "deploy"
|
||||
)
|
||||
|
||||
const validityDuration = time.Hour * 24 * 10
|
||||
|
||||
func deploy(ctx context.Context, record *models.Record) error {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
app.GetApp().Logger().Error("部署失败", "err", r)
|
||||
}
|
||||
}()
|
||||
var certificate *applicant.Certificate
|
||||
|
||||
history := NewHistory(record)
|
||||
defer history.commit()
|
||||
|
||||
// ############1.检查域名配置
|
||||
history.record(checkPhase, "开始检查", nil)
|
||||
|
||||
currRecord, err := app.GetApp().Dao().FindRecordById("domains", record.Id)
|
||||
if err != nil {
|
||||
app.GetApp().Logger().Error("获取记录失败", "err", err)
|
||||
history.record(checkPhase, "获取域名配置失败", &RecordInfo{Err: err})
|
||||
return err
|
||||
}
|
||||
history.record(checkPhase, "获取记录成功", nil)
|
||||
|
||||
cert := currRecord.GetString("certificate")
|
||||
expiredAt := currRecord.GetDateTime("expiredAt").Time()
|
||||
|
||||
// 检查证书是否包含设置的所有域名
|
||||
changed := isCertChanged(cert, currRecord)
|
||||
|
||||
if cert != "" && time.Until(expiredAt) > validityDuration && currRecord.GetBool("deployed") && !changed {
|
||||
app.GetApp().Logger().Info("证书在有效期内")
|
||||
history.record(checkPhase, "证书在有效期内且已部署,跳过", &RecordInfo{
|
||||
Info: []string{fmt.Sprintf("证书有效期至 %s", expiredAt.Format("2006-01-02"))},
|
||||
}, true)
|
||||
|
||||
// 跳过的情况也算成功
|
||||
history.setWholeSuccess(true)
|
||||
return nil
|
||||
}
|
||||
history.record(checkPhase, "检查通过", nil, true)
|
||||
|
||||
// ############2.申请证书
|
||||
history.record(applyPhase, "开始申请", nil)
|
||||
|
||||
if cert != "" && time.Until(expiredAt) > validityDuration && !changed {
|
||||
history.record(applyPhase, "证书在有效期内,跳过", &RecordInfo{
|
||||
Info: []string{fmt.Sprintf("证书有效期至 %s", expiredAt.Format("2006-01-02"))},
|
||||
})
|
||||
} else {
|
||||
applicant, err := applicant.Get(currRecord)
|
||||
if err != nil {
|
||||
history.record(applyPhase, "获取applicant失败", &RecordInfo{Err: err})
|
||||
app.GetApp().Logger().Error("获取applicant失败", "err", err)
|
||||
return err
|
||||
}
|
||||
certificate, err = applicant.Apply()
|
||||
if err != nil {
|
||||
history.record(applyPhase, "申请证书失败", &RecordInfo{Err: err})
|
||||
app.GetApp().Logger().Error("申请证书失败", "err", err)
|
||||
return err
|
||||
}
|
||||
history.record(applyPhase, "申请证书成功", &RecordInfo{
|
||||
Info: []string{fmt.Sprintf("证书地址: %s", certificate.CertUrl)},
|
||||
})
|
||||
history.setCert(certificate)
|
||||
}
|
||||
|
||||
history.record(applyPhase, "保存证书成功", nil, true)
|
||||
|
||||
// ############3.部署证书
|
||||
history.record(deployPhase, "开始部署", nil, false)
|
||||
deployers, err := deployer.Gets(currRecord, certificate)
|
||||
if err != nil {
|
||||
history.record(deployPhase, "获取deployer失败", &RecordInfo{Err: err})
|
||||
app.GetApp().Logger().Error("获取deployer失败", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 没有部署配置,也算成功
|
||||
if len(deployers) == 0 {
|
||||
history.record(deployPhase, "没有部署配置", &RecordInfo{Info: []string{"没有部署配置"}})
|
||||
history.setWholeSuccess(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, deployer := range deployers {
|
||||
if err = deployer.Deploy(ctx); err != nil {
|
||||
|
||||
app.GetApp().Logger().Error("部署失败", "err", err)
|
||||
history.record(deployPhase, "部署失败", &RecordInfo{Err: err, Info: deployer.GetInfos()})
|
||||
return err
|
||||
}
|
||||
history.record(deployPhase, fmt.Sprintf("[%s]-部署成功", deployer.GetID()), &RecordInfo{
|
||||
Info: deployer.GetInfos(),
|
||||
}, false)
|
||||
|
||||
}
|
||||
|
||||
app.GetApp().Logger().Info("部署成功")
|
||||
history.record(deployPhase, "部署成功", nil, true)
|
||||
|
||||
history.setWholeSuccess(true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isCertChanged(certificate string, record *models.Record) bool {
|
||||
// 如果证书为空,直接返回true
|
||||
if certificate == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// 解析证书
|
||||
cert, err := x509.ParseCertificateFromPEM(certificate)
|
||||
if err != nil {
|
||||
app.GetApp().Logger().Error("解析证书失败", "err", err)
|
||||
return true
|
||||
}
|
||||
|
||||
// 遍历域名列表,检查是否都在证书中,找到第一个不存在证书中域名时提前返回true
|
||||
for _, domain := range strings.Split(record.GetString("domain"), ";") {
|
||||
if !slices.Contains(cert.DNSNames, domain) && !slices.Contains(cert.DNSNames, "*."+removeLastSubdomain(domain)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 解析applyConfig
|
||||
applyConfig := &domain.ApplyConfig{}
|
||||
record.UnmarshalJSONField("applyConfig", applyConfig)
|
||||
|
||||
// 检查证书加密算法是否变更
|
||||
switch pubkey := cert.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
bitSize := pubkey.N.BitLen()
|
||||
switch bitSize {
|
||||
case 2048:
|
||||
// RSA2048
|
||||
if applyConfig.KeyAlgorithm != "" && applyConfig.KeyAlgorithm != "RSA2048" {
|
||||
return true
|
||||
}
|
||||
case 3072:
|
||||
// RSA3072
|
||||
if applyConfig.KeyAlgorithm != "RSA3072" {
|
||||
return true
|
||||
}
|
||||
case 4096:
|
||||
// RSA4096
|
||||
if applyConfig.KeyAlgorithm != "RSA4096" {
|
||||
return true
|
||||
}
|
||||
case 8192:
|
||||
// RSA8192
|
||||
if applyConfig.KeyAlgorithm != "RSA8192" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case *ecdsa.PublicKey:
|
||||
bitSize := pubkey.Curve.Params().BitSize
|
||||
switch bitSize {
|
||||
case 256:
|
||||
// EC256
|
||||
if applyConfig.KeyAlgorithm != "EC256" {
|
||||
return true
|
||||
}
|
||||
case 384:
|
||||
// EC384
|
||||
if applyConfig.KeyAlgorithm != "EC384" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func removeLastSubdomain(domain string) string {
|
||||
parts := strings.Split(domain, ".")
|
||||
if len(parts) > 1 {
|
||||
return strings.Join(parts[1:], ".")
|
||||
}
|
||||
return domain
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
|
||||
"github.com/usual2970/certimate/internal/utils/app"
|
||||
)
|
||||
|
||||
func create(ctx context.Context, record *models.Record) error {
|
||||
if !record.GetBool("enabled") {
|
||||
return nil
|
||||
}
|
||||
|
||||
if record.GetBool("rightnow") {
|
||||
go func() {
|
||||
if err := deploy(ctx, record); err != nil {
|
||||
app.GetApp().Logger().Error("deploy failed", "err", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
scheduler := app.GetScheduler()
|
||||
|
||||
err := scheduler.Add(record.Id, record.GetString("crontab"), func() {
|
||||
deploy(ctx, record)
|
||||
})
|
||||
if err != nil {
|
||||
app.GetApp().Logger().Error("add cron job failed", "err", err)
|
||||
return fmt.Errorf("add cron job failed: %w", err)
|
||||
}
|
||||
app.GetApp().Logger().Error("add cron job failed", "domain", record.GetString("domain"))
|
||||
|
||||
scheduler.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func update(ctx context.Context, record *models.Record) error {
|
||||
scheduler := app.GetScheduler()
|
||||
scheduler.Remove(record.Id)
|
||||
if !record.GetBool("enabled") {
|
||||
return nil
|
||||
}
|
||||
|
||||
if record.GetBool("rightnow") {
|
||||
go func() {
|
||||
if err := deploy(ctx, record); err != nil {
|
||||
app.GetApp().Logger().Error("deploy failed", "err", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
err := scheduler.Add(record.Id, record.GetString("crontab"), func() {
|
||||
deploy(ctx, record)
|
||||
})
|
||||
if err != nil {
|
||||
app.GetApp().Logger().Error("update cron job failed", "err", err)
|
||||
return fmt.Errorf("update cron job failed: %w", err)
|
||||
}
|
||||
app.GetApp().Logger().Info("update cron job success", "domain", record.GetString("domain"))
|
||||
|
||||
scheduler.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func delete(_ context.Context, record *models.Record) error {
|
||||
scheduler := app.GetScheduler()
|
||||
|
||||
scheduler.Remove(record.Id)
|
||||
scheduler.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func setRightnow(ctx context.Context, record *models.Record, ok bool) error {
|
||||
record.Set("rightnow", ok)
|
||||
return app.GetApp().Dao().SaveRecord(record)
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
|
||||
"github.com/usual2970/certimate/internal/utils/app"
|
||||
)
|
||||
|
||||
const tableName = "domains"
|
||||
|
||||
func AddEvent() error {
|
||||
app := app.GetApp()
|
||||
|
||||
app.OnRecordAfterCreateRequest(tableName).Add(func(e *core.RecordCreateEvent) error {
|
||||
return create(e.HttpContext.Request().Context(), e.Record)
|
||||
})
|
||||
|
||||
app.OnRecordAfterUpdateRequest(tableName).Add(func(e *core.RecordUpdateEvent) error {
|
||||
return update(e.HttpContext.Request().Context(), e.Record)
|
||||
})
|
||||
|
||||
app.OnRecordAfterDeleteRequest(tableName).Add(func(e *core.RecordDeleteEvent) error {
|
||||
return delete(e.HttpContext.Request().Context(), e.Record)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
|
||||
"github.com/usual2970/certimate/internal/applicant"
|
||||
"github.com/usual2970/certimate/internal/utils/app"
|
||||
"github.com/usual2970/certimate/internal/utils/xtime"
|
||||
)
|
||||
|
||||
type historyItem struct {
|
||||
Time string `json:"time"`
|
||||
Message string `json:"message"`
|
||||
Error string `json:"error"`
|
||||
Info []string `json:"info"`
|
||||
}
|
||||
|
||||
type RecordInfo struct {
|
||||
Err error `json:"err"`
|
||||
Info []string `json:"info"`
|
||||
}
|
||||
|
||||
type history struct {
|
||||
Domain string `json:"domain"`
|
||||
Log map[Phase][]historyItem `json:"log"`
|
||||
Phase Phase `json:"phase"`
|
||||
PhaseSuccess bool `json:"phaseSuccess"`
|
||||
DeployedAt string `json:"deployedAt"`
|
||||
Cert *applicant.Certificate `json:"cert"`
|
||||
WholeSuccess bool `json:"wholeSuccess"`
|
||||
}
|
||||
|
||||
func NewHistory(record *models.Record) *history {
|
||||
return &history{
|
||||
Domain: record.Id,
|
||||
DeployedAt: time.Now().UTC().Format("2006-01-02T15:04:05Z"),
|
||||
Log: make(map[Phase][]historyItem),
|
||||
Phase: checkPhase,
|
||||
PhaseSuccess: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *history) record(phase Phase, msg string, info *RecordInfo, pass ...bool) {
|
||||
if info == nil {
|
||||
info = &RecordInfo{}
|
||||
}
|
||||
a.Phase = phase
|
||||
if len(pass) > 0 {
|
||||
a.PhaseSuccess = pass[0]
|
||||
}
|
||||
|
||||
errMsg := ""
|
||||
if info.Err != nil {
|
||||
errMsg = info.Err.Error()
|
||||
a.PhaseSuccess = false
|
||||
}
|
||||
|
||||
a.Log[phase] = append(a.Log[phase], historyItem{
|
||||
Message: msg,
|
||||
Error: errMsg,
|
||||
Info: info.Info,
|
||||
Time: xtime.BeijingTimeStr(),
|
||||
})
|
||||
}
|
||||
|
||||
func (a *history) setCert(cert *applicant.Certificate) {
|
||||
a.Cert = cert
|
||||
}
|
||||
|
||||
func (a *history) setWholeSuccess(success bool) {
|
||||
a.WholeSuccess = success
|
||||
}
|
||||
|
||||
func (a *history) commit() error {
|
||||
collection, err := app.GetApp().Dao().FindCollectionByNameOrId("deployments")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := models.NewRecord(collection)
|
||||
|
||||
record.Set("domain", a.Domain)
|
||||
record.Set("deployedAt", a.DeployedAt)
|
||||
record.Set("log", a.Log)
|
||||
record.Set("phase", string(a.Phase))
|
||||
record.Set("phaseSuccess", a.PhaseSuccess)
|
||||
record.Set("wholeSuccess", a.WholeSuccess)
|
||||
|
||||
if err := app.GetApp().Dao().SaveRecord(record); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
domainRecord, err := app.GetApp().Dao().FindRecordById("domains", a.Domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
domainRecord.Set("lastDeployedAt", a.DeployedAt)
|
||||
domainRecord.Set("lastDeployment", record.Id)
|
||||
domainRecord.Set("rightnow", false)
|
||||
if a.Phase == deployPhase && a.PhaseSuccess {
|
||||
domainRecord.Set("deployed", true)
|
||||
}
|
||||
cert := a.Cert
|
||||
if cert != nil {
|
||||
domainRecord.Set("certUrl", cert.CertUrl)
|
||||
domainRecord.Set("certStableUrl", cert.CertStableUrl)
|
||||
domainRecord.Set("privateKey", cert.PrivateKey)
|
||||
domainRecord.Set("certificate", cert.Certificate)
|
||||
domainRecord.Set("issuerCertificate", cert.IssuerCertificate)
|
||||
domainRecord.Set("csr", cert.Csr)
|
||||
domainRecord.Set("expiredAt", time.Now().Add(time.Hour*24*90))
|
||||
}
|
||||
|
||||
if err := app.GetApp().Dao().SaveRecord(domainRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package variables
|
||||
|
||||
import "strings"
|
||||
|
||||
// Parse2Map 将变量赋值字符串解析为map
|
||||
func Parse2Map(str string) map[string]string {
|
||||
m := make(map[string]string)
|
||||
|
||||
lines := strings.Split(str, ";")
|
||||
|
||||
for _, line := range lines {
|
||||
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
kv := strings.Split(line, "=")
|
||||
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
m[kv[0]] = kv[1]
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package variables
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse2Map(t *testing.T) {
|
||||
type args struct {
|
||||
str string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want map[string]string
|
||||
}{
|
||||
{
|
||||
name: "test1",
|
||||
args: args{
|
||||
str: "a=1;b=2;c=3",
|
||||
},
|
||||
want: map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
"c": "3",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test2",
|
||||
args: args{
|
||||
str: `a=1;
|
||||
b=2;
|
||||
c=`,
|
||||
},
|
||||
want: map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
"c": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test3",
|
||||
args: args{
|
||||
str: "1",
|
||||
},
|
||||
want: map[string]string{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Parse2Map(tt.args.str); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Parse2Map() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user