1
0
mirror of https://github.com/go-acme/lego.git synced 2025-11-27 16:28:17 +02:00

edgeone: add zones mapping (#2728)

This commit is contained in:
Ludovic Fernandez
2025-11-25 19:29:47 +01:00
committed by GitHub
parent aea6afe2d6
commit 56cb356ef2
7 changed files with 61 additions and 20 deletions

View File

@@ -1342,6 +1342,7 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(` - "EDGEONE_REGION": Region`)
ew.writeln(` - "EDGEONE_SESSION_TOKEN": Access Key token`)
ew.writeln(` - "EDGEONE_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)`)
ew.writeln(` - "EDGEONE_ZONES_MAPPING": Mapping between DNS zones and site IDs. (ex: 'example.org:id1,example.com:id2')`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/edgeone`)

View File

@@ -55,6 +55,7 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
| `EDGEONE_REGION` | Region |
| `EDGEONE_SESSION_TOKEN` | Access Key token |
| `EDGEONE_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 60) |
| `EDGEONE_ZONES_MAPPING` | Mapping between DNS zones and site IDs. (ex: 'example.org:id1,example.com:id2') |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).

View File

@@ -165,7 +165,7 @@ func (d *DNSProvider) getHostedZone(domain string) (string, string, error) {
}
if hostedZone.ID == "" || hostedZone.ID == "0" {
return "", "", fmt.Errorf("zone %s not found in dnspod for domain %s", authZone, domain)
return "", "", fmt.Errorf("zone %s not found for domain %s", authZone, domain)
}
return hostedZone.ID.String(), hostedZone.Name, nil

View File

@@ -26,6 +26,7 @@ const (
EnvSecretKey = envNamespace + "SECRET_KEY"
EnvRegion = envNamespace + "REGION"
EnvSessionToken = envNamespace + "SESSION_TOKEN"
EnvZonesMapping = envNamespace + "ZONES_MAPPING"
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
@@ -40,6 +41,8 @@ type Config struct {
Region string
SessionToken string
ZonesMapping map[string]string
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
@@ -78,6 +81,14 @@ func NewDNSProvider() (*DNSProvider, error) {
config.Region = env.GetOrDefaultString(EnvRegion, "")
config.SessionToken = env.GetOrDefaultString(EnvSessionToken, "")
mapping := env.GetOrDefaultString(EnvZonesMapping, "")
if mapping != "" {
config.ZonesMapping, err = env.ParsePairs(mapping)
if err != nil {
return nil, fmt.Errorf("edgeone: zones mapping: %w", err)
}
}
return NewDNSProviderConfig(config)
}
@@ -121,7 +132,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
ctx := context.Background()
zone, err := d.getHostedZone(ctx, info.EffectiveFQDN)
zoneID, err := d.getHostedZoneID(ctx, info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("edgeone: failed to get hosted zone: %w", err)
}
@@ -133,7 +144,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
request := teo.NewCreateDnsRecordRequest()
request.Name = ptr.Pointer(punnyCoded)
request.ZoneId = zone.ZoneId
request.ZoneId = zoneID
request.Type = ptr.Pointer("TXT")
request.Content = ptr.Pointer(info.Value)
request.TTL = ptr.Pointer(int64(d.config.TTL))
@@ -156,7 +167,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
ctx := context.Background()
zone, err := d.getHostedZone(ctx, info.EffectiveFQDN)
zoneID, err := d.getHostedZoneID(ctx, info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("edgeone: failed to get hosted zone: %w", err)
}
@@ -171,7 +182,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
}
request := teo.NewDeleteDnsRecordsRequest()
request.ZoneId = zone.ZoneId
request.ZoneId = zoneID
request.RecordIds = []*string{recordID}
_, err = teo.DeleteDnsRecordsWithContext(ctx, d.client, request)

View File

@@ -17,6 +17,7 @@ lego --email you@example.com --dns edgeone -d '*.example.com' -d example.com run
[Configuration.Additional]
EDGEONE_SESSION_TOKEN = "Access Key token"
EDGEONE_REGION = "Region"
EDGEONE_ZONES_MAPPING = "Mapping between DNS zones and site IDs. (ex: 'example.org:id1,example.com:id2')"
EDGEONE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 30)"
EDGEONE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 1200)"
EDGEONE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)"

View File

@@ -9,8 +9,11 @@ import (
const envDomain = envNamespace + "DOMAIN"
var envTest = tester.NewEnvTest(EnvSecretID, EnvSecretKey).
WithDomain(envDomain)
var envTest = tester.NewEnvTest(
EnvSecretID,
EnvSecretKey,
EnvZonesMapping,
).WithDomain(envDomain)
func TestNewDNSProvider(t *testing.T) {
testCases := []struct {
@@ -25,6 +28,14 @@ func TestNewDNSProvider(t *testing.T) {
EnvSecretKey: "456",
},
},
{
desc: "success with zones mapping",
envVars: map[string]string{
EnvSecretID: "123",
EnvSecretKey: "456",
EnvZonesMapping: "example.org:id1,example.com:id2",
},
},
{
desc: "missing credentials",
envVars: map[string]string{
@@ -49,6 +60,15 @@ func TestNewDNSProvider(t *testing.T) {
},
expected: "edgeone: some credentials information are missing: EDGEONE_SECRET_KEY",
},
{
desc: "invalid mapping",
envVars: map[string]string{
EnvSecretID: "123",
EnvSecretKey: "456",
EnvZonesMapping: "example.org:id1,example.com",
},
expected: "edgeone: zones mapping: incorrect pair: example.com",
},
}
for _, test := range testCases {

View File

@@ -9,10 +9,22 @@ import (
teo "github.com/go-acme/tencentedgdeone/v20220901"
)
func (d *DNSProvider) getHostedZone(ctx context.Context, domain string) (*teo.Zone, error) {
func (d *DNSProvider) getHostedZoneID(ctx context.Context, domain string) (*string, error) {
authZone, err := dns01.FindZoneByFqdn(domain)
if err != nil {
return nil, fmt.Errorf("could not find zone: %w", err)
}
if d.config.ZonesMapping != nil {
zoneID, ok := d.config.ZonesMapping[authZone]
if ok {
return ptr.Pointer(zoneID), nil
}
}
request := teo.NewDescribeZonesRequest()
var domains []*teo.Zone
var zones []*teo.Zone
for {
response, err := teo.DescribeZonesWithContext(ctx, d.client, request)
@@ -20,23 +32,18 @@ func (d *DNSProvider) getHostedZone(ctx context.Context, domain string) (*teo.Zo
return nil, fmt.Errorf("API call failed: %w", err)
}
domains = append(domains, response.Response.Zones...)
zones = append(zones, response.Response.Zones...)
if int64(len(domains)) >= ptr.Deref(response.Response.TotalCount) {
if int64(len(zones)) >= ptr.Deref(response.Response.TotalCount) {
break
}
request.Offset = ptr.Pointer(int64(len(domains)))
}
authZone, err := dns01.FindZoneByFqdn(domain)
if err != nil {
return nil, fmt.Errorf("could not find zone: %w", err)
request.Offset = ptr.Pointer(int64(len(zones)))
}
var hostedZone *teo.Zone
for _, zone := range domains {
for _, zone := range zones {
unfqdn := dns01.UnFqdn(authZone)
if ptr.Deref(zone.ZoneName) == unfqdn {
hostedZone = zone
@@ -44,8 +51,8 @@ func (d *DNSProvider) getHostedZone(ctx context.Context, domain string) (*teo.Zo
}
if hostedZone == nil {
return nil, fmt.Errorf("zone %s not found in dnspod for domain %s", authZone, domain)
return nil, fmt.Errorf("zone %s not found for domain %s", authZone, domain)
}
return hostedZone, nil
return hostedZone.ZoneId, nil
}