Files
EdgeAPI/internal/acme/dns_provider.go
GoEdgeLab 5a17ae9d79 v1.4.1
2024-07-27 14:15:25 +08:00

90 lines
2.1 KiB
Go

package acme
import (
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/iwind/TeaGo/lists"
)
type DNSProvider struct {
raw dnsclients.ProviderInterface
dnsDomain string
locker sync.Mutex
deletedRecordNames []string
}
func NewDNSProvider(raw dnsclients.ProviderInterface, dnsDomain string) *DNSProvider {
return &DNSProvider{
raw: raw,
dnsDomain: dnsDomain,
}
}
func (this *DNSProvider) Present(domain, token, keyAuth string) error {
_ = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "true")
var info = dns01.GetChallengeInfo(domain, keyAuth)
var fqdn = info.EffectiveFQDN
var value = info.Value
// 设置记录
var index = strings.Index(fqdn, "."+this.dnsDomain)
if index < 0 {
return errors.New("invalid fqdn value")
}
var recordName = fqdn[:index]
// 先删除老的
this.locker.Lock()
var wasDeleted = lists.ContainsString(this.deletedRecordNames, recordName)
this.locker.Unlock()
if !wasDeleted {
records, err := this.raw.QueryRecords(this.dnsDomain, recordName, dnstypes.RecordTypeTXT)
if err != nil {
return fmt.Errorf("query DNS record failed: %w", err)
}
for _, record := range records {
err = this.raw.DeleteRecord(this.dnsDomain, record)
if err != nil {
return err
}
}
this.locker.Lock()
this.deletedRecordNames = append(this.deletedRecordNames, recordName)
this.locker.Unlock()
}
// 添加新的
err := this.raw.AddRecord(this.dnsDomain, &dnstypes.Record{
Id: "",
Name: recordName,
Type: dnstypes.RecordTypeTXT,
Value: value,
Route: this.raw.DefaultRoute(),
TTL: this.raw.MinTTL(),
})
if err != nil {
return fmt.Errorf("create DNS record failed: %w", err)
}
return nil
}
func (this *DNSProvider) Timeout() (timeout, interval time.Duration) {
return 2 * time.Minute, 2 * time.Second
}
func (this *DNSProvider) CleanUp(domain, token, keyAuth string) error {
return nil
}