From 02031540210117154d9833184ec9880d56606fac Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 17 Aug 2021 15:58:10 -0400 Subject: [PATCH] VULTR: Fix TXT quoting issue (#1239) * VULTR: Fix TXT quoting issue * VULTR: Add tests that trigger Vultr's SPF mode * VULTR: Enforce the fact that VULTR only supports a single string in TXT records Co-authored-by: Lee Martin --- integrationTest/integration_test.go | 6 ++++++ providers/vultr/auditrecords.go | 4 ++++ providers/vultr/vultrProvider.go | 13 +++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/integrationTest/integration_test.go b/integrationTest/integration_test.go index d7a45e0f1..9e10f10fa 100644 --- a/integrationTest/integration_test.go +++ b/integrationTest/integration_test.go @@ -789,6 +789,12 @@ func makeTests(t *testing.T) []*TestGroup { tc("Create a TXT with spaces", txt("foo", "with spaces")), ), + testgroup("simple TXT-spf1", + // This was added because Vultr syntax-checks TXT records with + // SPF contents. + tc("Create a TXT/SPF", txt("foo", "v=spf1 ip4:99.99.99.99 -all")), + ), + testgroup("long TXT", tc("Create long TXT", txt("foo", strings.Repeat("A", 300))), tc("Change long TXT", txt("foo", strings.Repeat("B", 310))), diff --git a/providers/vultr/auditrecords.go b/providers/vultr/auditrecords.go index 949127d45..4efe22900 100644 --- a/providers/vultr/auditrecords.go +++ b/providers/vultr/auditrecords.go @@ -16,5 +16,9 @@ func AuditRecords(records []*models.RecordConfig) error { } // Still needed as of 2021-03-02 + if err := recordaudit.TxtNoMultipleStrings(records); err != nil { + return err + } + return nil } diff --git a/providers/vultr/vultrProvider.go b/providers/vultr/vultrProvider.go index 3a5c4ca3a..d5a930981 100644 --- a/providers/vultr/vultrProvider.go +++ b/providers/vultr/vultrProvider.go @@ -200,8 +200,12 @@ func toRecordConfig(domain string, r *govultr.DNSRecord) (*models.RecordConfig, // Vultr returns SRV records in the format "[weight] [port] [target]". return rc, rc.SetTargetSRVPriorityString(uint16(vultrPriority(r)), data) case "TXT": - // Remove quotes if it is a TXT record. - if !strings.HasPrefix(data, `"`) || !strings.HasSuffix(data, `"`) { + // TXT records from Vultr are always surrounded by quotes. + // They don't permit quotes within the string, therefore there is no + // need to resolve \" or other quoting. + if !(strings.HasPrefix(data, `"`) && strings.HasSuffix(data, `"`)) { + // Give an error if Vultr changes their protocol. We'd rather break + // than do the wrong thing. return nil, errors.New("unexpected lack of quotes in TXT record from Vultr") } return rc, rc.SetTargetTXT(data[1 : len(data)-1]) @@ -251,6 +255,11 @@ func toVultrRecord(dc *models.DomainConfig, rc *models.RecordConfig, vultrID int r.Data = fmt.Sprintf(`%v %s "%s"`, rc.CaaFlag, rc.CaaTag, rc.GetTargetField()) case "SSHFP": r.Data = fmt.Sprintf("%d %d %s", rc.SshfpAlgorithm, rc.SshfpFingerprint, rc.GetTargetField()) + case "TXT": + // Vultr doesn't permit TXT strings to include double-quotes + // therefore, we don't have to escape interior double-quotes. + // Vultr's API requires the string to begin and end with double-quotes. + r.Data = `"` + strings.Join(rc.TxtStrings, "") + `"` default: }