diff --git a/docs/sources/mx-record.md b/docs/sources/mx-record.md index 2c864272ba..e3e8249f64 100644 --- a/docs/sources/mx-record.md +++ b/docs/sources/mx-record.md @@ -1,7 +1,7 @@ # MX record with CRD source You can create and manage MX records with the help of [CRD source](../sources/crd.md) -and `DNSEndpoint` CRD. Currently, this feature is only supported by `aws`, `azure`, `cloudflare`, `digitalocean` and `google` providers. +and `DNSEndpoint` CRD. Currently, this feature is only supported by `aws`, `azure`, `cloudflare`, `digitalocean`, `google` and `webhook` providers. In order to start managing MX records you need to set the `--managed-record-types=MX` flag. diff --git a/source/crd.go b/source/crd.go index 6fe96d7b1e..dcb25149cb 100644 --- a/source/crd.go +++ b/source/crd.go @@ -195,14 +195,20 @@ func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error if (ep.RecordType == endpoint.RecordTypeCNAME || ep.RecordType == endpoint.RecordTypeA || ep.RecordType == endpoint.RecordTypeAAAA) && len(ep.Targets) < 1 { log.Debugf("Endpoint %s with DNSName %s has an empty list of targets, allowing it to pass through for default-targets processing", dnsEndpoint.Name, ep.DNSName) } - isNAPTR := ep.RecordType == endpoint.RecordTypeNAPTR - isTXT := ep.RecordType == endpoint.RecordTypeTXT illegalTarget := false for _, target := range ep.Targets { hasDot := strings.HasSuffix(target, ".") - // Skip dot validation for TXT records as they can contain arbitrary text - if !isTXT && ((isNAPTR && !hasDot) || (!isNAPTR && hasDot)) { - illegalTarget = true + + switch ep.RecordType { + case endpoint.RecordTypeTXT, endpoint.RecordTypeMX: + continue // TXT records allow arbitrary text, skip validation; MX records can have trailing dot but it's not required, skip validation + case endpoint.RecordTypeNAPTR: + illegalTarget = !hasDot // Must have trailing dot + default: + illegalTarget = hasDot // Must NOT have trailing dot + } + + if illegalTarget { break } } diff --git a/source/crd_test.go b/source/crd_test.go index ffd9b50be9..0910bc47d5 100644 --- a/source/crd_test.go +++ b/source/crd_test.go @@ -518,6 +518,48 @@ func testCRDSourceEndpoints(t *testing.T) { expectEndpoints: false, expectError: false, }, + { + title: "MX Record allowing trailing dot in target", + registeredAPIVersion: apiv1alpha1.GroupVersion.String(), + apiVersion: apiv1alpha1.GroupVersion.String(), + registeredKind: apiv1alpha1.DNSEndpointKind, + kind: apiv1alpha1.DNSEndpointKind, + namespace: "foo", + registeredNamespace: "foo", + labels: map[string]string{"test": "that"}, + labelFilter: "test=that", + endpoints: []*endpoint.Endpoint{ + { + DNSName: "example.org", + Targets: endpoint.Targets{"example.com."}, + RecordType: endpoint.RecordTypeMX, + RecordTTL: 180, + }, + }, + expectEndpoints: true, + expectError: false, + }, + { + title: "MX Record without trailing dot in target", + registeredAPIVersion: apiv1alpha1.GroupVersion.String(), + apiVersion: apiv1alpha1.GroupVersion.String(), + registeredKind: apiv1alpha1.DNSEndpointKind, + kind: apiv1alpha1.DNSEndpointKind, + namespace: "foo", + registeredNamespace: "foo", + labels: map[string]string{"test": "that"}, + labelFilter: "test=that", + endpoints: []*endpoint.Endpoint{ + { + DNSName: "example.org", + Targets: endpoint.Targets{"example.com"}, + RecordType: endpoint.RecordTypeMX, + RecordTTL: 180, + }, + }, + expectEndpoints: true, + expectError: false, + }, } { t.Run(ti.title, func(t *testing.T) { t.Parallel()