68ca2d2716
Refs #37
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
// Package dnsproviders is a registry of DNS providers usable for ACME DNS-01
|
|
// challenges. Each provider is implemented as a separate file that registers
|
|
// itself in init(); to add a new provider, drop a file in this package — no
|
|
// changes are needed elsewhere.
|
|
//
|
|
// All providers wrap the libdns ecosystem (https://github.com/libdns) so they
|
|
// plug directly into certmagic's DNSManager.
|
|
package dnsproviders
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/caddyserver/certmagic"
|
|
)
|
|
|
|
// Builder constructs a certmagic.DNSProvider from a flat env-style map.
|
|
// The map mirrors the cert_config.dns_env block from config.yml.
|
|
type Builder func(env map[string]string) (certmagic.DNSProvider, error)
|
|
|
|
// Provider describes a single DNS provider entry in the registry.
|
|
type Provider struct {
|
|
// Names is the list of accepted dns_provider values; the first is canonical,
|
|
// the rest are aliases (case-insensitive match).
|
|
Names []string
|
|
// EnvVars lists the environment variable names this provider may consume.
|
|
// Used for documentation and error messages only.
|
|
EnvVars []string
|
|
// Build constructs the underlying libdns provider.
|
|
Build Builder
|
|
}
|
|
|
|
var (
|
|
mu sync.RWMutex
|
|
registry = map[string]*Provider{}
|
|
ordered []*Provider
|
|
)
|
|
|
|
// Register adds a provider to the global registry. It panics on duplicate
|
|
// names so that registration errors surface at process start.
|
|
func Register(p *Provider) {
|
|
if p == nil || len(p.Names) == 0 || p.Build == nil {
|
|
panic("dnsproviders: invalid provider registration")
|
|
}
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
for _, n := range p.Names {
|
|
key := strings.ToLower(strings.TrimSpace(n))
|
|
if key == "" {
|
|
panic("dnsproviders: empty provider name")
|
|
}
|
|
if _, exists := registry[key]; exists {
|
|
panic(fmt.Sprintf("dnsproviders: duplicate name %q", key))
|
|
}
|
|
registry[key] = p
|
|
}
|
|
ordered = append(ordered, p)
|
|
}
|
|
|
|
// Get returns the provider registered under the given (case-insensitive) name
|
|
// or alias.
|
|
func Get(name string) (*Provider, bool) {
|
|
mu.RLock()
|
|
defer mu.RUnlock()
|
|
p, ok := registry[strings.ToLower(strings.TrimSpace(name))]
|
|
return p, ok
|
|
}
|
|
|
|
// CanonicalNames returns the canonical (first-listed) name of every registered
|
|
// provider, sorted alphabetically. Useful for error messages.
|
|
func CanonicalNames() []string {
|
|
mu.RLock()
|
|
defer mu.RUnlock()
|
|
names := make([]string, 0, len(ordered))
|
|
for _, p := range ordered {
|
|
names = append(names, p.Names[0])
|
|
}
|
|
sort.Strings(names)
|
|
return names
|
|
}
|
|
|
|
// List returns all registered providers (canonical entries only), sorted by
|
|
// canonical name.
|
|
func List() []*Provider {
|
|
mu.RLock()
|
|
defer mu.RUnlock()
|
|
out := make([]*Provider, len(ordered))
|
|
copy(out, ordered)
|
|
sort.Slice(out, func(i, j int) bool { return out[i].Names[0] < out[j].Names[0] })
|
|
return out
|
|
}
|