123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- package registry // import "github.com/docker/docker/registry"
- import (
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
- "github.com/docker/docker/api/types/registry"
- "gotest.tools/v3/assert"
- is "gotest.tools/v3/assert/cmp"
- )
- func TestV1EndpointPing(t *testing.T) {
- testPing := func(index *registry.IndexInfo, expectedStandalone bool, assertMessage string) {
- ep, err := newV1Endpoint(index, nil)
- if err != nil {
- t.Fatal(err)
- }
- regInfo, err := ep.ping()
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, regInfo.Standalone, expectedStandalone, assertMessage)
- }
- testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)")
- testPing(makeHTTPSIndex("/v1/"), true, "Expected standalone to be true (default)")
- testPing(makePublicIndex(), false, "Expected standalone to be false for public index")
- }
- func TestV1Endpoint(t *testing.T) {
- // Simple wrapper to fail test if err != nil
- expandEndpoint := func(index *registry.IndexInfo) *v1Endpoint {
- endpoint, err := newV1Endpoint(index, nil)
- if err != nil {
- t.Fatal(err)
- }
- return endpoint
- }
- assertInsecureIndex := func(index *registry.IndexInfo) {
- index.Secure = true
- _, err := newV1Endpoint(index, nil)
- assert.ErrorContains(t, err, "insecure-registry", index.Name+": Expected insecure-registry error for insecure index")
- index.Secure = false
- }
- assertSecureIndex := func(index *registry.IndexInfo) {
- index.Secure = true
- _, err := newV1Endpoint(index, nil)
- assert.ErrorContains(t, err, "certificate signed by unknown authority", index.Name+": Expected cert error for secure index")
- index.Secure = false
- }
- index := ®istry.IndexInfo{}
- index.Name = makeURL("/v1/")
- endpoint := expandEndpoint(index)
- assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
- assertInsecureIndex(index)
- index.Name = makeURL("")
- endpoint = expandEndpoint(index)
- assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
- assertInsecureIndex(index)
- httpURL := makeURL("")
- index.Name = strings.SplitN(httpURL, "://", 2)[1]
- endpoint = expandEndpoint(index)
- assert.Equal(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/")
- assertInsecureIndex(index)
- index.Name = makeHTTPSURL("/v1/")
- endpoint = expandEndpoint(index)
- assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
- assertSecureIndex(index)
- index.Name = makeHTTPSURL("")
- endpoint = expandEndpoint(index)
- assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
- assertSecureIndex(index)
- httpsURL := makeHTTPSURL("")
- index.Name = strings.SplitN(httpsURL, "://", 2)[1]
- endpoint = expandEndpoint(index)
- assert.Equal(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/")
- assertSecureIndex(index)
- badEndpoints := []string{
- "http://127.0.0.1/v1/",
- "https://127.0.0.1/v1/",
- "http://127.0.0.1",
- "https://127.0.0.1",
- "127.0.0.1",
- }
- for _, address := range badEndpoints {
- index.Name = address
- _, err := newV1Endpoint(index, nil)
- assert.Check(t, err != nil, "Expected error while expanding bad endpoint: %s", address)
- }
- }
- func TestV1EndpointParse(t *testing.T) {
- tests := []struct {
- address string
- expected string
- expectedErr string
- }{
- {
- address: IndexServer,
- expected: IndexServer,
- },
- {
- address: "https://0.0.0.0:5000/v1/",
- expected: "https://0.0.0.0:5000/v1/",
- },
- {
- address: "https://0.0.0.0:5000",
- expected: "https://0.0.0.0:5000/v1/",
- },
- {
- address: "0.0.0.0:5000",
- expected: "https://0.0.0.0:5000/v1/",
- },
- {
- address: "https://0.0.0.0:5000/nonversion/",
- expected: "https://0.0.0.0:5000/nonversion/v1/",
- },
- {
- address: "https://0.0.0.0:5000/v0/",
- expected: "https://0.0.0.0:5000/v0/v1/",
- },
- {
- address: "https://0.0.0.0:5000/v2/",
- expectedErr: "search is not supported on v2 endpoints: https://0.0.0.0:5000/v2/",
- },
- }
- for _, tc := range tests {
- tc := tc
- t.Run(tc.address, func(t *testing.T) {
- ep, err := newV1EndpointFromStr(tc.address, nil, nil)
- if tc.expectedErr != "" {
- assert.Check(t, is.Error(err, tc.expectedErr))
- assert.Check(t, is.Nil(ep))
- } else {
- assert.NilError(t, err)
- assert.Check(t, is.Equal(ep.String(), tc.expected))
- }
- })
- }
- }
- // Ensure that a registry endpoint that responds with a 401 only is determined
- // to be a valid v1 registry endpoint
- func TestV1EndpointValidate(t *testing.T) {
- requireBasicAuthHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("WWW-Authenticate", `Basic realm="localhost"`)
- w.WriteHeader(http.StatusUnauthorized)
- })
- // Make a test server which should validate as a v1 server.
- testServer := httptest.NewServer(requireBasicAuthHandler)
- defer testServer.Close()
- testEndpoint, err := newV1Endpoint(®istry.IndexInfo{Name: testServer.URL}, nil)
- if err != nil {
- t.Fatal(err)
- }
- if testEndpoint.URL.Scheme != "http" {
- t.Fatalf("expecting to validate endpoint as http, got url %s", testEndpoint.String())
- }
- }
- func TestTrustedLocation(t *testing.T) {
- for _, u := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} {
- req, _ := http.NewRequest(http.MethodGet, u, nil)
- assert.Check(t, !trustedLocation(req))
- }
- for _, u := range []string{"https://docker.io", "https://test.docker.com:80"} {
- req, _ := http.NewRequest(http.MethodGet, u, nil)
- assert.Check(t, trustedLocation(req))
- }
- }
- func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
- for _, urls := range [][]string{
- {"http://docker.io", "https://docker.com"},
- {"https://foo.docker.io:7777", "http://bar.docker.com"},
- {"https://foo.docker.io", "https://example.com"},
- } {
- reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil)
- reqFrom.Header.Add("Content-Type", "application/json")
- reqFrom.Header.Add("Authorization", "super_secret")
- reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil)
- _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
- if len(reqTo.Header) != 1 {
- t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header))
- }
- if reqTo.Header.Get("Content-Type") != "application/json" {
- t.Fatal("'Content-Type' should be 'application/json'")
- }
- if reqTo.Header.Get("Authorization") != "" {
- t.Fatal("'Authorization' should be empty")
- }
- }
- for _, urls := range [][]string{
- {"https://docker.io", "https://docker.com"},
- {"https://foo.docker.io:7777", "https://bar.docker.com"},
- } {
- reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil)
- reqFrom.Header.Add("Content-Type", "application/json")
- reqFrom.Header.Add("Authorization", "super_secret")
- reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil)
- _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
- if len(reqTo.Header) != 2 {
- t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header))
- }
- if reqTo.Header.Get("Content-Type") != "application/json" {
- t.Fatal("'Content-Type' should be 'application/json'")
- }
- if reqTo.Header.Get("Authorization") != "super_secret" {
- t.Fatal("'Authorization' should be 'super_secret'")
- }
- }
- }
|