github.com/skf/moby@v1.13.1/distribution/registry_unit_test.go (about)

     1  package distribution
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"net/url"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/Sirupsen/logrus"
    12  	"github.com/docker/docker/api/types"
    13  	registrytypes "github.com/docker/docker/api/types/registry"
    14  	"github.com/docker/docker/reference"
    15  	"github.com/docker/docker/registry"
    16  	"github.com/docker/docker/utils"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  const secretRegistryToken = "mysecrettoken"
    21  
    22  type tokenPassThruHandler struct {
    23  	reached       bool
    24  	gotToken      bool
    25  	shouldSend401 func(url string) bool
    26  }
    27  
    28  func (h *tokenPassThruHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    29  	h.reached = true
    30  	if strings.Contains(r.Header.Get("Authorization"), secretRegistryToken) {
    31  		logrus.Debug("Detected registry token in auth header")
    32  		h.gotToken = true
    33  	}
    34  	if h.shouldSend401 == nil || h.shouldSend401(r.RequestURI) {
    35  		w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`)
    36  		w.WriteHeader(401)
    37  	}
    38  }
    39  
    40  func testTokenPassThru(t *testing.T, ts *httptest.Server) {
    41  	tmp, err := utils.TestDirectory("")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	defer os.RemoveAll(tmp)
    46  
    47  	uri, err := url.Parse(ts.URL)
    48  	if err != nil {
    49  		t.Fatalf("could not parse url from test server: %v", err)
    50  	}
    51  
    52  	endpoint := registry.APIEndpoint{
    53  		Mirror:       false,
    54  		URL:          uri,
    55  		Version:      2,
    56  		Official:     false,
    57  		TrimHostname: false,
    58  		TLSConfig:    nil,
    59  		//VersionHeader: "verheader",
    60  	}
    61  	n, _ := reference.ParseNamed("testremotename")
    62  	repoInfo := &registry.RepositoryInfo{
    63  		Named: n,
    64  		Index: &registrytypes.IndexInfo{
    65  			Name:     "testrepo",
    66  			Mirrors:  nil,
    67  			Secure:   false,
    68  			Official: false,
    69  		},
    70  		Official: false,
    71  	}
    72  	imagePullConfig := &ImagePullConfig{
    73  		Config: Config{
    74  			MetaHeaders: http.Header{},
    75  			AuthConfig: &types.AuthConfig{
    76  				RegistryToken: secretRegistryToken,
    77  			},
    78  		},
    79  		Schema2Types: ImageTypes,
    80  	}
    81  	puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	p := puller.(*v2Puller)
    86  	ctx := context.Background()
    87  	p.repo, _, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  
    92  	logrus.Debug("About to pull")
    93  	// We expect it to fail, since we haven't mock'd the full registry exchange in our handler above
    94  	tag, _ := reference.WithTag(n, "tag_goes_here")
    95  	_ = p.pullV2Repository(ctx, tag)
    96  }
    97  
    98  func TestTokenPassThru(t *testing.T) {
    99  	handler := &tokenPassThruHandler{shouldSend401: func(url string) bool { return url == "/v2/" }}
   100  	ts := httptest.NewServer(handler)
   101  	defer ts.Close()
   102  
   103  	testTokenPassThru(t, ts)
   104  
   105  	if !handler.reached {
   106  		t.Fatal("Handler not reached")
   107  	}
   108  	if !handler.gotToken {
   109  		t.Fatal("Failed to receive registry token")
   110  	}
   111  }
   112  
   113  func TestTokenPassThruDifferentHost(t *testing.T) {
   114  	handler := new(tokenPassThruHandler)
   115  	ts := httptest.NewServer(handler)
   116  	defer ts.Close()
   117  
   118  	tsredirect := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   119  		if r.RequestURI == "/v2/" {
   120  			w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`)
   121  			w.WriteHeader(401)
   122  			return
   123  		}
   124  		http.Redirect(w, r, ts.URL+r.URL.Path, http.StatusMovedPermanently)
   125  	}))
   126  	defer tsredirect.Close()
   127  
   128  	testTokenPassThru(t, tsredirect)
   129  
   130  	if !handler.reached {
   131  		t.Fatal("Handler not reached")
   132  	}
   133  	if handler.gotToken {
   134  		t.Fatal("Redirect should not forward Authorization header to another host")
   135  	}
   136  }