Use basic auth for private registries when over HTTPS.

RequestFactory is no longer a singleton (can be different for different instances of Registry)
Registry now has an indexEndpoint member
Registry methods that needed the indexEndpoint parameter no longer do so
Registry methods will only use token auth where applicable if basic auth is not enabled.
This commit is contained in:
shin- 2013-10-22 20:49:13 +02:00
parent a7b957f06f
commit 097f41245a
2 changed files with 51 additions and 20 deletions

View file

@ -160,7 +160,9 @@ func (r *Registry) GetRemoteHistory(imgID, registry string, token []string) ([]s
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return nil, err
@ -193,7 +195,9 @@ func (r *Registry) LookupRemoteImage(imgID, registry string, token []string) boo
if err != nil {
return false
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return false
@ -209,7 +213,9 @@ func (r *Registry) GetRemoteImageJSON(imgID, registry string, token []string) ([
if err != nil {
return nil, -1, fmt.Errorf("Failed to download json: %s", err)
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return nil, -1, fmt.Errorf("Failed to download json: %s", err)
@ -236,7 +242,9 @@ func (r *Registry) GetRemoteImageLayer(imgID, registry string, token []string) (
if err != nil {
return nil, fmt.Errorf("Error while getting from the server: %s\n", err)
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return nil, err
@ -262,7 +270,9 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return nil, err
@ -290,7 +300,8 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [
return nil, fmt.Errorf("Could not reach any registry endpoint")
}
func (r *Registry) GetRepositoryData(indexEp, remote string) (*RepositoryData, error) {
func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) {
indexEp := r.indexEndpoint
repositoryTarget := fmt.Sprintf("%srepositories/%s/images", indexEp, remote)
utils.Debugf("[registry] Calling GET %s", repositoryTarget)
@ -364,7 +375,9 @@ func (r *Registry) PushImageChecksumRegistry(imgData *ImgData, registry string,
if err != nil {
return err
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
req.Header.Set("X-Docker-Checksum", imgData.Checksum)
res, err := doWithCookies(r.client, req)
@ -401,7 +414,9 @@ func (r *Registry) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regis
return err
}
req.Header.Add("Content-type", "application/json")
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
@ -436,7 +451,9 @@ func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registr
}
req.ContentLength = -1
req.TransferEncoding = []string{"chunked"}
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
res, err := doWithCookies(r.client, req)
if err != nil {
return "", fmt.Errorf("Failed to upload layer: %s", err)
@ -465,7 +482,9 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token
return err
}
req.Header.Add("Content-type", "application/json")
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
if req.Header.Get("Authorization") == "" { // Don't override
req.Header.Set("Authorization", "Token "+strings.Join(token, ","))
}
req.ContentLength = int64(len(revision))
res, err := doWithCookies(r.client, req)
if err != nil {
@ -478,8 +497,9 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token
return nil
}
func (r *Registry) PushImageJSONIndex(indexEp, remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) {
func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) {
cleanImgList := []*ImgData{}
indexEp := r.indexEndpoint
if validate {
for _, elem := range imgList {
@ -583,6 +603,7 @@ func (r *Registry) PushImageJSONIndex(indexEp, remote string, imgList []*ImgData
}
func (r *Registry) SearchRepositories(term string) (*SearchResults, error) {
utils.Debugf("Index server: %s", r.indexEndpoint)
u := auth.IndexServerAddress() + "search?q=" + url.QueryEscape(term)
req, err := r.reqFactory.NewRequest("GET", u, nil)
if err != nil {
@ -644,12 +665,13 @@ type ImgData struct {
}
type Registry struct {
client *http.Client
authConfig *auth.AuthConfig
reqFactory *utils.HTTPRequestFactory
client *http.Client
authConfig *auth.AuthConfig
reqFactory *utils.HTTPRequestFactory
indexEndpoint string
}
func NewRegistry(root string, authConfig *auth.AuthConfig, factory *utils.HTTPRequestFactory) (r *Registry, err error) {
func NewRegistry(authConfig *auth.AuthConfig, factory *utils.HTTPRequestFactory, indexEndpoint string) (r *Registry, err error) {
httpTransport := &http.Transport{
DisableKeepAlives: true,
Proxy: http.ProxyFromEnvironment,
@ -660,12 +682,22 @@ func NewRegistry(root string, authConfig *auth.AuthConfig, factory *utils.HTTPRe
client: &http.Client{
Transport: httpTransport,
},
indexEndpoint: indexEndpoint,
}
r.client.Jar, err = cookiejar.New(nil)
if err != nil {
return nil, err
}
// If we're working with a private registry over HTTPS, send Basic Auth headers
// alongside our requests.
if indexEndpoint != auth.IndexServerAddress() && strings.HasPrefix(indexEndpoint, "https://") {
utils.Debugf("Endpoint %s is eligible for private registry auth. Enabling decorator.", indexEndpoint)
dec := utils.NewHTTPAuthDecorator(authConfig.Username, authConfig.Password)
factory.AddDecorator(dec)
}
r.reqFactory = factory
return r, nil
}

View file

@ -15,7 +15,7 @@ var (
func spawnTestRegistry(t *testing.T) *Registry {
authConfig := &auth.AuthConfig{}
r, err := NewRegistry("", authConfig, utils.NewHTTPRequestFactory())
r, err := NewRegistry(authConfig, utils.NewHTTPRequestFactory(), makeURL("/v1/"))
if err != nil {
t.Fatal(err)
}
@ -99,7 +99,7 @@ func TestGetRemoteTags(t *testing.T) {
func TestGetRepositoryData(t *testing.T) {
r := spawnTestRegistry(t)
data, err := r.GetRepositoryData(makeURL("/v1/"), "foo42/bar")
data, err := r.GetRepositoryData("foo42/bar")
if err != nil {
t.Fatal(err)
}
@ -168,15 +168,14 @@ func TestPushImageJSONIndex(t *testing.T) {
Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2",
},
}
ep := makeURL("/v1/")
repoData, err := r.PushImageJSONIndex(ep, "foo42/bar", imgData, false, nil)
repoData, err := r.PushImageJSONIndex("foo42/bar", imgData, false, nil)
if err != nil {
t.Fatal(err)
}
if repoData == nil {
t.Fatal("Expected RepositoryData object")
}
repoData, err = r.PushImageJSONIndex(ep, "foo42/bar", imgData, true, []string{ep})
repoData, err = r.PushImageJSONIndex("foo42/bar", imgData, true, []string{r.indexEndpoint})
if err != nil {
t.Fatal(err)
}