From 0849a0acb6093c94a3fb6f22781101427fecfd11 Mon Sep 17 00:00:00 2001 From: Ferdinando Formica Date: Thu, 28 Nov 2024 13:59:25 +0000 Subject: [PATCH] #334: protect against empty answers --- ns1/resource_record.go | 96 ++++++++++++++++++++----------------- ns1/resource_record_test.go | 17 +++++++ 2 files changed, 68 insertions(+), 45 deletions(-) diff --git a/ns1/resource_record.go b/ns1/resource_record.go index 2376c78..540071e 100644 --- a/ns1/resource_record.go +++ b/ns1/resource_record.go @@ -370,47 +370,51 @@ func resourceDataToRecord(r *dns.Record, d *schema.ResourceData) error { if shortAnswers := d.Get("short_answers").([]interface{}); len(shortAnswers) > 0 { for _, answerRaw := range shortAnswers { - answer := answerRaw.(string) - switch d.Get("type") { - case "TXT", "SPF": - r.AddAnswer(dns.NewTXTAnswer(answer)) - case "CAA": - r.AddAnswer(dns.NewAnswer(strings.SplitN(answer, " ", 3))) - default: - r.AddAnswer(dns.NewAnswer(strings.Split(answer, " "))) + if answerRaw != nil { + answer := answerRaw.(string) + switch d.Get("type") { + case "TXT", "SPF": + r.AddAnswer(dns.NewTXTAnswer(answer)) + case "CAA": + r.AddAnswer(dns.NewAnswer(strings.SplitN(answer, " ", 3))) + default: + r.AddAnswer(dns.NewAnswer(strings.Split(answer, " "))) + } } } } if answers := d.Get("answers").([]interface{}); len(answers) > 0 { for _, answerRaw := range answers { - answer := answerRaw.(map[string]interface{}) - var a *dns.Answer - - v := answer["answer"].(string) - switch d.Get("type") { - case "TXT", "SPF": - a = dns.NewTXTAnswer(v) - case "CAA": - a = dns.NewAnswer(strings.SplitN(v, " ", 3)) - default: - a = dns.NewAnswer(strings.Split(v, " ")) - } + if answerRaw != nil { + answer := answerRaw.(map[string]interface{}) + var a *dns.Answer + + v := answer["answer"].(string) + switch d.Get("type") { + case "TXT", "SPF": + a = dns.NewTXTAnswer(v) + case "CAA": + a = dns.NewAnswer(strings.SplitN(v, " ", 3)) + default: + a = dns.NewAnswer(strings.Split(v, " ")) + } - if v, ok := answer["region"]; ok { - a.RegionName = v.(string) - } + if v, ok := answer["region"]; ok { + a.RegionName = v.(string) + } - if v, ok := answer["meta"]; ok { - log.Println("answer meta", v) - meta, err := metaHandler(v) - if err != nil { - return err + if v, ok := answer["meta"]; ok { + log.Println("answer meta", v) + meta, err := metaHandler(v) + if err != nil { + return err + } + + a.Meta = meta } - a.Meta = meta + r.AddAnswer(a) } - - r.AddAnswer(a) } } log.Println("number of answers found:", len(r.Answers)) @@ -447,21 +451,23 @@ func resourceDataToRecord(r *dns.Record, d *schema.ResourceData) error { r.UseClientSubnet = &useClientSubnet if rawFilters := d.Get("filters").([]interface{}); len(rawFilters) > 0 { - filters := make([]*filter.Filter, len(rawFilters)) - for i, filterRaw := range rawFilters { - fi := filterRaw.(map[string]interface{}) - config := make(map[string]interface{}) - f := filter.Filter{ - Type: fi["filter"].(string), - Config: config, - } - if disabled, ok := fi["disabled"]; ok { - f.Disabled = disabled.(bool) - } - if rawConfig, ok := fi["config"]; ok { - f.Config = rawConfig.(map[string]interface{}) + filters := make([]*filter.Filter, 0, len(rawFilters)) + for _, filterRaw := range rawFilters { + if filterRaw != nil { + fi := filterRaw.(map[string]interface{}) + config := make(map[string]interface{}) + f := filter.Filter{ + Type: fi["filter"].(string), + Config: config, + } + if disabled, ok := fi["disabled"]; ok { + f.Disabled = disabled.(bool) + } + if rawConfig, ok := fi["config"]; ok { + f.Config = rawConfig.(map[string]interface{}) + } + filters = append(filters, &f) } - filters[i] = &f } r.Filters = filters } diff --git a/ns1/resource_record_test.go b/ns1/resource_record_test.go index 866d9cd..ba8076e 100644 --- a/ns1/resource_record_test.go +++ b/ns1/resource_record_test.go @@ -606,6 +606,10 @@ func TestAccRecord_validationError(t *testing.T) { */ ExpectError: regexp.MustCompile(`(?s)(Error: (zone|domain) has an invalid (leading|trailing) "\.", got: .*){4}`), }, + { + Config: testAccRecordNoAnswers(rString), + ExpectError: regexp.MustCompile(`Invalid body`), + }, }, }) } @@ -2018,6 +2022,19 @@ resource "ns1_record" "it" { `, rString, rString) } +// there must be at least one answer +func testAccRecordNoAnswers(rString string) string { + return fmt.Sprintf(` +resource "ns1_record" "it" { + zone = "terraform-test-%s.io" + domain = "test.terraform-test-%s.io" + type = "CNAME" + ttl = 60 + answers {} +} +`, rString, rString) +} + func testAccRecordLink(rString string) string { return fmt.Sprintf(` # the name being tested that is a link