github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/moby/registry/registry_test.go (about) 1 package registry // import "github.com/docker/docker/registry" 2 3 import ( 4 "net/http" 5 "net/http/httputil" 6 "os" 7 "strings" 8 "testing" 9 10 "github.com/docker/distribution/reference" 11 "github.com/docker/distribution/registry/client/transport" 12 "github.com/docker/docker/api/types" 13 registrytypes "github.com/docker/docker/api/types/registry" 14 "gotest.tools/v3/assert" 15 "gotest.tools/v3/skip" 16 ) 17 18 func spawnTestRegistrySession(t *testing.T) *Session { 19 authConfig := &types.AuthConfig{} 20 endpoint, err := NewV1Endpoint(makeIndex("/v1/"), "", nil) 21 if err != nil { 22 t.Fatal(err) 23 } 24 userAgent := "docker test client" 25 var tr http.RoundTripper = debugTransport{NewTransport(nil), t.Log} 26 tr = transport.NewTransport(AuthTransport(tr, authConfig, false), Headers(userAgent, nil)...) 27 client := HTTPClient(tr) 28 r, err := NewSession(client, authConfig, endpoint) 29 if err != nil { 30 t.Fatal(err) 31 } 32 // In a normal scenario for the v1 registry, the client should send a `X-Docker-Token: true` 33 // header while authenticating, in order to retrieve a token that can be later used to 34 // perform authenticated actions. 35 // 36 // The mock v1 registry does not support that, (TODO(tiborvass): support it), instead, 37 // it will consider authenticated any request with the header `X-Docker-Token: fake-token`. 38 // 39 // Because we know that the client's transport is an `*authTransport` we simply cast it, 40 // in order to set the internal cached token to the fake token, and thus send that fake token 41 // upon every subsequent requests. 42 r.client.Transport.(*authTransport).token = []string{"fake-token"} 43 return r 44 } 45 46 func TestPingRegistryEndpoint(t *testing.T) { 47 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 48 testPing := func(index *registrytypes.IndexInfo, expectedStandalone bool, assertMessage string) { 49 ep, err := NewV1Endpoint(index, "", nil) 50 if err != nil { 51 t.Fatal(err) 52 } 53 regInfo, err := ep.Ping() 54 if err != nil { 55 t.Fatal(err) 56 } 57 58 assertEqual(t, regInfo.Standalone, expectedStandalone, assertMessage) 59 } 60 61 testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)") 62 testPing(makeHTTPSIndex("/v1/"), true, "Expected standalone to be true (default)") 63 testPing(makePublicIndex(), false, "Expected standalone to be false for public index") 64 } 65 66 func TestEndpoint(t *testing.T) { 67 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 68 // Simple wrapper to fail test if err != nil 69 expandEndpoint := func(index *registrytypes.IndexInfo) *V1Endpoint { 70 endpoint, err := NewV1Endpoint(index, "", nil) 71 if err != nil { 72 t.Fatal(err) 73 } 74 return endpoint 75 } 76 77 assertInsecureIndex := func(index *registrytypes.IndexInfo) { 78 index.Secure = true 79 _, err := NewV1Endpoint(index, "", nil) 80 assertNotEqual(t, err, nil, index.Name+": Expected error for insecure index") 81 assertEqual(t, strings.Contains(err.Error(), "insecure-registry"), true, index.Name+": Expected insecure-registry error for insecure index") 82 index.Secure = false 83 } 84 85 assertSecureIndex := func(index *registrytypes.IndexInfo) { 86 index.Secure = true 87 _, err := NewV1Endpoint(index, "", nil) 88 assertNotEqual(t, err, nil, index.Name+": Expected cert error for secure index") 89 assertEqual(t, strings.Contains(err.Error(), "certificate signed by unknown authority"), true, index.Name+": Expected cert error for secure index") 90 index.Secure = false 91 } 92 93 index := ®istrytypes.IndexInfo{} 94 index.Name = makeURL("/v1/") 95 endpoint := expandEndpoint(index) 96 assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 97 assertInsecureIndex(index) 98 99 index.Name = makeURL("") 100 endpoint = expandEndpoint(index) 101 assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 102 assertInsecureIndex(index) 103 104 httpURL := makeURL("") 105 index.Name = strings.SplitN(httpURL, "://", 2)[1] 106 endpoint = expandEndpoint(index) 107 assertEqual(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/") 108 assertInsecureIndex(index) 109 110 index.Name = makeHTTPSURL("/v1/") 111 endpoint = expandEndpoint(index) 112 assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 113 assertSecureIndex(index) 114 115 index.Name = makeHTTPSURL("") 116 endpoint = expandEndpoint(index) 117 assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 118 assertSecureIndex(index) 119 120 httpsURL := makeHTTPSURL("") 121 index.Name = strings.SplitN(httpsURL, "://", 2)[1] 122 endpoint = expandEndpoint(index) 123 assertEqual(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/") 124 assertSecureIndex(index) 125 126 badEndpoints := []string{ 127 "http://127.0.0.1/v1/", 128 "https://127.0.0.1/v1/", 129 "http://127.0.0.1", 130 "https://127.0.0.1", 131 "127.0.0.1", 132 } 133 for _, address := range badEndpoints { 134 index.Name = address 135 _, err := NewV1Endpoint(index, "", nil) 136 checkNotEqual(t, err, nil, "Expected error while expanding bad endpoint") 137 } 138 } 139 140 func TestParseRepositoryInfo(t *testing.T) { 141 type staticRepositoryInfo struct { 142 Index *registrytypes.IndexInfo 143 RemoteName string 144 CanonicalName string 145 LocalName string 146 Official bool 147 } 148 149 expectedRepoInfos := map[string]staticRepositoryInfo{ 150 "fooo/bar": { 151 Index: ®istrytypes.IndexInfo{ 152 Name: IndexName, 153 Official: true, 154 }, 155 RemoteName: "fooo/bar", 156 LocalName: "fooo/bar", 157 CanonicalName: "docker.io/fooo/bar", 158 Official: false, 159 }, 160 "library/ubuntu": { 161 Index: ®istrytypes.IndexInfo{ 162 Name: IndexName, 163 Official: true, 164 }, 165 RemoteName: "library/ubuntu", 166 LocalName: "ubuntu", 167 CanonicalName: "docker.io/library/ubuntu", 168 Official: true, 169 }, 170 "nonlibrary/ubuntu": { 171 Index: ®istrytypes.IndexInfo{ 172 Name: IndexName, 173 Official: true, 174 }, 175 RemoteName: "nonlibrary/ubuntu", 176 LocalName: "nonlibrary/ubuntu", 177 CanonicalName: "docker.io/nonlibrary/ubuntu", 178 Official: false, 179 }, 180 "ubuntu": { 181 Index: ®istrytypes.IndexInfo{ 182 Name: IndexName, 183 Official: true, 184 }, 185 RemoteName: "library/ubuntu", 186 LocalName: "ubuntu", 187 CanonicalName: "docker.io/library/ubuntu", 188 Official: true, 189 }, 190 "other/library": { 191 Index: ®istrytypes.IndexInfo{ 192 Name: IndexName, 193 Official: true, 194 }, 195 RemoteName: "other/library", 196 LocalName: "other/library", 197 CanonicalName: "docker.io/other/library", 198 Official: false, 199 }, 200 "127.0.0.1:8000/private/moonbase": { 201 Index: ®istrytypes.IndexInfo{ 202 Name: "127.0.0.1:8000", 203 Official: false, 204 }, 205 RemoteName: "private/moonbase", 206 LocalName: "127.0.0.1:8000/private/moonbase", 207 CanonicalName: "127.0.0.1:8000/private/moonbase", 208 Official: false, 209 }, 210 "127.0.0.1:8000/privatebase": { 211 Index: ®istrytypes.IndexInfo{ 212 Name: "127.0.0.1:8000", 213 Official: false, 214 }, 215 RemoteName: "privatebase", 216 LocalName: "127.0.0.1:8000/privatebase", 217 CanonicalName: "127.0.0.1:8000/privatebase", 218 Official: false, 219 }, 220 "localhost:8000/private/moonbase": { 221 Index: ®istrytypes.IndexInfo{ 222 Name: "localhost:8000", 223 Official: false, 224 }, 225 RemoteName: "private/moonbase", 226 LocalName: "localhost:8000/private/moonbase", 227 CanonicalName: "localhost:8000/private/moonbase", 228 Official: false, 229 }, 230 "localhost:8000/privatebase": { 231 Index: ®istrytypes.IndexInfo{ 232 Name: "localhost:8000", 233 Official: false, 234 }, 235 RemoteName: "privatebase", 236 LocalName: "localhost:8000/privatebase", 237 CanonicalName: "localhost:8000/privatebase", 238 Official: false, 239 }, 240 "example.com/private/moonbase": { 241 Index: ®istrytypes.IndexInfo{ 242 Name: "example.com", 243 Official: false, 244 }, 245 RemoteName: "private/moonbase", 246 LocalName: "example.com/private/moonbase", 247 CanonicalName: "example.com/private/moonbase", 248 Official: false, 249 }, 250 "example.com/privatebase": { 251 Index: ®istrytypes.IndexInfo{ 252 Name: "example.com", 253 Official: false, 254 }, 255 RemoteName: "privatebase", 256 LocalName: "example.com/privatebase", 257 CanonicalName: "example.com/privatebase", 258 Official: false, 259 }, 260 "example.com:8000/private/moonbase": { 261 Index: ®istrytypes.IndexInfo{ 262 Name: "example.com:8000", 263 Official: false, 264 }, 265 RemoteName: "private/moonbase", 266 LocalName: "example.com:8000/private/moonbase", 267 CanonicalName: "example.com:8000/private/moonbase", 268 Official: false, 269 }, 270 "example.com:8000/privatebase": { 271 Index: ®istrytypes.IndexInfo{ 272 Name: "example.com:8000", 273 Official: false, 274 }, 275 RemoteName: "privatebase", 276 LocalName: "example.com:8000/privatebase", 277 CanonicalName: "example.com:8000/privatebase", 278 Official: false, 279 }, 280 "localhost/private/moonbase": { 281 Index: ®istrytypes.IndexInfo{ 282 Name: "localhost", 283 Official: false, 284 }, 285 RemoteName: "private/moonbase", 286 LocalName: "localhost/private/moonbase", 287 CanonicalName: "localhost/private/moonbase", 288 Official: false, 289 }, 290 "localhost/privatebase": { 291 Index: ®istrytypes.IndexInfo{ 292 Name: "localhost", 293 Official: false, 294 }, 295 RemoteName: "privatebase", 296 LocalName: "localhost/privatebase", 297 CanonicalName: "localhost/privatebase", 298 Official: false, 299 }, 300 IndexName + "/public/moonbase": { 301 Index: ®istrytypes.IndexInfo{ 302 Name: IndexName, 303 Official: true, 304 }, 305 RemoteName: "public/moonbase", 306 LocalName: "public/moonbase", 307 CanonicalName: "docker.io/public/moonbase", 308 Official: false, 309 }, 310 "index." + IndexName + "/public/moonbase": { 311 Index: ®istrytypes.IndexInfo{ 312 Name: IndexName, 313 Official: true, 314 }, 315 RemoteName: "public/moonbase", 316 LocalName: "public/moonbase", 317 CanonicalName: "docker.io/public/moonbase", 318 Official: false, 319 }, 320 "ubuntu-12.04-base": { 321 Index: ®istrytypes.IndexInfo{ 322 Name: IndexName, 323 Official: true, 324 }, 325 RemoteName: "library/ubuntu-12.04-base", 326 LocalName: "ubuntu-12.04-base", 327 CanonicalName: "docker.io/library/ubuntu-12.04-base", 328 Official: true, 329 }, 330 IndexName + "/ubuntu-12.04-base": { 331 Index: ®istrytypes.IndexInfo{ 332 Name: IndexName, 333 Official: true, 334 }, 335 RemoteName: "library/ubuntu-12.04-base", 336 LocalName: "ubuntu-12.04-base", 337 CanonicalName: "docker.io/library/ubuntu-12.04-base", 338 Official: true, 339 }, 340 "index." + IndexName + "/ubuntu-12.04-base": { 341 Index: ®istrytypes.IndexInfo{ 342 Name: IndexName, 343 Official: true, 344 }, 345 RemoteName: "library/ubuntu-12.04-base", 346 LocalName: "ubuntu-12.04-base", 347 CanonicalName: "docker.io/library/ubuntu-12.04-base", 348 Official: true, 349 }, 350 } 351 352 for reposName, expectedRepoInfo := range expectedRepoInfos { 353 named, err := reference.ParseNormalizedNamed(reposName) 354 if err != nil { 355 t.Error(err) 356 } 357 358 repoInfo, err := ParseRepositoryInfo(named) 359 if err != nil { 360 t.Error(err) 361 } else { 362 checkEqual(t, repoInfo.Index.Name, expectedRepoInfo.Index.Name, reposName) 363 checkEqual(t, reference.Path(repoInfo.Name), expectedRepoInfo.RemoteName, reposName) 364 checkEqual(t, reference.FamiliarName(repoInfo.Name), expectedRepoInfo.LocalName, reposName) 365 checkEqual(t, repoInfo.Name.Name(), expectedRepoInfo.CanonicalName, reposName) 366 checkEqual(t, repoInfo.Index.Official, expectedRepoInfo.Index.Official, reposName) 367 checkEqual(t, repoInfo.Official, expectedRepoInfo.Official, reposName) 368 } 369 } 370 } 371 372 func TestNewIndexInfo(t *testing.T) { 373 testIndexInfo := func(config *serviceConfig, expectedIndexInfos map[string]*registrytypes.IndexInfo) { 374 for indexName, expectedIndexInfo := range expectedIndexInfos { 375 index, err := newIndexInfo(config, indexName) 376 if err != nil { 377 t.Fatal(err) 378 } else { 379 checkEqual(t, index.Name, expectedIndexInfo.Name, indexName+" name") 380 checkEqual(t, index.Official, expectedIndexInfo.Official, indexName+" is official") 381 checkEqual(t, index.Secure, expectedIndexInfo.Secure, indexName+" is secure") 382 checkEqual(t, len(index.Mirrors), len(expectedIndexInfo.Mirrors), indexName+" mirrors") 383 } 384 } 385 } 386 387 config := emptyServiceConfig 388 var noMirrors []string 389 expectedIndexInfos := map[string]*registrytypes.IndexInfo{ 390 IndexName: { 391 Name: IndexName, 392 Official: true, 393 Secure: true, 394 Mirrors: noMirrors, 395 }, 396 "index." + IndexName: { 397 Name: IndexName, 398 Official: true, 399 Secure: true, 400 Mirrors: noMirrors, 401 }, 402 "example.com": { 403 Name: "example.com", 404 Official: false, 405 Secure: true, 406 Mirrors: noMirrors, 407 }, 408 "127.0.0.1:5000": { 409 Name: "127.0.0.1:5000", 410 Official: false, 411 Secure: false, 412 Mirrors: noMirrors, 413 }, 414 } 415 testIndexInfo(config, expectedIndexInfos) 416 417 publicMirrors := []string{"http://mirror1.local", "http://mirror2.local"} 418 var err error 419 config, err = makeServiceConfig(publicMirrors, []string{"example.com"}) 420 if err != nil { 421 t.Fatal(err) 422 } 423 424 expectedIndexInfos = map[string]*registrytypes.IndexInfo{ 425 IndexName: { 426 Name: IndexName, 427 Official: true, 428 Secure: true, 429 Mirrors: publicMirrors, 430 }, 431 "index." + IndexName: { 432 Name: IndexName, 433 Official: true, 434 Secure: true, 435 Mirrors: publicMirrors, 436 }, 437 "example.com": { 438 Name: "example.com", 439 Official: false, 440 Secure: false, 441 Mirrors: noMirrors, 442 }, 443 "example.com:5000": { 444 Name: "example.com:5000", 445 Official: false, 446 Secure: true, 447 Mirrors: noMirrors, 448 }, 449 "127.0.0.1": { 450 Name: "127.0.0.1", 451 Official: false, 452 Secure: false, 453 Mirrors: noMirrors, 454 }, 455 "127.0.0.1:5000": { 456 Name: "127.0.0.1:5000", 457 Official: false, 458 Secure: false, 459 Mirrors: noMirrors, 460 }, 461 "other.com": { 462 Name: "other.com", 463 Official: false, 464 Secure: true, 465 Mirrors: noMirrors, 466 }, 467 } 468 testIndexInfo(config, expectedIndexInfos) 469 470 config, err = makeServiceConfig(nil, []string{"42.42.0.0/16"}) 471 if err != nil { 472 t.Fatal(err) 473 } 474 expectedIndexInfos = map[string]*registrytypes.IndexInfo{ 475 "example.com": { 476 Name: "example.com", 477 Official: false, 478 Secure: false, 479 Mirrors: noMirrors, 480 }, 481 "example.com:5000": { 482 Name: "example.com:5000", 483 Official: false, 484 Secure: false, 485 Mirrors: noMirrors, 486 }, 487 "127.0.0.1": { 488 Name: "127.0.0.1", 489 Official: false, 490 Secure: false, 491 Mirrors: noMirrors, 492 }, 493 "127.0.0.1:5000": { 494 Name: "127.0.0.1:5000", 495 Official: false, 496 Secure: false, 497 Mirrors: noMirrors, 498 }, 499 "other.com": { 500 Name: "other.com", 501 Official: false, 502 Secure: true, 503 Mirrors: noMirrors, 504 }, 505 } 506 testIndexInfo(config, expectedIndexInfos) 507 } 508 509 func TestMirrorEndpointLookup(t *testing.T) { 510 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 511 containsMirror := func(endpoints []APIEndpoint) bool { 512 for _, pe := range endpoints { 513 if pe.URL.Host == "my.mirror" { 514 return true 515 } 516 } 517 return false 518 } 519 cfg, err := makeServiceConfig([]string{"https://my.mirror"}, nil) 520 if err != nil { 521 t.Fatal(err) 522 } 523 s := DefaultService{config: cfg} 524 525 imageName, err := reference.WithName(IndexName + "/test/image") 526 if err != nil { 527 t.Error(err) 528 } 529 pushAPIEndpoints, err := s.LookupPushEndpoints(reference.Domain(imageName)) 530 if err != nil { 531 t.Fatal(err) 532 } 533 if containsMirror(pushAPIEndpoints) { 534 t.Fatal("Push endpoint should not contain mirror") 535 } 536 537 pullAPIEndpoints, err := s.LookupPullEndpoints(reference.Domain(imageName)) 538 if err != nil { 539 t.Fatal(err) 540 } 541 if !containsMirror(pullAPIEndpoints) { 542 t.Fatal("Pull endpoint should contain mirror") 543 } 544 } 545 546 func TestSearchRepositories(t *testing.T) { 547 r := spawnTestRegistrySession(t) 548 results, err := r.SearchRepositories("fakequery", 25) 549 if err != nil { 550 t.Fatal(err) 551 } 552 if results == nil { 553 t.Fatal("Expected non-nil SearchResults object") 554 } 555 assertEqual(t, results.NumResults, 1, "Expected 1 search results") 556 assertEqual(t, results.Query, "fakequery", "Expected 'fakequery' as query") 557 assertEqual(t, results.Results[0].StarCount, 42, "Expected 'fakeimage' to have 42 stars") 558 } 559 560 func TestTrustedLocation(t *testing.T) { 561 for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} { 562 req, _ := http.NewRequest(http.MethodGet, url, nil) 563 assert.Check(t, !trustedLocation(req)) 564 } 565 566 for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} { 567 req, _ := http.NewRequest(http.MethodGet, url, nil) 568 assert.Check(t, trustedLocation(req)) 569 } 570 } 571 572 func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) { 573 for _, urls := range [][]string{ 574 {"http://docker.io", "https://docker.com"}, 575 {"https://foo.docker.io:7777", "http://bar.docker.com"}, 576 {"https://foo.docker.io", "https://example.com"}, 577 } { 578 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 579 reqFrom.Header.Add("Content-Type", "application/json") 580 reqFrom.Header.Add("Authorization", "super_secret") 581 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 582 583 addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 584 585 if len(reqTo.Header) != 1 { 586 t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header)) 587 } 588 589 if reqTo.Header.Get("Content-Type") != "application/json" { 590 t.Fatal("'Content-Type' should be 'application/json'") 591 } 592 593 if reqTo.Header.Get("Authorization") != "" { 594 t.Fatal("'Authorization' should be empty") 595 } 596 } 597 598 for _, urls := range [][]string{ 599 {"https://docker.io", "https://docker.com"}, 600 {"https://foo.docker.io:7777", "https://bar.docker.com"}, 601 } { 602 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 603 reqFrom.Header.Add("Content-Type", "application/json") 604 reqFrom.Header.Add("Authorization", "super_secret") 605 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 606 607 addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 608 609 if len(reqTo.Header) != 2 { 610 t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header)) 611 } 612 613 if reqTo.Header.Get("Content-Type") != "application/json" { 614 t.Fatal("'Content-Type' should be 'application/json'") 615 } 616 617 if reqTo.Header.Get("Authorization") != "super_secret" { 618 t.Fatal("'Authorization' should be 'super_secret'") 619 } 620 } 621 } 622 623 func TestAllowNondistributableArtifacts(t *testing.T) { 624 tests := []struct { 625 addr string 626 registries []string 627 expected bool 628 }{ 629 {IndexName, nil, false}, 630 {"example.com", []string{}, false}, 631 {"example.com", []string{"example.com"}, true}, 632 {"localhost", []string{"localhost:5000"}, false}, 633 {"localhost:5000", []string{"localhost:5000"}, true}, 634 {"localhost", []string{"example.com"}, false}, 635 {"127.0.0.1:5000", []string{"127.0.0.1:5000"}, true}, 636 {"localhost", nil, false}, 637 {"localhost:5000", nil, false}, 638 {"127.0.0.1", nil, false}, 639 {"localhost", []string{"example.com"}, false}, 640 {"127.0.0.1", []string{"example.com"}, false}, 641 {"example.com", nil, false}, 642 {"example.com", []string{"example.com"}, true}, 643 {"127.0.0.1", []string{"example.com"}, false}, 644 {"127.0.0.1:5000", []string{"example.com"}, false}, 645 {"example.com:5000", []string{"42.42.0.0/16"}, true}, 646 {"example.com", []string{"42.42.0.0/16"}, true}, 647 {"example.com:5000", []string{"42.42.42.42/8"}, true}, 648 {"127.0.0.1:5000", []string{"127.0.0.0/8"}, true}, 649 {"42.42.42.42:5000", []string{"42.1.1.1/8"}, true}, 650 {"invalid.domain.com", []string{"42.42.0.0/16"}, false}, 651 {"invalid.domain.com", []string{"invalid.domain.com"}, true}, 652 {"invalid.domain.com:5000", []string{"invalid.domain.com"}, false}, 653 {"invalid.domain.com:5000", []string{"invalid.domain.com:5000"}, true}, 654 } 655 for _, tt := range tests { 656 config, err := newServiceConfig(ServiceOptions{ 657 AllowNondistributableArtifacts: tt.registries, 658 }) 659 if err != nil { 660 t.Error(err) 661 } 662 if v := allowNondistributableArtifacts(config, tt.addr); v != tt.expected { 663 t.Errorf("allowNondistributableArtifacts failed for %q %v, expected %v got %v", tt.addr, tt.registries, tt.expected, v) 664 } 665 } 666 } 667 668 func TestIsSecureIndex(t *testing.T) { 669 tests := []struct { 670 addr string 671 insecureRegistries []string 672 expected bool 673 }{ 674 {IndexName, nil, true}, 675 {"example.com", []string{}, true}, 676 {"example.com", []string{"example.com"}, false}, 677 {"localhost", []string{"localhost:5000"}, false}, 678 {"localhost:5000", []string{"localhost:5000"}, false}, 679 {"localhost", []string{"example.com"}, false}, 680 {"127.0.0.1:5000", []string{"127.0.0.1:5000"}, false}, 681 {"localhost", nil, false}, 682 {"localhost:5000", nil, false}, 683 {"127.0.0.1", nil, false}, 684 {"localhost", []string{"example.com"}, false}, 685 {"127.0.0.1", []string{"example.com"}, false}, 686 {"example.com", nil, true}, 687 {"example.com", []string{"example.com"}, false}, 688 {"127.0.0.1", []string{"example.com"}, false}, 689 {"127.0.0.1:5000", []string{"example.com"}, false}, 690 {"example.com:5000", []string{"42.42.0.0/16"}, false}, 691 {"example.com", []string{"42.42.0.0/16"}, false}, 692 {"example.com:5000", []string{"42.42.42.42/8"}, false}, 693 {"127.0.0.1:5000", []string{"127.0.0.0/8"}, false}, 694 {"42.42.42.42:5000", []string{"42.1.1.1/8"}, false}, 695 {"invalid.domain.com", []string{"42.42.0.0/16"}, true}, 696 {"invalid.domain.com", []string{"invalid.domain.com"}, false}, 697 {"invalid.domain.com:5000", []string{"invalid.domain.com"}, true}, 698 {"invalid.domain.com:5000", []string{"invalid.domain.com:5000"}, false}, 699 } 700 for _, tt := range tests { 701 config, err := makeServiceConfig(nil, tt.insecureRegistries) 702 if err != nil { 703 t.Error(err) 704 } 705 if sec := isSecureIndex(config, tt.addr); sec != tt.expected { 706 t.Errorf("isSecureIndex failed for %q %v, expected %v got %v", tt.addr, tt.insecureRegistries, tt.expected, sec) 707 } 708 } 709 } 710 711 type debugTransport struct { 712 http.RoundTripper 713 log func(...interface{}) 714 } 715 716 func (tr debugTransport) RoundTrip(req *http.Request) (*http.Response, error) { 717 dump, err := httputil.DumpRequestOut(req, false) 718 if err != nil { 719 tr.log("could not dump request") 720 } 721 tr.log(string(dump)) 722 resp, err := tr.RoundTripper.RoundTrip(req) 723 if err != nil { 724 return nil, err 725 } 726 dump, err = httputil.DumpResponse(resp, false) 727 if err != nil { 728 tr.log("could not dump response") 729 } 730 tr.log(string(dump)) 731 return resp, err 732 }