2016-08-23 08:31:50 +08:00
package normalize
import (
2018-04-27 02:45:10 +08:00
"fmt"
2016-08-23 08:31:50 +08:00
"net"
"strings"
2020-04-15 04:47:30 +08:00
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/transform"
"github.com/StackExchange/dnscontrol/v3/providers"
2016-09-28 02:28:09 +08:00
"github.com/miekg/dns"
"github.com/miekg/dns/dnsutil"
2016-08-23 08:31:50 +08:00
)
// Returns false if target does not validate.
2017-03-21 04:20:02 +08:00
func checkIPv4 ( label string ) error {
2016-08-23 08:31:50 +08:00
if net . ParseIP ( label ) . To4 ( ) == nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "WARNING: target (%v) is not an IPv4 address" , label )
2016-08-23 08:31:50 +08:00
}
return nil
}
// Returns false if target does not validate.
2017-03-21 04:20:02 +08:00
func checkIPv6 ( label string ) error {
2016-08-23 08:31:50 +08:00
if net . ParseIP ( label ) . To16 ( ) == nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "WARNING: target (%v) is not an IPv6 address" , label )
2016-08-23 08:31:50 +08:00
}
return nil
}
2017-03-21 04:20:02 +08:00
// make sure target is valid reference for cnames, mx, etc.
func checkTarget ( target string ) error {
2016-12-17 04:10:27 +08:00
if target == "@" {
2016-08-23 08:31:50 +08:00
return nil
}
2016-12-17 04:10:27 +08:00
if len ( target ) < 1 {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "empty target" )
2016-08-23 08:31:50 +08:00
}
2017-06-11 21:31:26 +08:00
if strings . ContainsAny ( target , ` '" +,|!£$%&/()=?^*ç°§;:<>[]()@ ` ) {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "target (%v) includes invalid char" , target )
2017-06-11 21:30:12 +08:00
}
2016-08-23 08:31:50 +08:00
// If it containts a ".", it must end in a ".".
2016-12-17 04:10:27 +08:00
if strings . ContainsRune ( target , '.' ) && target [ len ( target ) - 1 ] != '.' {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "target (%v) must end with a (.) [https://stackexchange.github.io/dnscontrol/why-the-dot]" , target )
2016-08-23 08:31:50 +08:00
}
return nil
}
// validateRecordTypes list of valid rec.Type values. Returns true if this is a real DNS record type, false means it is a pseudo-type used internally.
2017-05-20 02:15:57 +08:00
func validateRecordTypes ( rec * models . RecordConfig , domain string , pTypes [ ] string ) error {
2017-03-21 04:20:02 +08:00
var validTypes = map [ string ] bool {
2016-08-23 08:31:50 +08:00
"A" : true ,
"AAAA" : true ,
"CNAME" : true ,
2017-07-26 02:59:40 +08:00
"CAA" : true ,
2020-05-30 22:40:21 +08:00
"DS" : true ,
2017-09-15 21:03:29 +08:00
"TLSA" : true ,
2016-08-23 08:31:50 +08:00
"IMPORT_TRANSFORM" : false ,
"MX" : true ,
2017-07-20 03:53:40 +08:00
"SRV" : true ,
2019-01-29 06:26:20 +08:00
"SSHFP" : true ,
2016-08-23 08:31:50 +08:00
"TXT" : true ,
"NS" : true ,
2017-07-06 22:18:15 +08:00
"PTR" : true ,
2019-03-28 22:40:13 +08:00
"NAPTR" : true ,
2017-04-20 03:13:28 +08:00
"ALIAS" : false ,
2016-08-23 08:31:50 +08:00
}
2017-05-20 02:15:57 +08:00
_ , ok := validTypes [ rec . Type ]
if ! ok {
cType := providers . GetCustomRecordType ( rec . Type )
if cType == nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "Unsupported record type (%v) domain=%v name=%v" , rec . Type , domain , rec . GetLabel ( ) )
2017-05-20 02:15:57 +08:00
}
for _ , providerType := range pTypes {
if providerType != cType . Provider {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "Custom record type %s is not compatible with provider type %s" , rec . Type , providerType )
2017-05-20 02:15:57 +08:00
}
}
2018-01-10 01:53:16 +08:00
// it is ok. Lets replace the type with real type and add metadata to say we checked it
2017-05-20 02:15:57 +08:00
rec . Metadata [ "orig_custom_type" ] = rec . Type
if cType . RealType != "" {
rec . Type = cType . RealType
}
2016-08-23 08:31:50 +08:00
}
return nil
}
2017-03-21 04:20:02 +08:00
// underscores in names are often used erroneously. They are valid for dns records, but invalid for urls.
// here we list common records expected to have underscores. Anything else containing an underscore will print a warning.
2019-03-05 01:11:25 +08:00
var labelUnderscores = [ ] string {
"_acme-challenge" ,
"_amazonses" ,
"_dmarc" ,
2020-05-30 09:41:40 +08:00
"_domainconnect" ,
2019-03-05 01:11:25 +08:00
"_domainkey" ,
"_jabber" ,
2020-02-08 03:20:24 +08:00
"_mta-sts" ,
2019-03-05 01:11:25 +08:00
"_sip" ,
"_xmpp" ,
}
2017-09-15 21:03:29 +08:00
2018-01-10 01:53:16 +08:00
// these record types may contain underscores
2017-09-15 21:03:29 +08:00
var rTypeUnderscores = [ ] string { "SRV" , "TLSA" , "TXT" }
2017-03-21 04:20:02 +08:00
2020-02-28 12:10:35 +08:00
func checkLabel ( label string , rType string , target , domain string , meta map [ string ] string ) error {
2017-03-21 04:20:02 +08:00
if label == "@" {
return nil
}
if len ( label ) < 1 {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "empty %s label in %s" , rType , domain )
2017-03-21 04:20:02 +08:00
}
if label [ len ( label ) - 1 ] == '.' {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "label %s.%s ends with a (.)" , label , domain )
2017-03-21 04:20:02 +08:00
}
2017-11-15 12:13:50 +08:00
if strings . HasSuffix ( label , domain ) {
if m := meta [ "skip_fqdn_check" ] ; m != "true" {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( ` label %s ends with domain name %s. Record names should not be fully qualified. Add { skip_fqdn_check:"true"} to this record if you really want to make %s.%s ` , label , domain , label , domain )
2017-11-15 12:13:50 +08:00
}
}
2019-03-05 01:11:25 +08:00
// Underscores are permitted in labels, but we print a warning unless they
// are used in a way we consider typical. Yes, we're opinionated here.
// Don't warn for certain rtypes:
2017-09-15 21:03:29 +08:00
for _ , ex := range rTypeUnderscores {
if rType == ex {
return nil
2017-03-21 04:20:02 +08:00
}
2017-09-15 21:03:29 +08:00
}
2020-02-28 12:10:35 +08:00
// Don't warn for CNAMEs if the target ends with acm-validations.aws
// See https://github.com/StackExchange/dnscontrol/issues/519
if strings . HasPrefix ( label , "_" ) && rType == "CNAME" && strings . HasSuffix ( target , ".acm-validations.aws." ) {
return nil
}
2019-03-05 01:11:25 +08:00
// Don't warn for certain label substrings
2017-09-15 21:03:29 +08:00
for _ , ex := range labelUnderscores {
if strings . Contains ( label , ex ) {
return nil
2017-03-21 04:20:02 +08:00
}
}
2019-03-05 01:11:25 +08:00
// Otherwise, warn.
2017-09-15 21:03:29 +08:00
if strings . ContainsRune ( label , '_' ) {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return Warning { fmt . Errorf ( "label %s.%s contains an underscore" , label , domain ) }
2017-09-15 21:03:29 +08:00
}
2017-11-15 12:13:50 +08:00
2017-03-21 04:20:02 +08:00
return nil
}
// checkTargets returns true if rec.Target is valid for the rec.Type.
func checkTargets ( rec * models . RecordConfig , domain string ) ( errs [ ] error ) {
2018-03-20 05:18:58 +08:00
label := rec . GetLabel ( )
target := rec . GetTargetField ( )
2016-08-23 08:31:50 +08:00
check := func ( e error ) {
if e != nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
err := fmt . Errorf ( "In %s %s.%s: %s" , rec . Type , rec . GetLabel ( ) , domain , e . Error ( ) )
2017-03-21 04:20:02 +08:00
if _ , ok := e . ( Warning ) ; ok {
err = Warning { err }
}
errs = append ( errs , err )
2016-08-23 08:31:50 +08:00
}
}
2017-08-05 03:26:29 +08:00
switch rec . Type { // #rtype_variations
2016-08-23 08:31:50 +08:00
case "A" :
2017-03-21 04:20:02 +08:00
check ( checkIPv4 ( target ) )
2016-08-23 08:31:50 +08:00
case "AAAA" :
2017-03-21 04:20:02 +08:00
check ( checkIPv6 ( target ) )
2016-08-23 08:31:50 +08:00
case "CNAME" :
2017-03-21 04:20:02 +08:00
check ( checkTarget ( target ) )
2017-04-20 03:13:28 +08:00
if label == "@" {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
check ( fmt . Errorf ( "cannot create CNAME record for bare domain" ) )
2017-04-20 03:13:28 +08:00
}
2016-08-23 08:31:50 +08:00
case "MX" :
2017-03-21 04:20:02 +08:00
check ( checkTarget ( target ) )
2016-08-23 08:31:50 +08:00
case "NS" :
2017-03-21 04:20:02 +08:00
check ( checkTarget ( target ) )
2016-12-17 04:10:27 +08:00
if label == "@" {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
check ( fmt . Errorf ( "cannot create NS record for bare domain. Use NAMESERVER instead" ) )
2016-12-17 04:10:27 +08:00
}
2017-07-06 22:18:15 +08:00
case "PTR" :
check ( checkTarget ( target ) )
2019-04-01 15:15:43 +08:00
case "NAPTR" :
check ( checkTarget ( target ) )
2017-04-20 03:13:28 +08:00
case "ALIAS" :
check ( checkTarget ( target ) )
2020-02-24 02:58:49 +08:00
case "SOA" :
check ( checkTarget ( target ) )
2017-07-20 03:53:40 +08:00
case "SRV" :
check ( checkTarget ( target ) )
2020-05-26 19:46:10 +08:00
case "TXT" , "IMPORT_TRANSFORM" , "CAA" , "SSHFP" , "TLSA" , "DS" :
2016-08-23 08:31:50 +08:00
default :
2017-05-20 02:15:57 +08:00
if rec . Metadata [ "orig_custom_type" ] != "" {
2018-01-10 01:53:16 +08:00
// it is a valid custom type. We perform no validation on target
2017-05-20 02:15:57 +08:00
return
}
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "checkTargets: Unimplemented record type (%v) domain=%v name=%v" ,
2018-03-20 05:18:58 +08:00
rec . Type , domain , rec . GetLabel ( ) ) )
2016-08-23 08:31:50 +08:00
}
return
}
2017-03-21 04:20:02 +08:00
func transformCNAME ( target , oldDomain , newDomain string ) string {
// Canonicalize. If it isn't a FQDN, add the newDomain.
result := dnsutil . AddOrigin ( target , oldDomain )
2016-08-23 08:31:50 +08:00
if dns . IsFqdn ( result ) {
result = result [ : len ( result ) - 1 ]
}
2017-03-21 04:20:02 +08:00
return dnsutil . AddOrigin ( result , newDomain ) + "."
2016-08-23 08:31:50 +08:00
}
// import_transform imports the records of one zone into another, modifying records along the way.
2017-03-21 04:20:02 +08:00
func importTransform ( srcDomain , dstDomain * models . DomainConfig , transforms [ ] transform . IpConversion , ttl uint32 ) error {
// Read srcDomain.Records, transform, and append to dstDomain.Records:
2016-08-23 08:31:50 +08:00
// 1. Skip any that aren't A or CNAMEs.
2017-03-21 04:20:02 +08:00
// 2. Append destDomainname to the end of the label.
// 3. For CNAMEs, append destDomainname to the end of the target.
2016-08-23 08:31:50 +08:00
// 4. For As, change the target as described the transforms.
2017-03-21 04:20:02 +08:00
for _ , rec := range srcDomain . Records {
2020-02-18 21:59:18 +08:00
if dstDomain . Records . HasRecordTypeName ( rec . Type , rec . GetLabelFQDN ( ) ) {
2017-02-08 03:42:11 +08:00
continue
}
2016-09-28 02:28:09 +08:00
newRec := func ( ) * models . RecordConfig {
rec2 , _ := rec . Copy ( )
2018-03-20 05:18:58 +08:00
newlabel := rec2 . GetLabelFQDN ( )
2018-04-27 02:45:10 +08:00
rec2 . SetLabel ( newlabel , dstDomain . Name )
2016-09-29 02:45:59 +08:00
if ttl != 0 {
rec2 . TTL = ttl
}
2016-09-28 02:28:09 +08:00
return rec2
}
2017-08-05 03:26:29 +08:00
switch rec . Type { // #rtype_variations
2016-08-23 08:31:50 +08:00
case "A" :
2018-03-20 05:18:58 +08:00
trs , err := transform . TransformIPToList ( net . ParseIP ( rec . GetTargetField ( ) ) , transforms )
2016-08-23 08:31:50 +08:00
if err != nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "import_transform: TransformIP(%v, %v) returned err=%s" , rec . GetTargetField ( ) , transforms , err )
2016-09-28 02:28:09 +08:00
}
for _ , tr := range trs {
r := newRec ( )
2018-03-20 05:18:58 +08:00
r . SetTarget ( tr . String ( ) )
2017-03-21 04:20:02 +08:00
dstDomain . Records = append ( dstDomain . Records , r )
2016-08-23 08:31:50 +08:00
}
case "CNAME" :
2016-09-28 02:28:09 +08:00
r := newRec ( )
2018-03-20 05:18:58 +08:00
r . SetTarget ( transformCNAME ( r . GetTargetField ( ) , srcDomain . Name , dstDomain . Name ) )
2017-03-21 04:20:02 +08:00
dstDomain . Records = append ( dstDomain . Records , r )
2020-02-24 02:58:49 +08:00
case "MX" , "NAPTR" , "NS" , "SOA" , "SRV" , "TXT" , "CAA" , "TLSA" :
2016-08-23 08:31:50 +08:00
// Not imported.
continue
default :
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "import_transform: Unimplemented record type %v (%v)" ,
2018-03-20 05:18:58 +08:00
rec . Type , rec . GetLabel ( ) )
2016-08-23 08:31:50 +08:00
}
}
return nil
}
// deleteImportTransformRecords deletes any IMPORT_TRANSFORM records from a domain.
func deleteImportTransformRecords ( domain * models . DomainConfig ) {
for i := len ( domain . Records ) - 1 ; i >= 0 ; i -- {
rec := domain . Records [ i ]
if rec . Type == "IMPORT_TRANSFORM" {
domain . Records = append ( domain . Records [ : i ] , domain . Records [ i + 1 : ] ... )
}
}
}
2017-03-21 04:20:02 +08:00
// Warning is a wrapper around error that can be used to indicate it should not
// stop execution, but is still likely a problem.
type Warning struct {
error
}
2020-03-11 04:53:17 +08:00
// ValidateAndNormalizeConfig performs and normalization and/or validation of the IR.
func ValidateAndNormalizeConfig ( config * models . DNSConfig ) ( errs [ ] error ) {
2017-03-21 04:20:02 +08:00
for _ , domain := range config . Domains {
2017-05-20 02:15:57 +08:00
pTypes := [ ] string { }
2018-01-05 08:19:35 +08:00
txtMultiDissenters := [ ] string { }
2018-02-02 00:45:53 +08:00
for _ , provider := range domain . DNSProviderInstances {
pType := provider . ProviderType
2018-01-10 01:53:16 +08:00
// If NO_PURGE is in use, make sure this *isn't* a provider that *doesn't* support NO_PURGE.
2020-01-13 00:24:10 +08:00
if domain . KeepUnknown && providers . ProviderHasCapability ( pType , providers . CantUseNOPURGE ) {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "%s uses NO_PURGE which is not supported by %s(%s)" , domain . Name , provider . Name , pType ) )
2017-08-12 03:43:06 +08:00
}
2018-01-05 08:19:35 +08:00
// Record if any providers do not support TXTMulti:
2020-01-13 00:24:10 +08:00
if ! providers . ProviderHasCapability ( pType , providers . CanUseTXTMulti ) {
2018-02-02 00:45:53 +08:00
txtMultiDissenters = append ( txtMultiDissenters , provider . Name )
2018-01-05 08:19:35 +08:00
}
2017-05-20 02:15:57 +08:00
}
2016-08-23 08:31:50 +08:00
// Normalize Nameservers.
for _ , ns := range domain . Nameservers {
2020-03-01 23:33:24 +08:00
// NB(tlim): Like any target, NAMESERVER() is input by the user
// as a shortname or a FQDN+dot. It is stored as FQDN+dot.
// Normalize it like we do any target to assure it is FQDN+dot
ns . Name = dnsutil . AddOrigin ( ns . Name , domain . Name + "." )
ns . Name = strings . TrimSuffix ( ns . Name , "." )
checkTarget ( ns . Name )
2016-08-23 08:31:50 +08:00
}
2020-03-01 23:33:24 +08:00
2016-08-23 08:31:50 +08:00
// Normalize Records.
2018-01-05 08:19:35 +08:00
models . PostProcessRecords ( domain . Records )
2016-08-23 08:31:50 +08:00
for _ , rec := range domain . Records {
2017-01-12 03:38:07 +08:00
if rec . TTL == 0 {
rec . TTL = models . DefaultTTL
}
2016-08-23 08:31:50 +08:00
// Validate the unmodified inputs:
2017-05-20 02:15:57 +08:00
if err := validateRecordTypes ( rec , domain . Name , pTypes ) ; err != nil {
2016-08-23 08:31:50 +08:00
errs = append ( errs , err )
}
2020-02-28 12:10:35 +08:00
if err := checkLabel ( rec . GetLabel ( ) , rec . Type , rec . GetTargetField ( ) , domain . Name , rec . Metadata ) ; err != nil {
2017-03-21 04:20:02 +08:00
errs = append ( errs , err )
}
if errs2 := checkTargets ( rec , domain . Name ) ; errs2 != nil {
2016-08-23 08:31:50 +08:00
errs = append ( errs , errs2 ... )
}
// Canonicalize Targets.
2020-05-30 22:56:20 +08:00
if rec . Type == "CNAME" || rec . Type == "MX" || rec . Type == "NAPTR" || rec . Type == "NS" || rec . Type == "SRV" {
2018-12-08 05:30:04 +08:00
// #rtype_variations
// These record types have a target that is a hostname.
// We normalize them to a FQDN so there is less variation to handle. If a
// provider API requires a shortname, the provider must do the shortening.
2018-03-20 05:18:58 +08:00
rec . SetTarget ( dnsutil . AddOrigin ( rec . GetTargetField ( ) , domain . Name + "." ) )
2017-06-06 02:57:32 +08:00
} else if rec . Type == "A" || rec . Type == "AAAA" {
2018-03-20 05:18:58 +08:00
rec . SetTarget ( net . ParseIP ( rec . GetTargetField ( ) ) . String ( ) )
2017-07-08 01:59:29 +08:00
} else if rec . Type == "PTR" {
var err error
2018-03-20 05:18:58 +08:00
var name string
if name , err = transform . PtrNameMagic ( rec . GetLabel ( ) , domain . Name ) ; err != nil {
2017-07-08 01:59:29 +08:00
errs = append ( errs , err )
}
2018-03-20 05:18:58 +08:00
rec . SetLabel ( name , domain . Name )
2017-07-26 02:59:40 +08:00
} else if rec . Type == "CAA" {
if rec . CaaTag != "issue" && rec . CaaTag != "issuewild" && rec . CaaTag != "iodef" {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "CAA tag %s is invalid" , rec . CaaTag ) )
2017-07-26 02:59:40 +08:00
}
2017-09-15 21:03:29 +08:00
} else if rec . Type == "TLSA" {
if rec . TlsaUsage < 0 || rec . TlsaUsage > 3 {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "TLSA Usage %d is invalid in record %s (domain %s)" ,
2018-03-20 05:18:58 +08:00
rec . TlsaUsage , rec . GetLabel ( ) , domain . Name ) )
2017-09-15 21:03:29 +08:00
}
if rec . TlsaSelector < 0 || rec . TlsaSelector > 1 {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "TLSA Selector %d is invalid in record %s (domain %s)" ,
2018-03-20 05:18:58 +08:00
rec . TlsaSelector , rec . GetLabel ( ) , domain . Name ) )
2017-09-15 21:03:29 +08:00
}
if rec . TlsaMatchingType < 0 || rec . TlsaMatchingType > 2 {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "TLSA MatchingType %d is invalid in record %s (domain %s)" ,
2018-03-20 05:18:58 +08:00
rec . TlsaMatchingType , rec . GetLabel ( ) , domain . Name ) )
2017-09-15 21:03:29 +08:00
}
2018-01-05 08:19:35 +08:00
} else if rec . Type == "TXT" && len ( txtMultiDissenters ) != 0 && len ( rec . TxtStrings ) > 1 {
// There are providers that don't support TXTMulti yet there is
// a TXT record with multiple strings:
errs = append ( errs ,
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
fmt . Errorf ( "TXT records with multiple strings (label %v domain: %v) not supported by %s" ,
2018-03-20 05:18:58 +08:00
rec . GetLabel ( ) , domain . Name , strings . Join ( txtMultiDissenters , "," ) ) )
2016-08-23 08:31:50 +08:00
}
2017-09-15 21:03:29 +08:00
2016-08-23 08:31:50 +08:00
// Populate FQDN:
2018-03-22 21:29:55 +08:00
rec . SetLabel ( rec . GetLabel ( ) , domain . Name )
2016-08-23 08:31:50 +08:00
}
}
2017-09-30 03:30:36 +08:00
// SPF flattening
if ers := flattenSPFs ( config ) ; len ( ers ) > 0 {
errs = append ( errs , ers ... )
}
// Process IMPORT_TRANSFORM
2016-08-23 08:31:50 +08:00
for _ , domain := range config . Domains {
for _ , rec := range domain . Records {
if rec . Type == "IMPORT_TRANSFORM" {
table , err := transform . DecodeTransformTable ( rec . Metadata [ "transform_table" ] )
if err != nil {
errs = append ( errs , err )
continue
}
2018-03-20 05:18:58 +08:00
err = importTransform ( config . FindDomain ( rec . GetTargetField ( ) ) , domain , table , rec . TTL )
2016-08-23 08:31:50 +08:00
if err != nil {
errs = append ( errs , err )
}
}
}
}
// Clean up:
for _ , domain := range config . Domains {
deleteImportTransformRecords ( domain )
}
// Run record transforms
for _ , domain := range config . Domains {
if err := applyRecordTransforms ( domain ) ; err != nil {
errs = append ( errs , err )
}
}
2017-04-20 03:13:28 +08:00
2017-04-14 01:10:15 +08:00
for _ , d := range config . Domains {
2018-04-27 02:45:10 +08:00
// Check that CNAMES don't have to co-exist with any other records
2017-04-14 01:10:15 +08:00
errs = append ( errs , checkCNAMEs ( d ) ... )
2018-04-27 02:45:10 +08:00
// Check that if any advanced record types are used in a domain, every provider for that domain supports them
2018-02-02 00:45:53 +08:00
err := checkProviderCapabilities ( d )
2017-04-20 03:13:28 +08:00
if err != nil {
2017-05-03 23:56:08 +08:00
errs = append ( errs , err )
2017-04-20 03:13:28 +08:00
}
2019-04-23 03:41:39 +08:00
// Check for duplicates
errs = append ( errs , checkDuplicates ( d . Records ) ... )
2018-04-27 02:45:10 +08:00
// Validate FQDN consistency
for _ , r := range d . Records {
if r . NameFQDN == "" || ! strings . HasSuffix ( r . NameFQDN , d . Name ) {
errs = append ( errs , fmt . Errorf ( "Record named '%s' does not have correct FQDN in domain '%s'. FQDN: %s" , r . Name , d . Name , r . NameFQDN ) )
}
}
2017-04-20 03:13:28 +08:00
}
2016-08-23 08:31:50 +08:00
return errs
}
2017-04-14 01:10:15 +08:00
func checkCNAMEs ( dc * models . DomainConfig ) ( errs [ ] error ) {
cnames := map [ string ] bool { }
for _ , r := range dc . Records {
if r . Type == "CNAME" {
2018-03-20 05:18:58 +08:00
if cnames [ r . GetLabel ( ) ] {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "Cannot have multiple CNAMEs with same name: %s" , r . GetLabelFQDN ( ) ) )
2017-04-14 01:10:15 +08:00
}
2018-03-20 05:18:58 +08:00
cnames [ r . GetLabel ( ) ] = true
2017-04-14 01:10:15 +08:00
}
}
for _ , r := range dc . Records {
2018-03-20 05:18:58 +08:00
if cnames [ r . GetLabel ( ) ] && r . Type != "CNAME" {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "Cannot have CNAME and %s record with same name: %s" , r . Type , r . GetLabelFQDN ( ) ) )
2017-04-14 01:10:15 +08:00
}
}
return
}
2019-04-23 03:41:39 +08:00
func checkDuplicates ( records [ ] * models . RecordConfig ) ( errs [ ] error ) {
seen := map [ string ] * models . RecordConfig { }
for _ , r := range records {
diffable := fmt . Sprintf ( "%s %s %s" , r . GetLabelFQDN ( ) , r . Type , r . ToDiffable ( ) )
if seen [ diffable ] != nil {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
errs = append ( errs , fmt . Errorf ( "Exact duplicate record found: %s" , diffable ) )
2019-04-23 03:41:39 +08:00
}
seen [ diffable ] = r
}
return errs
}
2020-02-25 20:22:32 +08:00
// We pull this out of checkProviderCapabilities() so that it's visible within
// the package elsewhere, so that our test suite can look at the list of
// capabilities we're checking and make sure that it's up-to-date.
var providerCapabilityChecks [ ] pairTypeCapability
type pairTypeCapability struct {
rType string
cap providers . Capability
}
func init ( ) {
providerCapabilityChecks = [ ] pairTypeCapability {
// If a zone uses rType X, the provider must support capability Y.
//{"X", providers.Y},
2017-07-06 22:24:21 +08:00
{ "ALIAS" , providers . CanUseAlias } ,
2020-02-22 20:09:31 +08:00
{ "AUTODNSSEC" , providers . CanAutoDNSSEC } ,
{ "CAA" , providers . CanUseCAA } ,
2020-05-30 23:05:54 +08:00
{ "DS" , providers . CanUseDS } ,
2020-02-25 20:22:32 +08:00
{ "NAPTR" , providers . CanUseNAPTR } ,
2017-07-06 22:24:21 +08:00
{ "PTR" , providers . CanUsePTR } ,
2020-02-25 20:22:32 +08:00
{ "R53_ALIAS" , providers . CanUseRoute53Alias } ,
2020-02-22 20:09:31 +08:00
{ "SSHFP" , providers . CanUseSSHFP } ,
2017-07-21 03:55:26 +08:00
{ "SRV" , providers . CanUseSRV } ,
2017-09-15 21:03:29 +08:00
{ "TLSA" , providers . CanUseTLSA } ,
2020-03-03 00:25:42 +08:00
{ "AZURE_ALIAS" , providers . CanUseAzureAlias } ,
2017-04-20 03:13:28 +08:00
}
2020-02-25 20:22:32 +08:00
}
func checkProviderCapabilities ( dc * models . DomainConfig ) error {
// Check if the zone uses a capability that the provider doesn't
// support.
for _ , ty := range providerCapabilityChecks {
2017-07-06 22:24:21 +08:00
hasAny := false
2020-02-22 20:09:31 +08:00
switch ty . rType {
case "AUTODNSSEC" :
if dc . AutoDNSSEC {
2017-07-06 22:24:21 +08:00
hasAny = true
2017-04-20 03:13:28 +08:00
}
2020-02-22 20:09:31 +08:00
default :
for _ , r := range dc . Records {
if r . Type == ty . rType {
hasAny = true
break
}
}
2017-04-20 03:13:28 +08:00
}
2017-07-06 22:24:21 +08:00
if ! hasAny {
continue
}
2018-02-02 00:45:53 +08:00
for _ , provider := range dc . DNSProviderInstances {
2020-02-22 20:09:31 +08:00
// fmt.Printf(" (checking if %q can %q for domain %q)\n", provider.ProviderType, ty.rType, dc.Name)
2020-01-13 00:24:10 +08:00
if ! providers . ProviderHasCapability ( provider . ProviderType , ty . cap ) {
Switch to Go 1.13 error wrapping (#604)
* Replaced errors.Wrap with fmt.Errorf (#589)
* Find: errors\.Wrap\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Replaced errors.Wrapf with fmt.Errorf (#589)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])\)
Replace: fmt.Errorf($2: %w$3, $1)
* Find: errors\.Wrapf\(([^,]+),\s+(["`][^"`]*)(["`])(,[^)]+)\)
* Replace: fmt.Errorf($2: %w$3$4, $1)
* Replaced errors.Errorf with fmt.Errorf (#589)
* Find: errors\.Errorf
Replace: fmt.Errorf
* Cleaned up remaining imports
* Cleanup
* Regenerate provider support matrix
This was broken by #533 ... and it's now the third time this has been missed.
2020-01-29 00:06:56 +08:00
return fmt . Errorf ( "Domain %s uses %s records, but DNS provider type %s does not support them" , dc . Name , ty . rType , provider . ProviderType )
2017-07-06 22:24:21 +08:00
}
}
2017-04-20 03:13:28 +08:00
}
return nil
}
2016-08-23 08:31:50 +08:00
func applyRecordTransforms ( domain * models . DomainConfig ) error {
for _ , rec := range domain . Records {
if rec . Type != "A" {
continue
}
tt , ok := rec . Metadata [ "transform" ]
if ! ok {
continue
}
table , err := transform . DecodeTransformTable ( tt )
if err != nil {
return err
}
2018-03-20 05:18:58 +08:00
ip := net . ParseIP ( rec . GetTargetField ( ) ) // ip already validated above
newIPs , err := transform . TransformIPToList ( net . ParseIP ( rec . GetTargetField ( ) ) , table )
2016-08-23 08:31:50 +08:00
if err != nil {
return err
}
for i , newIP := range newIPs {
if i == 0 && ! newIP . Equal ( ip ) {
2018-03-20 05:18:58 +08:00
rec . SetTarget ( newIP . String ( ) ) // replace target of first record if different
2016-08-23 08:31:50 +08:00
} else if i > 0 {
// any additional ips need identical records with the alternate ip added to the domain
copy , err := rec . Copy ( )
if err != nil {
return err
}
2018-03-20 05:18:58 +08:00
copy . SetTarget ( newIP . String ( ) )
2016-08-23 08:31:50 +08:00
domain . Records = append ( domain . Records , copy )
}
}
}
return nil
}