Example #1
0
func (graph *Graph) getHttpClient() *http.Client {
	if graph.httpClient == nil {
		graph.httpClient = &http.Client{}
		graph.httpClient.Jar = cookiejar.NewCookieJar()
	}
	return graph.httpClient
}
Example #2
0
func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
	config := &auth.AuthConfig{}
	if err := json.NewDecoder(r.Body).Decode(config); err != nil {
		return nil, err
	}

	if config.Username == srv.runtime.authConfig.Username {
		config.Password = srv.runtime.authConfig.Password
	}

	newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
	status, err := auth.Login(newAuthConfig)
	if err != nil {
		return nil, err
	} else {
		srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar()
		srv.runtime.authConfig = newAuthConfig
	}
	if status != "" {
		b, err := json.Marshal(&ApiAuth{Status: status})
		if err != nil {
			return nil, err
		}
		return b, nil
	}
	w.WriteHeader(http.StatusNoContent)
	return nil, nil
}
Example #3
0
func NewRegistry(root string) *Registry {
	// If the auth file does not exist, keep going
	authConfig, _ := auth.LoadConfig(root)

	r := &Registry{
		authConfig: authConfig,
		client:     &http.Client{},
	}
	r.client.Jar = cookiejar.NewCookieJar()
	return r
}
Example #4
0
func NewRegistry(root string, authConfig *auth.AuthConfig) *Registry {
	httpTransport := &http.Transport{
		DisableKeepAlives: true,
		Proxy:             http.ProxyFromEnvironment,
	}

	r := &Registry{
		authConfig: authConfig,
		client: &http.Client{
			Transport: httpTransport,
		},
	}
	r.client.Jar = cookiejar.NewCookieJar()
	return r
}
Example #5
0
func NewRegistry(root string) *Registry {
	// If the auth file does not exist, keep going
	authConfig, _ := auth.LoadConfig(root)

	httpTransport := &http.Transport{
		DisableKeepAlives: true,
		Proxy:             http.ProxyFromEnvironment,
	}

	r := &Registry{
		authConfig: authConfig,
		client: &http.Client{
			Transport: httpTransport,
		},
	}
	r.client.Jar = cookiejar.NewCookieJar()
	return r
}
Example #6
0
func (r *Registry) ResetClient(authConfig *auth.AuthConfig) {
	r.authConfig = authConfig
	r.client.Jar = cookiejar.NewCookieJar()
}
Example #7
0
// 'docker login': login / register a user to registry service.
func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error {
	// Read a line on raw terminal with support for simple backspace
	// sequences and echo.
	//
	// This function is necessary because the login command must be done in a
	// raw terminal for two reasons:
	// - we have to read a password (without echoing it);
	// - the rcli "protocol" only supports cannonical and raw modes and you
	//   can't tune it once the command as been started.
	var readStringOnRawTerminal = func(stdin io.Reader, stdout io.Writer, echo bool) string {
		char := make([]byte, 1)
		buffer := make([]byte, 64)
		var i = 0
		for i < len(buffer) {
			n, err := stdin.Read(char)
			if n > 0 {
				if char[0] == '\r' || char[0] == '\n' {
					stdout.Write([]byte{'\r', '\n'})
					break
				} else if char[0] == 127 || char[0] == '\b' {
					if i > 0 {
						if echo {
							stdout.Write([]byte{'\b', ' ', '\b'})
						}
						i--
					}
				} else if !unicode.IsSpace(rune(char[0])) &&
					!unicode.IsControl(rune(char[0])) {
					if echo {
						stdout.Write(char)
					}
					buffer[i] = char[0]
					i++
				}
			}
			if err != nil {
				if err != io.EOF {
					fmt.Fprintf(stdout, "Read error: %v\r\n", err)
				}
				break
			}
		}
		return string(buffer[:i])
	}
	var readAndEchoString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, true)
	}
	var readString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, false)
	}

	stdout.SetOptionRawTerminal()

	cmd := rcli.Subcmd(stdout, "login", "", "Register or Login to the docker registry server")
	if err := cmd.Parse(args); err != nil {
		return nil
	}

	var username string
	var password string
	var email string

	fmt.Fprint(stdout, "Username (", srv.runtime.authConfig.Username, "): ")
	username = readAndEchoString(stdin, stdout)
	if username == "" {
		username = srv.runtime.authConfig.Username
	}
	if username != srv.runtime.authConfig.Username {
		fmt.Fprint(stdout, "Password: "******"" {
			return fmt.Errorf("Error : Password Required")
		}

		fmt.Fprint(stdout, "Email (", srv.runtime.authConfig.Email, "): ")
		email = readAndEchoString(stdin, stdout)
		if email == "" {
			email = srv.runtime.authConfig.Email
		}
	} else {
		password = srv.runtime.authConfig.Password
		email = srv.runtime.authConfig.Email
	}
	newAuthConfig := auth.NewAuthConfig(username, password, email, srv.runtime.root)
	status, err := auth.Login(newAuthConfig)
	if err != nil {
		fmt.Fprintf(stdout, "Error: %s\r\n", err)
	} else {
		srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar()
		srv.runtime.authConfig = newAuthConfig
	}
	if status != "" {
		fmt.Fprint(stdout, status)
	}
	return nil
}
Example #8
0
// Push a repository to the registry.
// Remote has the format '<user>/<repo>
func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Repository, authConfig *auth.AuthConfig) error {
	client := graph.getHttpClient()
	// FIXME: Do not reset the cookie each time? (need to reset it in case updating latest of a repo and repushing)
	client.Jar = cookiejar.NewCookieJar()
	var imgList []*ImgListJson

	fmt.Fprintf(stdout, "Processing checksums\n")
	imageSet := make(map[string]struct{})

	for tag, id := range localRepo {
		img, err := graph.Get(id)
		if err != nil {
			return err
		}
		img.WalkHistory(func(img *Image) error {
			if _, exists := imageSet[img.Id]; exists {
				return nil
			}
			imageSet[img.Id] = struct{}{}
			checksum, err := graph.getChecksum(img.Id)
			if err != nil {
				return err
			}
			imgList = append([]*ImgListJson{{
				Id:       img.Id,
				Checksum: checksum,
				tag:      tag,
			}}, imgList...)
			return nil
		})
	}

	imgListJson, err := json.Marshal(imgList)
	if err != nil {
		return err
	}

	Debugf("json sent: %s\n", imgListJson)

	fmt.Fprintf(stdout, "Sending image list\n")
	req, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote+"/", bytes.NewReader(imgListJson))
	if err != nil {
		return err
	}
	req.SetBasicAuth(authConfig.Username, authConfig.Password)
	req.ContentLength = int64(len(imgListJson))
	req.Header.Set("X-Docker-Token", "true")

	res, err := client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	for res.StatusCode >= 300 && res.StatusCode < 400 {
		Debugf("Redirected to %s\n", res.Header.Get("Location"))
		req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJson))
		if err != nil {
			return err
		}
		req.SetBasicAuth(authConfig.Username, authConfig.Password)
		req.ContentLength = int64(len(imgListJson))
		req.Header.Set("X-Docker-Token", "true")

		res, err = client.Do(req)
		if err != nil {
			return err
		}
		defer res.Body.Close()
	}

	if res.StatusCode != 200 && res.StatusCode != 201 {
		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		return fmt.Errorf("Error: Status %d trying to push repository %s: %s", res.StatusCode, remote, errBody)
	}

	var token, endpoints []string
	if res.Header.Get("X-Docker-Token") != "" {
		token = res.Header["X-Docker-Token"]
		Debugf("Auth token: %v", token)
	} else {
		return fmt.Errorf("Index response didn't contain an access token")
	}
	if res.Header.Get("X-Docker-Endpoints") != "" {
		endpoints = res.Header["X-Docker-Endpoints"]
	} else {
		return fmt.Errorf("Index response didn't contain any endpoints")
	}

	// FIXME: Send only needed images
	for _, registry := range endpoints {
		fmt.Fprintf(stdout, "Pushing repository %s to %s (%d tags)\r\n", remote, registry, len(localRepo))
		// For each image within the repo, push them
		for _, elem := range imgList {
			if err := graph.pushPrimitive(stdout, remote, elem.tag, elem.Id, registry, token); err != nil {
				// FIXME: Continue on error?
				return err
			}
		}
	}

	req2, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote+"/images", bytes.NewReader(imgListJson))
	if err != nil {
		return err
	}
	req2.SetBasicAuth(authConfig.Username, authConfig.Password)
	req2.Header["X-Docker-Endpoints"] = endpoints
	req2.ContentLength = int64(len(imgListJson))
	res2, err := client.Do(req2)
	if err != nil {
		return err
	}
	defer res2.Body.Close()
	if res2.StatusCode != 204 {
		if errBody, err := ioutil.ReadAll(res2.Body); err != nil {
			return err
		} else {
			return fmt.Errorf("Error: Status %d trying to push checksums %s: %s", res2.StatusCode, remote, errBody)
		}
	}

	return nil
}