95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package letsencrypt
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
|
"sslh-multiplex-lab/internal/providers/namecheap"
|
|
)
|
|
|
|
type NamecheapDNSProvider struct {
|
|
namecheapClient *namecheap.Client
|
|
domain string
|
|
txtRecords map[string]string
|
|
}
|
|
|
|
func NewNamecheapDNSProvider(namecheapClient *namecheap.Client, domain string) *NamecheapDNSProvider {
|
|
return &NamecheapDNSProvider{
|
|
namecheapClient: namecheapClient,
|
|
domain: domain,
|
|
txtRecords: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
func (p *NamecheapDNSProvider) Present(domain, token, keyAuth string) error {
|
|
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
|
|
|
subdomain := extractSubdomain(fqdn, p.domain)
|
|
if subdomain == "" {
|
|
return fmt.Errorf("failed to extract subdomain from %s for domain %s", fqdn, p.domain)
|
|
}
|
|
|
|
p.txtRecords[subdomain] = value
|
|
|
|
_, err := p.namecheapClient.CreateOrUpdateDNSRecord(p.domain, subdomain, "TXT", value, 300)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create TXT record for %s: %w", subdomain, err)
|
|
}
|
|
|
|
time.Sleep(10 * time.Second)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *NamecheapDNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
|
|
|
subdomain := extractSubdomain(fqdn, p.domain)
|
|
if subdomain == "" {
|
|
return nil
|
|
}
|
|
|
|
records, err := p.namecheapClient.ListDNSRecords(p.domain)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list DNS records: %w", err)
|
|
}
|
|
|
|
for _, record := range records {
|
|
if record.Name == subdomain && record.Type == "TXT" {
|
|
if err := p.namecheapClient.DeleteDNSRecord(p.domain, record.ID); err != nil {
|
|
return fmt.Errorf("failed to delete TXT record for %s: %w", subdomain, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
delete(p.txtRecords, subdomain)
|
|
return nil
|
|
}
|
|
|
|
func extractSubdomain(fqdn, domain string) string {
|
|
if len(fqdn) <= len(domain) {
|
|
return ""
|
|
}
|
|
|
|
suffix := "." + domain
|
|
if !endsWith(fqdn, suffix) {
|
|
return ""
|
|
}
|
|
|
|
subdomain := fqdn[:len(fqdn)-len(suffix)]
|
|
if subdomain == "_acme-challenge" {
|
|
return "_acme-challenge"
|
|
}
|
|
|
|
if len(subdomain) > len("_acme-challenge.") && subdomain[:len("_acme-challenge.")] == "_acme-challenge." {
|
|
return subdomain
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func endsWith(s, suffix string) bool {
|
|
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
|
|
}
|