diff --git a/commands/types/dnscontrol.d.ts b/commands/types/dnscontrol.d.ts index 65d694af9..000695e1c 100644 --- a/commands/types/dnscontrol.d.ts +++ b/commands/types/dnscontrol.d.ts @@ -550,13 +550,13 @@ declare function CAA(name: string, tag: "issue" | "issuewild" | "iodef" | "conta declare function CAA_BUILDER(opts: { label?: string; iodef: string; iodef_critical?: boolean; issue: string[]|string; issue_critical?: boolean; issuewild: string[]|string; issuewild_critical?: boolean; issuevmc: string[]|string; issuevmc_critical?: boolean; issuemail: string[]|string; issuemail_critical?: boolean; ttl?: Duration }): DomainModifier; /** - * WARNING: Cloudflare is removing this feature and replacing it with a new + * **WARNING:** Cloudflare is removing this feature and replacing it with a new * feature called "Dynamic Single Redirect". DNSControl will automatically * generate "Dynamic Single Redirects" for a limited number of use cases. See * [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. * - * `CF_REDIRECT` uses Cloudflare-specific features ("Forwarding URL" Page Rules) to - * generate a HTTP 301 permanent redirect. + * `CF_REDIRECT` uses Cloudflare-specific features ("Forwarding URL" Page + * Rules) to generate a HTTP 301 permanent redirect. * * If _any_ `CF_REDIRECT` or [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) functions are used then * `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. @@ -587,36 +587,50 @@ declare function CF_REDIRECT(source: string, destination: string, ...modifiers: /** * `CF_SINGLE_REDIRECT` is a Cloudflare-specific feature for creating HTTP redirects. 301, 302, 303, 307, 308 are supported. - * Typically one uses 302 (temporary) or (less likely) 301 (permanent). + * Typically one uses 302 (temporary) or 301 (permanent). * * This feature manages dynamic "Single Redirects". (Single Redirects can be * static or dynamic but DNSControl only maintains dynamic redirects). * + * DNSControl will delete any "single redirects" it doesn't recognize (i.e. ones created via the web UI) so please be careful. + * * Cloudflare documentation: * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), - * CF_SINGLE_REDIRECT("name", 302, "when", "then"), * CF_SINGLE_REDIRECT('redirect www.example.com', 302, 'http.host eq "www.example.com"', 'concat("https://otherplace.com", http.request.uri.path)'), * CF_SINGLE_REDIRECT('redirect yyy.example.com', 302, 'http.host eq "yyy.example.com"', 'concat("https://survey.stackoverflow.co", "")'), + * CF_TEMP_REDIRECT("*example.com/*", "https://contests.otherexample.com/$2"), * ); * ``` * * The fields are: * - * * name: The name (basically a comment, but it must be unique) + * * name: The name (basically a comment) * * code: Any of 301, 302, 303, 307, 308. May be a number or string. * * when: What Cloudflare sometimes calls the "rule expression". * * then: The replacement expression. * - * NOTE: The features [`CF_REDIRECT`](CF_REDIRECT.md) and [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) generate `CF_SINGLE_REDIRECT` if enabled in [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md). + * DNSControl does not currently choose the order of the rules. New rules are + * added to the end of the list. Use Cloudflare's dashboard to re-order the rule, + * DNSControl should not change them. (In the future we hope to add a feature + * where the order the rules appear in dnsconfig.js is maintained in the + * dashboard.) + * + * ## `CF_REDIRECT` and `CF_TEMP_REDIRECT` + * + * `CF_REDIRECT` and `CF_TEMP_REDIRECT` used to manage Cloudflare Page Rules. + * However that feature is going away. To help with the migration, DNSControl now + * translates those commands into CF_SINGLE_REDIRECT equivalents. The conversion + * process is a transpiler that only understands certain formats. Please submit + * a Github issue if you find something it can't handle. * * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/service-provider-specific/cloudflare-dns/cf_single_redirect */ declare function CF_SINGLE_REDIRECT(name: string, code: number, when: string, then: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * WARNING: Cloudflare is removing this feature and replacing it with a new + * **WARNING:** Cloudflare is removing this feature and replacing it with a new * feature called "Dynamic Single Redirect". DNSControl will automatically * generate "Dynamic Single Redirects" for a limited number of use cases. See * [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. @@ -624,9 +638,9 @@ declare function CF_SINGLE_REDIRECT(name: string, code: number, when: string, th * `CF_TEMP_REDIRECT` uses Cloudflare-specific features ("Forwarding URL" Page * Rules) to generate a HTTP 302 temporary redirect. * - * If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT` functions are used then + * If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT functions are used then * `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. - * Page Rule types other than "Forwarding URL” will be left alone. + * Page Rule types other than "Forwarding URL" will be left alone. * * WARNING: Cloudflare does not currently fully document the Page Rules API and * this interface is not extensively tested. Take precautions such as making @@ -634,9 +648,12 @@ declare function CF_SINGLE_REDIRECT(name: string, code: number, when: string, th * `dnscontrol push`. This is especially true when mixing Page Rules that are * managed by DNSControl and those that aren't. * + * This example redirects the bare (aka apex, or naked) domain to www: + * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), - * CF_TEMP_REDIRECT("example.example.com/*", "https://otherplace.yourdomain.com/$1"), + * CF_TEMP_REDIRECT("example.com/*", "https://www.example.com/$1"), + * * ); * ``` * @@ -3205,6 +3222,21 @@ declare function REV(address: string): string; */ declare function REVCOMPAT(rfc: string): string; +/** + * `RP()` adds an RP record to a domain. + * + * The RP implementation in DNSControl is still experimental and may change. + * + * ```javascript + * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), + * RP("@", "user.example.com.", "example.com."), + * ); + * ``` + * + * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/rp + */ +declare function RP(name: string, mbox: unknown, txt: unknown, ...modifiers: RecordModifier[]): DomainModifier; + /** * `SMIMEA` adds a `SMIMEA` record to a domain. The name should be the hashed and stripped local part of the e-mail. * diff --git a/documentation/provider/index.md b/documentation/provider/index.md index 301d6d7c6..d406d36fd 100644 --- a/documentation/provider/index.md +++ b/documentation/provider/index.md @@ -91,7 +91,7 @@ Jump to a table: | ------------- | -------------------------------------------------------------------- | ---------------------------------------------- | -------------- | --------- | | [`ADGUARDHOME`](adguardhome.md) | ❔ | ❔ | ❌ | ❌ | | [`AKAMAIEDGEDNS`](akamaiedgedns.md) | ❔ | ✅ | ✅ | ✅ | -| [`ALIDNS`](alidns.md) | ✅ | ❌ | ❌ | ✅ | +| [`ALIDNS`](alidns.md) | ✅ | ✅ | ❌ | ✅ | | [`AUTODNS`](autodns.md) | ✅ | ❌ | ❌ | ✅ | | [`AXFRDDNS`](axfrddns.md) | ✅ | ❌ | ❌ | ❌ | | [`AZURE_DNS`](azure_dns.md) | ✅ | ✅ | ✅ | ✅ | diff --git a/pkg/js/parse_tests/011-cfRedirect.json b/pkg/js/parse_tests/011-cfRedirect.json index c27456630..6e3734372 100644 --- a/pkg/js/parse_tests/011-cfRedirect.json +++ b/pkg/js/parse_tests/011-cfRedirect.json @@ -9,11 +9,11 @@ "name": "foo.com", "records": [ { - "comparable": "name=(001,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "comparable": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "fields": { "code": 301, - "sr_display": "name=(001,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", - "sr_name": "001,301,test1.foo.com,https://goo.com/$1", + "sr_display": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "sr_name": "301,test1.foo.com,https://goo.com/$1", "sr_then": "concat(\"https://goo.com\", http.request.uri.path)", "sr_when": "http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\"" }, @@ -21,17 +21,17 @@ "name": "@", "name_raw": "@", "name_unicode": "@", - "target": "name=(001,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "target": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "ttl": 1, "type": "CLOUDFLAREAPI_SINGLE_REDIRECT", - "zonfefilepartial": "name=(001,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" + "zonfefilepartial": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" }, { - "comparable": "name=(002,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "comparable": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "fields": { "code": 302, - "sr_display": "name=(002,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", - "sr_name": "002,302,test2.foo.com,https://goo.com/$1", + "sr_display": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "sr_name": "302,test2.foo.com,https://goo.com/$1", "sr_then": "concat(\"https://goo.com\", http.request.uri.path)", "sr_when": "http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\"" }, @@ -39,10 +39,10 @@ "name": "@", "name_raw": "@", "name_unicode": "@", - "target": "name=(002,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "target": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "ttl": 1, "type": "CLOUDFLAREAPI_SINGLE_REDIRECT", - "zonfefilepartial": "name=(002,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" + "zonfefilepartial": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" } ], "registrar": "none" diff --git a/pkg/js/parse_tests/011-cfRedirect/foo.com.zone b/pkg/js/parse_tests/011-cfRedirect/foo.com.zone index 2d3bd70a9..d3da3e157 100644 --- a/pkg/js/parse_tests/011-cfRedirect/foo.com.zone +++ b/pkg/js/parse_tests/011-cfRedirect/foo.com.zone @@ -1,3 +1,3 @@ $TTL 300 -;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(001,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq "test1.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) -;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(002,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq "test2.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) +;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq "test1.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) +;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq "test2.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) diff --git a/pkg/js/parse_tests/036-dextendcf.json b/pkg/js/parse_tests/036-dextendcf.json index 7d304fff2..923ac17c5 100644 --- a/pkg/js/parse_tests/036-dextendcf.json +++ b/pkg/js/parse_tests/036-dextendcf.json @@ -26,11 +26,11 @@ "type": "CF_WORKER_ROUTE" }, { - "comparable": "name=(003,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "comparable": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "fields": { "code": 301, - "sr_display": "name=(003,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", - "sr_name": "003,301,test1.foo.com,https://goo.com/$1", + "sr_display": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "sr_name": "301,test1.foo.com,https://goo.com/$1", "sr_then": "concat(\"https://goo.com\", http.request.uri.path)", "sr_when": "http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\"" }, @@ -38,17 +38,17 @@ "name": "@", "name_raw": "@", "name_unicode": "@", - "target": "name=(003,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "target": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "ttl": 1, "type": "CLOUDFLAREAPI_SINGLE_REDIRECT", - "zonfefilepartial": "name=(003,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" + "zonfefilepartial": "name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq \"test1.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" }, { - "comparable": "name=(004,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "comparable": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "fields": { "code": 302, - "sr_display": "name=(004,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", - "sr_name": "004,302,test2.foo.com,https://goo.com/$1", + "sr_display": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "sr_name": "302,test2.foo.com,https://goo.com/$1", "sr_then": "concat(\"https://goo.com\", http.request.uri.path)", "sr_when": "http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\"" }, @@ -56,10 +56,10 @@ "name": "@", "name_raw": "@", "name_unicode": "@", - "target": "name=(004,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", + "target": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))", "ttl": 1, "type": "CLOUDFLAREAPI_SINGLE_REDIRECT", - "zonfefilepartial": "name=(004,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" + "zonfefilepartial": "name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq \"test2.foo.com\" and http.request.uri.path eq \"/\") then=(concat(\"https://goo.com\", http.request.uri.path))" }, { "filepos": "[line:6:5]", diff --git a/pkg/js/parse_tests/036-dextendcf/foo.com.zone b/pkg/js/parse_tests/036-dextendcf/foo.com.zone index 0f741ac5d..10acd6053 100644 --- a/pkg/js/parse_tests/036-dextendcf/foo.com.zone +++ b/pkg/js/parse_tests/036-dextendcf/foo.com.zone @@ -1,7 +1,7 @@ $TTL 300 ;@ IN CF_WORKER_ROUTE test3.foo.com,test-worker -;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(003,301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq "test1.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) -;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(004,302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq "test2.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) +;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(301,test1.foo.com,https://goo.com/$1) code=(301) when=(http.host eq "test1.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) +;@ 1 IN CLOUDFLAREAPI_SINGLE_REDIRECT name=(302,test2.foo.com,https://goo.com/$1) code=(302) when=(http.host eq "test2.foo.com" and http.request.uri.path eq "/") then=(concat("https://goo.com", http.request.uri.path)) test1.foo.com.sub IN A 10.2.3.1 test2.foo.com.sub IN A 10.2.3.2 test3.foo.com.sub IN A 10.2.3.3