github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/modules/dns-helper/dns_helper_test.go (about) 1 package dns_helper 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/gruntwork-io/terratest/modules/retry" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 // These are the current public nameservers for gruntwork.io domain 13 // They should be updated whenever they change to pass the tests 14 // relying on the public DNS infrastructure 15 var publicDomainNameservers = []string{ 16 "ns-1499.awsdns-59.org", 17 "ns-190.awsdns-23.com", 18 "ns-1989.awsdns-56.co.uk", 19 "ns-853.awsdns-42.net", 20 } 21 22 var testDNSDatabase = dnsDatabase{ 23 DNSQuery{"A", "a." + testDomain}: DNSAnswers{ 24 {"A", "2.2.2.2"}, 25 {"A", "1.1.1.1"}, 26 }, 27 28 DNSQuery{"AAAA", "aaaa." + testDomain}: DNSAnswers{ 29 {"AAAA", "2001:db8::aaaa"}, 30 }, 31 32 DNSQuery{"CNAME", "terratest." + testDomain}: DNSAnswers{ 33 {"CNAME", "gruntwork-io.github.io."}, 34 }, 35 36 DNSQuery{"CNAME", "cname1." + testDomain}: DNSAnswers{ 37 {"CNAME", "cname2." + testDomain + "."}, 38 }, 39 40 DNSQuery{"A", "cname1." + testDomain}: DNSAnswers{ 41 {"CNAME", "cname2." + testDomain + "."}, 42 {"CNAME", "cname3." + testDomain + "."}, 43 {"CNAME", "cname4." + testDomain + "."}, 44 {"CNAME", "cnamefinal." + testDomain + "."}, 45 {"A", "1.1.1.1"}, 46 }, 47 48 DNSQuery{"TXT", "txt." + testDomain}: DNSAnswers{ 49 {"TXT", `"This is a text."`}, 50 }, 51 52 DNSQuery{"MX", testDomain}: DNSAnswers{ 53 {"MX", "10 mail." + testDomain + "."}, 54 }, 55 } 56 57 // Lookup should succeed in finding the nameservers of the public domain 58 // Uses system resolver config 59 func TestOkDNSFindNameservers(t *testing.T) { 60 t.Parallel() 61 fqdn := "terratest.gruntwork.io" 62 expectedNameservers := publicDomainNameservers 63 nameservers, err := DNSFindNameserversE(t, fqdn, nil) 64 require.NoError(t, err) 65 require.ElementsMatch(t, nameservers, expectedNameservers) 66 } 67 68 // Lookup should fail because of inexistent domain 69 // Uses system resolver config 70 func TestErrorDNSFindNameservers(t *testing.T) { 71 t.Parallel() 72 fqdn := "this.domain.doesnt.exist" 73 nameservers, err := DNSFindNameserversE(t, fqdn, nil) 74 require.Error(t, err) 75 require.Nil(t, nameservers) 76 } 77 78 // Lookup should succeed with answers from just one authoritative nameserver 79 // Uses system resolver config to lookup a public domain and its public nameservers 80 func TestOkTerratestDNSLookupAuthoritative(t *testing.T) { 81 t.Parallel() 82 dnsQuery := DNSQuery{"CNAME", "terratest." + testDomain} 83 expected := DNSAnswers{{"CNAME", "gruntwork-io.github.io."}} 84 res, err := DNSLookupAuthoritativeE(t, dnsQuery, nil) 85 require.NoError(t, err) 86 require.ElementsMatch(t, res, expected) 87 } 88 89 // *********************************** 90 // Tests that use local dnsTestServers 91 92 // Lookup should succeed with answers from just one authoritative nameserver 93 func TestOkLocalDNSLookupAuthoritative(t *testing.T) { 94 t.Parallel() 95 s1, s2 := setupTestDNSServers(t) 96 defer shutDownServers(t, s1, s2) 97 for dnsQuery, expected := range testDNSDatabase { 98 s1.AddEntryToDNSDatabase(dnsQuery, expected) 99 res, err := DNSLookupAuthoritativeE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 100 require.NoError(t, err) 101 require.ElementsMatch(t, res, expected) 102 } 103 } 104 105 // Lookup should fail because of missing answers from all authoritative nameservers 106 func TestErrorLocalDNSLookupAuthoritative(t *testing.T) { 107 t.Parallel() 108 s1, s2 := setupTestDNSServers(t) 109 defer shutDownServers(t, s1, s2) 110 dnsQuery := DNSQuery{"A", "txt." + testDomain} 111 _, err := DNSLookupAuthoritativeE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 112 if _, ok := err.(*NotFoundError); !ok { 113 t.Errorf("unexpected error, got %q", err) 114 } 115 } 116 117 // Lookup should succeed with consistent answers from all authoritative nameservers 118 func TestOkLocalDNSLookupAuthoritativeAll(t *testing.T) { 119 t.Parallel() 120 s1, s2 := setupTestDNSServers(t) 121 defer shutDownServers(t, s1, s2) 122 for dnsQuery, expected := range testDNSDatabase { 123 s1.AddEntryToDNSDatabase(dnsQuery, expected) 124 s2.AddEntryToDNSDatabase(dnsQuery, expected) 125 res, err := DNSLookupAuthoritativeE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 126 require.NoError(t, err) 127 require.ElementsMatch(t, res, expected) 128 } 129 } 130 131 // Lookup should fail because of missing answers from all authoritative nameservers 132 func TestError1DNSLookupAuthoritativeAll(t *testing.T) { 133 t.Parallel() 134 s1, s2 := setupTestDNSServers(t) 135 defer shutDownServers(t, s1, s2) 136 dnsQuery := DNSQuery{"A", "txt." + testDomain} 137 _, err := DNSLookupAuthoritativeAllE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 138 if _, ok := err.(*NotFoundError); !ok { 139 t.Errorf("unexpected error, got %q", err) 140 } 141 } 142 143 // Lookup should fail because of missing answers from one authoritative nameserver 144 func TestError2DNSLookupAuthoritativeAll(t *testing.T) { 145 t.Parallel() 146 s1, s2 := setupTestDNSServers(t) 147 defer shutDownServers(t, s1, s2) 148 dnsQuery := DNSQuery{"A", "a." + testDomain} 149 s1.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "1.1.1.1"}}) 150 _, err := DNSLookupAuthoritativeAllE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 151 if _, ok := err.(*NotFoundError); !ok { 152 t.Errorf("unexpected error, got %q", err) 153 } 154 } 155 156 // Lookup should fail because of inconsistent answers from authoritative nameservers 157 func TestError3DNSLookupAuthoritativeAll(t *testing.T) { 158 t.Parallel() 159 s1, s2 := setupTestDNSServers(t) 160 defer shutDownServers(t, s1, s2) 161 dnsQuery := DNSQuery{"A", "a." + testDomain} 162 s1.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "1.1.1.1"}}) 163 s2.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 164 _, err := DNSLookupAuthoritativeAllE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 165 if _, ok := err.(*InconsistentAuthoritativeError); !ok { 166 t.Errorf("unexpected error, got %q", err) 167 } 168 } 169 170 // Lookup should fail because of inexistent domain 171 func TestError4DNSLookupAuthoritativeAll(t *testing.T) { 172 t.Parallel() 173 s1, s2 := setupTestDNSServers(t) 174 defer shutDownServers(t, s1, s2) 175 dnsQuery := DNSQuery{"A", "this.domain.doesnt.exist"} 176 _, err := DNSLookupAuthoritativeAllE(t, dnsQuery, []string{s1.Address(), s2.Address()}) 177 if _, ok := err.(*NSNotFoundError); !ok { 178 t.Errorf("unexpected error, got %q", err) 179 } 180 } 181 182 // First lookups should fail because of missing answers from all authoritative nameservers 183 // Retry lookups should succeed with answers from just one authoritative nameserver 184 func TestOkDNSLookupAuthoritativeWithRetry(t *testing.T) { 185 t.Parallel() 186 s1, s2 := setupTestDNSServersRetry(t) 187 defer shutDownServers(t, s1, s2) 188 dnsQuery := DNSQuery{"A", "a." + testDomain} 189 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 190 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 191 res, err := DNSLookupAuthoritativeWithRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, 5, time.Second) 192 require.NoError(t, err) 193 require.ElementsMatch(t, res, expectedRes) 194 } 195 196 // First lookups should fail because of missing answers from all authoritative nameservers 197 // Retry lookups should fail because of missing answers from all authoritative nameservers 198 func TestErrorDNSLookupAuthoritativeWithRetry(t *testing.T) { 199 t.Parallel() 200 s1, s2 := setupTestDNSServersRetry(t) 201 defer shutDownServers(t, s1, s2) 202 dnsQuery := DNSQuery{"A", "txt." + testDomain} 203 _, err := DNSLookupAuthoritativeWithRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, 5, time.Second) 204 require.Error(t, err) 205 if _, ok := err.(retry.MaxRetriesExceeded); !ok { 206 t.Errorf("unexpected error, got %q", err) 207 } 208 } 209 210 // First lookups should fail because of missing answers from one authoritative nameservers 211 // Retry lookups should succeed with consistent answers 212 func TestOkDNSLookupAuthoritativeAllWithRetryNotfound(t *testing.T) { 213 t.Parallel() 214 s1, s2 := setupTestDNSServersRetry(t) 215 defer shutDownServers(t, s1, s2) 216 dnsQuery := DNSQuery{"A", "a." + testDomain} 217 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 218 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 219 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 220 s2.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 221 res, err := DNSLookupAuthoritativeAllWithRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, 5, time.Second) 222 require.NoError(t, err) 223 require.ElementsMatch(t, res, expectedRes) 224 } 225 226 // First lookups should fail because of inconsistent answers from authoritative nameservers 227 // Retry lookups should succeed with consistent answers 228 func TestOkDNSLookupAuthoritativeAllWithRetryInconsistent(t *testing.T) { 229 t.Parallel() 230 s1, s2 := setupTestDNSServersRetry(t) 231 defer shutDownServers(t, s1, s2) 232 dnsQuery := DNSQuery{"A", "a." + testDomain} 233 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 234 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 235 s2.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 236 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 237 s2.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 238 res, err := DNSLookupAuthoritativeAllWithRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, 5, time.Second) 239 require.NoError(t, err) 240 require.ElementsMatch(t, res, expectedRes) 241 } 242 243 // First lookups should fail because of missing answer from one authoritative nameserver 244 // Retry lookups should fail because of inconsistent answers from authoritative nameservers 245 func TestErrorDNSLookupAuthoritativeAllWithRetry(t *testing.T) { 246 t.Parallel() 247 s1, s2 := setupTestDNSServersRetry(t) 248 defer shutDownServers(t, s1, s2) 249 dnsQuery := DNSQuery{"A", "a." + testDomain} 250 s1.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 251 s1.AddEntryToDNSDatabaseRetry(dnsQuery, DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}}) 252 s2.AddEntryToDNSDatabaseRetry(dnsQuery, DNSAnswers{{"A", "1.1.1.1"}}) 253 _, err := DNSLookupAuthoritativeAllWithRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, 5, time.Second) 254 require.Error(t, err) 255 if _, ok := err.(retry.MaxRetriesExceeded); !ok { 256 t.Errorf("unexpected error, got %q", err) 257 } 258 } 259 260 // Lookup should succeed with consistent and validated replies 261 func TestOkDNSLookupAuthoritativeAllWithValidation(t *testing.T) { 262 t.Parallel() 263 s1, s2 := setupTestDNSServers(t) 264 defer shutDownServers(t, s1, s2) 265 dnsQuery := DNSQuery{"A", "a." + testDomain} 266 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 267 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 268 s2.AddEntryToDNSDatabase(dnsQuery, expectedRes) 269 err := DNSLookupAuthoritativeAllWithValidationE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes) 270 require.NoError(t, err) 271 } 272 273 // Lookup should fail because of missing answers from all authoritative nameservers 274 func TestErrorDNSLookupAuthoritativeAllWithValidation(t *testing.T) { 275 t.Parallel() 276 s1, s2 := setupTestDNSServers(t) 277 defer shutDownServers(t, s1, s2) 278 dnsQuery := DNSQuery{"A", "a." + testDomain} 279 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 280 err := DNSLookupAuthoritativeAllWithValidationE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes) 281 require.Error(t, err) 282 if _, ok := err.(*NotFoundError); !ok { 283 t.Errorf("unexpected error, got %q", err) 284 } 285 } 286 287 // Lookup should fail because of missing answers from one authoritative nameservers 288 func TestError2DNSLookupAuthoritativeAllWithValidation(t *testing.T) { 289 t.Parallel() 290 s1, s2 := setupTestDNSServers(t) 291 defer shutDownServers(t, s1, s2) 292 dnsQuery := DNSQuery{"A", "a." + testDomain} 293 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 294 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 295 err := DNSLookupAuthoritativeAllWithValidationE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes) 296 require.Error(t, err) 297 if _, ok := err.(*NotFoundError); !ok { 298 t.Errorf("unexpected error, got %q", err) 299 } 300 } 301 302 // Lookup should fail because of inconsistent authoritative replies 303 func TestError3DNSLookupAuthoritativeAllWithValidation(t *testing.T) { 304 t.Parallel() 305 s1, s2 := setupTestDNSServers(t) 306 defer shutDownServers(t, s1, s2) 307 dnsQuery := DNSQuery{"A", "a." + testDomain} 308 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 309 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 310 s2.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 311 err := DNSLookupAuthoritativeAllWithValidationE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes) 312 require.Error(t, err) 313 if _, ok := err.(*InconsistentAuthoritativeError); !ok { 314 t.Errorf("unexpected error, got %q", err) 315 } 316 } 317 318 // First lookups should fail because of missing answers from all authoritative nameservers 319 // Retry lookups should succeed with consistent and validated replies 320 func TestOkDNSLookupAuthoritativeAllWithValidationRetry(t *testing.T) { 321 t.Parallel() 322 s1, s2 := setupTestDNSServersRetry(t) 323 defer shutDownServers(t, s1, s2) 324 dnsQuery := DNSQuery{"A", "a." + testDomain} 325 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 326 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 327 s2.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 328 err := DNSLookupAuthoritativeAllWithValidationRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes, 5, time.Second) 329 require.NoError(t, err) 330 } 331 332 // First lookups should fail because of missing answer from one authoritative nameserver 333 // Retry lookups should succeed with consistent and validated replies 334 func TestOk2DNSLookupAuthoritativeAllWithValidationRetry(t *testing.T) { 335 t.Parallel() 336 s1, s2 := setupTestDNSServersRetry(t) 337 defer shutDownServers(t, s1, s2) 338 dnsQuery := DNSQuery{"A", "a." + testDomain} 339 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 340 s1.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 341 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 342 s2.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 343 err := DNSLookupAuthoritativeAllWithValidationRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes, 5, time.Second) 344 require.NoError(t, err) 345 } 346 347 // First lookups should fail because of inconsistent authoritative replies 348 // Retry lookups should succeed with consistent and validated replies 349 func TestOk3DNSLookupAuthoritativeAllWithValidationRetry(t *testing.T) { 350 t.Parallel() 351 s1, s2 := setupTestDNSServersRetry(t) 352 defer shutDownServers(t, s1, s2) 353 dnsQuery := DNSQuery{"A", "a." + testDomain} 354 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 355 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 356 s2.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 357 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 358 s2.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 359 err := DNSLookupAuthoritativeAllWithValidationRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes, 5, time.Second) 360 require.NoError(t, err) 361 } 362 363 // First lookups should fail because of inconsistent authoritative replies 364 // Retry lookups should fail also because of inconsistent authoritative replies 365 func TestErrorDNSLookupAuthoritativeAllWithValidationRetry(t *testing.T) { 366 t.Parallel() 367 s1, s2 := setupTestDNSServersRetry(t) 368 defer shutDownServers(t, s1, s2) 369 dnsQuery := DNSQuery{"A", "a." + testDomain} 370 expectedRes := DNSAnswers{{"A", "1.1.1.1"}, {"A", "2.2.2.2"}} 371 s1.AddEntryToDNSDatabase(dnsQuery, expectedRes) 372 s2.AddEntryToDNSDatabase(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 373 s1.AddEntryToDNSDatabaseRetry(dnsQuery, expectedRes) 374 s2.AddEntryToDNSDatabaseRetry(dnsQuery, DNSAnswers{{"A", "2.2.2.2"}}) 375 err := DNSLookupAuthoritativeAllWithValidationRetryE(t, dnsQuery, []string{s1.Address(), s2.Address()}, expectedRes, 5, time.Second) 376 if _, ok := err.(retry.MaxRetriesExceeded); !ok { 377 t.Errorf("unexpected error, got %q", err) 378 } 379 } 380 381 func shutDownServers(t *testing.T, s1, s2 *dnsTestServer) { 382 err := s1.Server.Shutdown() 383 assert.NoError(t, err) 384 err = s2.Server.Shutdown() 385 assert.NoError(t, err) 386 }