mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-12-09 21:55:57 +08:00
AKAMAIEDGEDNS: Add ALIAS and AKAMAITLC support to the Akamai Edge DNS provider (#3836)
This commit is contained in:
parent
9d4cb301f3
commit
97209bc2fc
15 changed files with 169 additions and 15 deletions
32
commands/types/dnscontrol.d.ts
vendored
32
commands/types/dnscontrol.d.ts
vendored
|
|
@ -266,6 +266,38 @@ declare function ADGUARDHOME_A_PASSTHROUGH(source: string, destination: string):
|
||||||
*/
|
*/
|
||||||
declare function AKAMAICDN(name: string, target: string, ...modifiers: RecordModifier[]): DomainModifier;
|
declare function AKAMAICDN(name: string, target: string, ...modifiers: RecordModifier[]): DomainModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `AKAMAITLC` is a proprietary Top-Level CNAME (TLC) record type specific to Akamai Edge DNS.
|
||||||
|
* It allows CNAME-like functionality at the zone apex (`@`) of a domain where regular CNAME records
|
||||||
|
* are not permitted.
|
||||||
|
*
|
||||||
|
* The difference between `AKAMAITLC` and `CNAME` is that `AKAMAITLC` records are resolved by Akamai Edge DNS
|
||||||
|
* servers instead of the client's resolver. This is similar to how `AKAMAICDN` records work, except that `AKAMAITLC`
|
||||||
|
* records can be pointed to any domain, not just Akamai properties. If you are pointing to an Akamai property,
|
||||||
|
* you should use `AKAMAICDN` instead.
|
||||||
|
*
|
||||||
|
* Important restrictions:
|
||||||
|
* - Can only be used at the zone apex (`@`)
|
||||||
|
* - Limited to one `AKAMAITLC` record per zone
|
||||||
|
* - Cannot coexist with an `AKAMAICDN` record at the apex
|
||||||
|
*
|
||||||
|
* The `answer_type` parameter controls which record types are returned when clients resolve the target:
|
||||||
|
* - `DUAL`: Returns both IPv4 (`A`) and IPv6 (`AAAA`) records
|
||||||
|
* - `A`: Returns only IPv4 records
|
||||||
|
* - `AAAA`: Returns only IPv6 records
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
* ```javascript
|
||||||
|
* D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER),
|
||||||
|
* // Redirect example.com to google.com, returning both A and AAAA records
|
||||||
|
* AKAMAITLC("@", "DUAL", "google.com."),
|
||||||
|
* );
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @see https://docs.dnscontrol.org/language-reference/domain-modifiers/service-provider-specific/akamai-edge-dns/akamaitlc
|
||||||
|
*/
|
||||||
|
declare function AKAMAITLC(name: string, answer_type: "DUAL" | "A" | "AAAA", target: string, ...modifiers: RecordModifier[]): DomainModifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ALIAS is a virtual record type that points a record at another record. It is analogous to a CNAME, but is usually resolved at request-time and served as an A record. Unlike CNAMEs, ALIAS records can be used at the zone apex (`@`)
|
* ALIAS is a virtual record type that points a record at another record. It is analogous to a CNAME, but is usually resolved at request-time and served as an A record. Unlike CNAMEs, ALIAS records can be used at the zone apex (`@`)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@
|
||||||
* [ADGUARDHOME_AAAA_PASSTHROUGH](language-reference/domain-modifiers/ADGUARDHOME_AAAA_PASSTHROUGH.md)
|
* [ADGUARDHOME_AAAA_PASSTHROUGH](language-reference/domain-modifiers/ADGUARDHOME_AAAA_PASSTHROUGH.md)
|
||||||
* Akamai Edge Dns
|
* Akamai Edge Dns
|
||||||
* [AKAMAICDN](language-reference/domain-modifiers/AKAMAICDN.md)
|
* [AKAMAICDN](language-reference/domain-modifiers/AKAMAICDN.md)
|
||||||
|
* [AKAMAITLC](language-reference/domain-modifiers/AKAMAITLC.md)
|
||||||
* Amazon Route 53
|
* Amazon Route 53
|
||||||
* [R53_ALIAS](language-reference/domain-modifiers/R53_ALIAS.md)
|
* [R53_ALIAS](language-reference/domain-modifiers/R53_ALIAS.md)
|
||||||
* Azure DNS
|
* Azure DNS
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
name: AKAMAITLC
|
||||||
|
parameters:
|
||||||
|
- name
|
||||||
|
- answer_type
|
||||||
|
- target
|
||||||
|
- modifiers...
|
||||||
|
provider: AKAMAIEDGEDNS
|
||||||
|
parameter_types:
|
||||||
|
name: string
|
||||||
|
answer_type: '"DUAL" | "A" | "AAAA"'
|
||||||
|
target: string
|
||||||
|
"modifiers...": RecordModifier[]
|
||||||
|
---
|
||||||
|
|
||||||
|
`AKAMAITLC` is a proprietary Top-Level CNAME (TLC) record type specific to Akamai Edge DNS.
|
||||||
|
It allows CNAME-like functionality at the zone apex (`@`) of a domain where regular CNAME records
|
||||||
|
are not permitted.
|
||||||
|
|
||||||
|
The difference between `AKAMAITLC` and `CNAME` is that `AKAMAITLC` records are resolved by Akamai Edge DNS
|
||||||
|
servers instead of the client's resolver. This is similar to how `AKAMAICDN` records work, except that `AKAMAITLC`
|
||||||
|
records can be pointed to any domain, not just Akamai properties. If you are pointing to an Akamai property,
|
||||||
|
you should use `AKAMAICDN` instead.
|
||||||
|
|
||||||
|
Important restrictions:
|
||||||
|
- Can only be used at the zone apex (`@`)
|
||||||
|
- Limited to one `AKAMAITLC` record per zone
|
||||||
|
- Cannot coexist with an `AKAMAICDN` record at the apex
|
||||||
|
|
||||||
|
The `answer_type` parameter controls which record types are returned when clients resolve the target:
|
||||||
|
- `DUAL`: Returns both IPv4 (`A`) and IPv6 (`AAAA`) records
|
||||||
|
- `A`: Returns only IPv4 records
|
||||||
|
- `AAAA`: Returns only IPv6 records
|
||||||
|
|
||||||
|
## Example
|
||||||
|
{% code title="dnsconfig.js" %}
|
||||||
|
```javascript
|
||||||
|
D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER),
|
||||||
|
// Redirect example.com to google.com, returning both A and AAAA records
|
||||||
|
AKAMAITLC("@", "DUAL", "google.com."),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
{% endcode %}
|
||||||
|
|
@ -35,9 +35,35 @@ Example:
|
||||||
```
|
```
|
||||||
{% endcode %}
|
{% endcode %}
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
### Records
|
||||||
|
|
||||||
|
#### AKAMAICDN
|
||||||
|
|
||||||
|
The AKAMAICDN target must be an Edge Hostname preconfigured in your Akamai account.
|
||||||
|
|
||||||
|
The AKAMAICDN record must have a TTL of 20 seconds.
|
||||||
|
|
||||||
|
The AKAMAICDN record may only be used at the zone apex (`@`) if an AKAMAITLC record hasn't been used.
|
||||||
|
|
||||||
|
#### AKAMAITLC
|
||||||
|
|
||||||
|
The AKAMAITLC record can only be used at the zone apex (`@`).
|
||||||
|
|
||||||
|
The AKAMAITLC record can only be used once per zone.
|
||||||
|
|
||||||
|
#### ALIAS
|
||||||
|
Akamai Edge DNS does directly support `ALIAS` records. This provider will convert `ALIAS` records used at the
|
||||||
|
zone apex (`@`) to `AKAMAITLC` records, and any other names to `CNAME` records.
|
||||||
|
|
||||||
|
### Secondary zones
|
||||||
|
|
||||||
|
This provider only supports creating primary zones in Akamai. If a secondary zone has been manually created, only `AKAMAICDN` and `AKAMAITLC` records can be managed, as all other records are read-only.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
A new zone created by DNSControl:
|
A new primary zone created by DNSControl:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
dnscontrol create-domains
|
dnscontrol create-domains
|
||||||
|
|
@ -70,11 +96,9 @@ var DSP_AKAMAIEDGEDNS = NewDnsProvider("akamaiedgedns");
|
||||||
D("example.com", REG_NONE, DnsProvider(DSP_AKAMAIEDGEDNS),
|
D("example.com", REG_NONE, DnsProvider(DSP_AKAMAIEDGEDNS),
|
||||||
NAMESERVER_TTL(86400),
|
NAMESERVER_TTL(86400),
|
||||||
AUTODNSSEC_ON,
|
AUTODNSSEC_ON,
|
||||||
AKAMAICDN("@", "www.preconfigured.edgesuite.net", TTL(20)),
|
AKAMAICDN("@", "preconfigured.edgesuite.net", TTL(20)),
|
||||||
|
AKAMAICDN("www", "www.preconfigured.edgesuite.net", TTL(20)),
|
||||||
A("foo", "1.2.3.4"),
|
A("foo", "1.2.3.4"),
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
{% endcode %}
|
{% endcode %}
|
||||||
|
|
||||||
AKAMAICDN is a proprietary record type that is used to configure [Zone Apex Mapping](https://www.akamai.com/blog/security/edge-dns--zone-apex-mapping---dnssec).
|
|
||||||
The AKAMAICDN target must be preconfigured in the Akamai network.
|
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ Jump to a table:
|
||||||
| Provider name | [`ALIAS`](../language-reference/domain-modifiers/ALIAS.md) | [`DNAME`](../language-reference/domain-modifiers/DNAME.md) | [`LOC`](../language-reference/domain-modifiers/LOC.md) | [`PTR`](../language-reference/domain-modifiers/PTR.md) | [`SOA`](../language-reference/domain-modifiers/SOA.md) |
|
| Provider name | [`ALIAS`](../language-reference/domain-modifiers/ALIAS.md) | [`DNAME`](../language-reference/domain-modifiers/DNAME.md) | [`LOC`](../language-reference/domain-modifiers/LOC.md) | [`PTR`](../language-reference/domain-modifiers/PTR.md) | [`SOA`](../language-reference/domain-modifiers/SOA.md) |
|
||||||
| ------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
|
| ------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
|
||||||
| [`ADGUARDHOME`](adguardhome.md) | ✅ | ❔ | ❔ | ❔ | ❔ |
|
| [`ADGUARDHOME`](adguardhome.md) | ✅ | ❔ | ❔ | ❔ | ❔ |
|
||||||
| [`AKAMAIEDGEDNS`](akamaiedgedns.md) | ❌ | ❔ | ✅ | ✅ | ❌ |
|
| [`AKAMAIEDGEDNS`](akamaiedgedns.md) | ✅ | ❔ | ✅ | ✅ | ❌ |
|
||||||
| [`AUTODNS`](autodns.md) | ✅ | ❔ | ❔ | ✅ | ❔ |
|
| [`AUTODNS`](autodns.md) | ✅ | ❔ | ❔ | ✅ | ❔ |
|
||||||
| [`AXFRDDNS`](axfrddns.md) | ❌ | ✅ | ✅ | ✅ | ❌ |
|
| [`AXFRDDNS`](axfrddns.md) | ❌ | ✅ | ✅ | ✅ | ❌ |
|
||||||
| [`AZURE_DNS`](azure_dns.md) | ❌ | ❔ | ❌ | ✅ | ❔ |
|
| [`AZURE_DNS`](azure_dns.md) | ❌ | ❔ | ❌ | ✅ | ❔ |
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ func (dc *DomainConfig) Punycode() error {
|
||||||
|
|
||||||
// Set the target:
|
// Set the target:
|
||||||
switch rec.Type { // #rtype_variations
|
switch rec.Type { // #rtype_variations
|
||||||
case "ALIAS", "MX", "NS", "CNAME", "DNAME", "PTR", "SRV", "URL", "URL301", "FRAME", "R53_ALIAS", "AKAMAICDN", "CLOUDNS_WR", "PORKBUN_URLFWD", "BUNNY_DNS_RDR":
|
case "ALIAS", "MX", "NS", "CNAME", "DNAME", "PTR", "SRV", "URL", "URL301", "FRAME", "R53_ALIAS", "AKAMAICDN", "AKAMAITLC", "CLOUDNS_WR", "PORKBUN_URLFWD", "BUNNY_DNS_RDR":
|
||||||
// These rtypes are hostnames, therefore need to be converted (unlike, for example, an AAAA record)
|
// These rtypes are hostnames, therefore need to be converted (unlike, for example, an AAAA record)
|
||||||
t, err := idna.ToASCII(rec.GetTargetField())
|
t, err := idna.ToASCII(rec.GetTargetField())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ type RecordConfig struct {
|
||||||
TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"`
|
TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"`
|
||||||
R53Alias map[string]string `json:"r53_alias,omitempty"`
|
R53Alias map[string]string `json:"r53_alias,omitempty"`
|
||||||
AzureAlias map[string]string `json:"azure_alias,omitempty"`
|
AzureAlias map[string]string `json:"azure_alias,omitempty"`
|
||||||
|
AnswerType string `json:"answer_type,omitempty"`
|
||||||
UnknownTypeName string `json:"unknown_type_name,omitempty"`
|
UnknownTypeName string `json:"unknown_type_name,omitempty"`
|
||||||
|
|
||||||
// Cloudflare-specific fields:
|
// Cloudflare-specific fields:
|
||||||
|
|
@ -252,6 +253,7 @@ func (rc *RecordConfig) UnmarshalJSON(b []byte) error {
|
||||||
TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"`
|
TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"`
|
||||||
R53Alias map[string]string `json:"r53_alias,omitempty"`
|
R53Alias map[string]string `json:"r53_alias,omitempty"`
|
||||||
AzureAlias map[string]string `json:"azure_alias,omitempty"`
|
AzureAlias map[string]string `json:"azure_alias,omitempty"`
|
||||||
|
AnswerType string `json:"answer_type,omitempty"`
|
||||||
UnknownTypeName string `json:"unknown_type_name,omitempty"`
|
UnknownTypeName string `json:"unknown_type_name,omitempty"`
|
||||||
|
|
||||||
EnsureAbsent bool `json:"ensure_absent,omitempty"` // Override NO_PURGE and delete this record
|
EnsureAbsent bool `json:"ensure_absent,omitempty"` // Override NO_PURGE and delete this record
|
||||||
|
|
@ -647,7 +649,7 @@ func Downcase(recs []*RecordConfig) {
|
||||||
r.Name = strings.ToLower(r.Name)
|
r.Name = strings.ToLower(r.Name)
|
||||||
r.NameFQDN = strings.ToLower(r.NameFQDN)
|
r.NameFQDN = strings.ToLower(r.NameFQDN)
|
||||||
switch r.Type { // #rtype_variations
|
switch r.Type { // #rtype_variations
|
||||||
case "AKAMAICDN", "ALIAS", "AAAA", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "OPENPGPKEY", "SMIMEA", "PTR", "SRV", "TLSA", "AZURE_ALIAS":
|
case "AKAMAICDN", "AKAMAITLC", "ALIAS", "AAAA", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "OPENPGPKEY", "SMIMEA", "PTR", "SRV", "TLSA", "AZURE_ALIAS":
|
||||||
// Target is case insensitive. Downcase it.
|
// Target is case insensitive. Downcase it.
|
||||||
r.target = strings.ToLower(r.target)
|
r.target = strings.ToLower(r.target)
|
||||||
// BUGFIX(tlim): isn't ALIAS in the wrong case statement?
|
// BUGFIX(tlim): isn't ALIAS in the wrong case statement?
|
||||||
|
|
@ -675,7 +677,7 @@ func CanonicalizeTargets(recs []*RecordConfig, origin string) {
|
||||||
case "ALIAS", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "PTR", "SRV":
|
case "ALIAS", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "PTR", "SRV":
|
||||||
// Target is a hostname that might be a shortname. Turn it into a FQDN.
|
// Target is a hostname that might be a shortname. Turn it into a FQDN.
|
||||||
r.target = dnsutil.AddOrigin(r.target, originFQDN)
|
r.target = dnsutil.AddOrigin(r.target, originFQDN)
|
||||||
case "A", "AKAMAICDN", "CAA", "DHCID", "CLOUDFLAREAPI_SINGLE_REDIRECT", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE", "HTTPS", "IMPORT_TRANSFORM", "LOC", "OPENPGPKEY", "SMIMEA", "SSHFP", "SVCB", "TLSA", "TXT", "ADGUARDHOME_A_PASSTHROUGH", "ADGUARDHOME_AAAA_PASSTHROUGH":
|
case "A", "AKAMAICDN", "AKAMAITLC", "CAA", "DHCID", "CLOUDFLAREAPI_SINGLE_REDIRECT", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE", "HTTPS", "IMPORT_TRANSFORM", "LOC", "OPENPGPKEY", "SMIMEA", "SSHFP", "SVCB", "TLSA", "TXT", "ADGUARDHOME_A_PASSTHROUGH", "ADGUARDHOME_AAAA_PASSTHROUGH":
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
case "SOA":
|
case "SOA":
|
||||||
if r.target != "DEFAULT_NOT_SET." {
|
if r.target != "DEFAULT_NOT_SET." {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func (rc *RecordConfig) PopulateFromStringFunc(rtype, contents, origin string, t
|
||||||
return fmt.Errorf("invalid IP in AAAA record: %s", contents)
|
return fmt.Errorf("invalid IP in AAAA record: %s", contents)
|
||||||
}
|
}
|
||||||
return rc.SetTargetIP(ip) // Reformat to canonical form.
|
return rc.SetTargetIP(ip) // Reformat to canonical form.
|
||||||
case "AKAMAICDN", "ALIAS", "ANAME", "CNAME", "NS", "PTR":
|
case "AKAMAICDN", "AKAMAITLC", "ALIAS", "ANAME", "CNAME", "NS", "PTR":
|
||||||
return rc.SetTarget(contents)
|
return rc.SetTarget(contents)
|
||||||
case "CAA":
|
case "CAA":
|
||||||
return rc.SetTargetCAAString(contents)
|
return rc.SetTargetCAAString(contents)
|
||||||
|
|
@ -181,7 +181,7 @@ func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error
|
||||||
return fmt.Errorf("invalid IP in AAAA record: %s", contents)
|
return fmt.Errorf("invalid IP in AAAA record: %s", contents)
|
||||||
}
|
}
|
||||||
return rc.SetTargetIP(ip) // Reformat to canonical form.
|
return rc.SetTargetIP(ip) // Reformat to canonical form.
|
||||||
case "AKAMAICDN", "ALIAS", "ANAME", "CNAME", "NS", "PTR":
|
case "AKAMAICDN", "AKAMAITLC", "ALIAS", "ANAME", "CNAME", "NS", "PTR":
|
||||||
return rc.SetTarget(contents)
|
return rc.SetTarget(contents)
|
||||||
case "CAA":
|
case "CAA":
|
||||||
return rc.SetTargetCAAString(contents)
|
return rc.SetTargetCAAString(contents)
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ func (rc *RecordConfig) GetTargetCombined() string {
|
||||||
case "AZURE_ALIAS":
|
case "AZURE_ALIAS":
|
||||||
// Differentiate between multiple AZURE_ALIASs on the same label.
|
// Differentiate between multiple AZURE_ALIASs on the same label.
|
||||||
return fmt.Sprintf("%s atype=%s", rc.target, rc.AzureAlias["type"])
|
return fmt.Sprintf("%s atype=%s", rc.target, rc.AzureAlias["type"])
|
||||||
|
case "AKAMAITLC":
|
||||||
|
return fmt.Sprintf("%s %s", rc.AnswerType, rc.target)
|
||||||
default:
|
default:
|
||||||
// Just return the target.
|
// Just return the target.
|
||||||
return rc.target
|
return rc.target
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,20 @@ var AAAA = recordBuilder('AAAA');
|
||||||
// AKAMAICDN(name, target, recordModifiers...)
|
// AKAMAICDN(name, target, recordModifiers...)
|
||||||
var AKAMAICDN = recordBuilder('AKAMAICDN');
|
var AKAMAICDN = recordBuilder('AKAMAICDN');
|
||||||
|
|
||||||
|
// AKAMAITLC(name, answer_type, target, recordModifiers...)
|
||||||
|
var AKAMAITLC = recordBuilder('AKAMAITLC', {
|
||||||
|
args: [
|
||||||
|
['name', _.isString],
|
||||||
|
['answer_type', function(value) { return _.isString(value) && ['DUAL', 'A', 'AAAA'].indexOf(value) !== -1; }],
|
||||||
|
['target', _.isString],
|
||||||
|
],
|
||||||
|
transform: function (record, args, modifier) {
|
||||||
|
record.name = args.name;
|
||||||
|
record.answer_type = args.answer_type;
|
||||||
|
record.target = args.target;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// ALIAS(name,target, recordModifiers...)
|
// ALIAS(name,target, recordModifiers...)
|
||||||
var ALIAS = recordBuilder('ALIAS');
|
var ALIAS = recordBuilder('ALIAS');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -743,6 +743,7 @@ var providerCapabilityChecks = []pairTypeCapability{
|
||||||
// If a zone uses rType X, the provider must support capability Y.
|
// If a zone uses rType X, the provider must support capability Y.
|
||||||
// {"X", providers.Y},
|
// {"X", providers.Y},
|
||||||
capabilityCheck("AKAMAICDN", providers.CanUseAKAMAICDN),
|
capabilityCheck("AKAMAICDN", providers.CanUseAKAMAICDN),
|
||||||
|
capabilityCheck("AKAMAITLC", providers.CanUseAKAMAITLC),
|
||||||
capabilityCheck("ALIAS", providers.CanUseAlias),
|
capabilityCheck("ALIAS", providers.CanUseAlias),
|
||||||
capabilityCheck("AUTODNSSEC", providers.CanAutoDNSSEC),
|
capabilityCheck("AUTODNSSEC", providers.CanAutoDNSSEC),
|
||||||
capabilityCheck("AZURE_ALIAS", providers.CanUseAzureAlias),
|
capabilityCheck("AZURE_ALIAS", providers.CanUseAzureAlias),
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ var features = providers.DocumentationNotes{
|
||||||
providers.CanGetZones: providers.Can(),
|
providers.CanGetZones: providers.Can(),
|
||||||
providers.CanOnlyDiff1Features: providers.Can(),
|
providers.CanOnlyDiff1Features: providers.Can(),
|
||||||
providers.CanUseAKAMAICDN: providers.Can(),
|
providers.CanUseAKAMAICDN: providers.Can(),
|
||||||
providers.CanUseAlias: providers.Cannot(),
|
providers.CanUseAKAMAITLC: providers.Can(),
|
||||||
|
providers.CanUseAlias: providers.Can("Akamai Edge DNS does not directly support ALIAS. Apex record will be converted to AKAMAITLC, any others to CNAME."),
|
||||||
providers.CanUseCAA: providers.Can(),
|
providers.CanUseCAA: providers.Can(),
|
||||||
providers.CanUseDS: providers.Cannot(),
|
providers.CanUseDS: providers.Cannot(),
|
||||||
providers.CanUseDSForChildren: providers.Can(),
|
providers.CanUseDSForChildren: providers.Can(),
|
||||||
|
|
@ -58,6 +59,7 @@ func init() {
|
||||||
}
|
}
|
||||||
providers.RegisterDomainServiceProviderType(providerName, fns, features)
|
providers.RegisterDomainServiceProviderType(providerName, fns, features)
|
||||||
providers.RegisterCustomRecordType("AKAMAICDN", providerName, "")
|
providers.RegisterCustomRecordType("AKAMAICDN", providerName, "")
|
||||||
|
providers.RegisterCustomRecordType("AKAMAITLC", providerName, "")
|
||||||
providers.RegisterMaintainer(providerName, providerMaintainer)
|
providers.RegisterMaintainer(providerName, providerMaintainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,6 +111,11 @@ func (a *edgeDNSProvider) EnsureZoneExists(domain string, metadata map[string]st
|
||||||
|
|
||||||
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
|
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
|
||||||
func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
|
func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
|
||||||
|
|
||||||
|
if err := a.preprocessConfig(dc); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
keysToUpdate, toReport, actualChangeCount, err := diff.NewCompat(dc).ChangedGroups(existingRecords)
|
keysToUpdate, toReport, actualChangeCount, err := diff.NewCompat(dc).ChangedGroups(existingRecords)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
|
@ -235,3 +242,19 @@ func (a *edgeDNSProvider) ListZones() ([]string, error) {
|
||||||
}
|
}
|
||||||
return zones, nil
|
return zones, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *edgeDNSProvider) preprocessConfig(dc *models.DomainConfig) error {
|
||||||
|
for _, rec := range dc.Records {
|
||||||
|
// Convert ALIAS records to the Akamai equivalents. AKAMAITLC is only valid
|
||||||
|
// at the apex, so any other ALIAS must be converted to CNAME.
|
||||||
|
if rec.Type == "ALIAS" {
|
||||||
|
if rec.Name == "@" {
|
||||||
|
rec.ChangeType("AKAMAITLC", dc.Name)
|
||||||
|
rec.AnswerType = "DUAL"
|
||||||
|
} else {
|
||||||
|
rec.ChangeType("CNAME", dc.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ https://github.com/akamai/AkamaiOPEN-edgegrid-golang
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/StackExchange/dnscontrol/v4/models"
|
"github.com/StackExchange/dnscontrol/v4/models"
|
||||||
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
|
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
|
||||||
dnsv2 "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v2"
|
dnsv2 "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v2"
|
||||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
|
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// initialize initializes the "Akamai OPEN EdgeGrid" library
|
// initialize initializes the "Akamai OPEN EdgeGrid" library
|
||||||
|
|
@ -293,6 +293,14 @@ func getRecords(zonename string) ([]*models.RecordConfig, error) {
|
||||||
TTL: uint32(akattl),
|
TTL: uint32(akattl),
|
||||||
}
|
}
|
||||||
rc.SetLabelFromFQDN(akaname, zonename)
|
rc.SetLabelFromFQDN(akaname, zonename)
|
||||||
|
if akatype == "AKAMAITLC" {
|
||||||
|
part := strings.Fields(r)
|
||||||
|
if len(part) != 2 {
|
||||||
|
return nil, fmt.Errorf("AKAMAITLC value does not contain 2 fields: (%#v)", r)
|
||||||
|
}
|
||||||
|
rc.AnswerType = part[0]
|
||||||
|
r = part[1]
|
||||||
|
}
|
||||||
err = rc.PopulateFromString(akatype, r, zonename)
|
err = rc.PopulateFromString(akatype, r, zonename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,9 @@ const (
|
||||||
|
|
||||||
// DocOfficiallySupported means it is actively used and maintained by stack exchange
|
// DocOfficiallySupported means it is actively used and maintained by stack exchange
|
||||||
DocOfficiallySupported
|
DocOfficiallySupported
|
||||||
|
|
||||||
|
// CanUseAKAMAITLC indicates the provider supports the specific AKAMAITLC records that only the Akamai EdgeDns provider supports
|
||||||
|
CanUseAKAMAITLC
|
||||||
)
|
)
|
||||||
|
|
||||||
var providerCapabilities = map[string]map[Capability]bool{}
|
var providerCapabilities = map[string]map[Capability]bool{}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,12 @@ func _() {
|
||||||
_ = x[DocCreateDomains-25]
|
_ = x[DocCreateDomains-25]
|
||||||
_ = x[DocDualHost-26]
|
_ = x[DocDualHost-26]
|
||||||
_ = x[DocOfficiallySupported-27]
|
_ = x[DocOfficiallySupported-27]
|
||||||
|
_ = x[CanUseAKAMAITLC-28]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSMIMEACanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupported"
|
const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSMIMEACanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupportedCanUseAKAMAITLC"
|
||||||
|
|
||||||
var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 223, 232, 241, 252, 262, 272, 284, 300, 316, 327, 349}
|
var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 223, 232, 241, 252, 262, 272, 284, 300, 316, 327, 349, 364}
|
||||||
|
|
||||||
func (i Capability) String() string {
|
func (i Capability) String() string {
|
||||||
idx := int(i) - 0
|
idx := int(i) - 0
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue