示例#1
0
//Pull Image from Registry or Hub depending on image name
func Login(registry string) (bool, error) {

	logrus.Info("log in: ", registry)

	if strings.Contains(registry, "docker") {
		registry = "https://" + registry + "/v2"

	} else {
		registry = "http://" + registry + "/v2"
	}

	client := httpclient.Get()
	request, err := http.NewRequest("GET", registry, nil)
	response, err := client.Do(request)
	if err != nil {
		return false, fmt.Errorf("log in %v: %v", registry, err)
	}
	authorized := response.StatusCode != http.StatusUnauthorized
	if !authorized {
		logrus.Info("Unauthorized access")
		err := AuthenticateResponse(response, request)

		if err != nil {
			if err == xerrors.Unauthorized {
				authorized = false
			}
			return false, err
		} else {
			authorized = true
		}
	}

	return authorized, nil
}
示例#2
0
// NewReverseProxy returns a new ReverseProxy that load-balances the proxy requests between multiple hosts defined by the RegistryMapping in the database
// It also allows to define a chain of filter functions to process the outgoing response(s)
func NewReverseProxy(filters []FilterFunc) *ReverseProxy {
	director := func(request *http.Request) {

		inr := context.Get(request, "in_req").(*http.Request)
		host, _ := database.GetRegistryMapping(mux.Vars(inr)["digest"])
		out, _ := url.Parse(host)
		request.URL.Scheme = out.Scheme
		request.URL.Host = out.Host
		client := httpclient.Get()
		req, _ := http.NewRequest("HEAD", request.URL.String(), nil)
		resp, err := client.Do(req)
		if err != nil {
			logrus.Errorf("response error: %v", err)
			return
		}

		if resp.StatusCode == http.StatusUnauthorized {
			logrus.Info("pull from clair is unauthorized")
			docker.AuthenticateResponse(resp, request)
		}

		r, _ := http.NewRequest("GET", request.URL.String(), nil)
		r.Header.Set("Authorization", request.Header.Get("Authorization"))
		r.Header.Set("Accept-Encoding", request.Header.Get("Accept-Encoding"))
		*request = *r
	}

	return &ReverseProxy{
		Transport: moxy.NewTransport(),
		Director:  director,
		Filters:   filters,
	}
}
示例#3
0
//Pull Image from Registry or Hub depending on image name
func Pull(imageName string) (Image, error) {
	image, err := Parse(imageName)
	if err != nil {
		return Image{}, err
	}

	logrus.Info("pulling image: ", image)

	mURI := fmt.Sprintf("%v/%v/manifests/%v", image.Registry, image.Name, image.Tag)
	client := httpclient.Get()
	request, err := http.NewRequest("GET", mURI, nil)
	response, err := client.Do(request)
	if err != nil {
		return Image{}, fmt.Errorf("retrieving manifest: %v", err)
	}

	if response.StatusCode == http.StatusUnauthorized {
		logrus.Info("Pull is Unauthorized")
		err := AuthenticateResponse(response, request)

		if err != nil {
			return Image{}, fmt.Errorf("authenticating: %v", err)
		}
		response, err = client.Do(request)
		if err != nil {
			return Image{}, fmt.Errorf("retrieving manifest: %v", err)
		}
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return Image{}, fmt.Errorf("reading manifest body: %v", err)
	}
	if response.StatusCode != 200 {
		switch response.StatusCode {
		case http.StatusUnauthorized:
			return Image{}, xerrors.Unauthorized
		case http.StatusNotFound:
			return Image{}, xerrors.NotFound
		default:
			return Image{}, fmt.Errorf("%d - %s", response.StatusCode, string(body))
		}
	}
	if err := image.parseManifest(body); err != nil {
		return Image{}, fmt.Errorf("parsing manifest: %v", err)
	}

	return image, nil
}
示例#4
0
func AuthenticateResponse(dockerResponse *http.Response, request *http.Request) error {
	bearerToken := BearerAuthParams(dockerResponse)
	url := bearerToken["realm"] + "?service=" + bearerToken["service"]
	if bearerToken["scope"] != "" {
		url += "&scope=" + bearerToken["scope"]
	}
	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		return err
	}
	l, err := config.GetLogin(request.URL.Host)
	if err != nil {
		return err
	}
	req.SetBasicAuth(l.Username, l.Password)

	response, err := httpclient.Get().Do(req)

	if err != nil {
		return err
	}

	if response.StatusCode == http.StatusUnauthorized {
		return xerrors.Unauthorized
	}

	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("authentication server response: %v - %v", response.StatusCode, response.Status)
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)

	if err != nil {
		return err
	}

	var tok token
	err = json.Unmarshal(body, &tok)

	if err != nil {
		return err
	}
	request.Header.Set("Authorization", "Bearer "+tok.String())

	return nil
}
示例#5
0
func newSingleHostReverseProxy() *httputil.ReverseProxy {
	director := func(request *http.Request) {

		var validID = regexp.MustCompile(`.*/blobs/(.*)$`)
		u := request.URL.Path
		logrus.Debugf("request url: %v", u)
		if !validID.MatchString(u) {
			logrus.Errorf("cannot parse url: %v", u)
		}

		host, _ := database.GetRegistryMapping(validID.FindStringSubmatch(u)[1])
		out, _ := url.Parse(host)
		request.URL.Scheme = out.Scheme
		request.URL.Host = out.Host
		client := httpclient.Get()
		req, _ := http.NewRequest("HEAD", request.URL.String(), nil)
		resp, err := client.Do(req)
		if err != nil {
			logrus.Errorf("response error: %v", err)
			return
		}

		if resp.StatusCode == http.StatusUnauthorized {
			logrus.Info("pull from clair is unauthorized")
			docker.AuthenticateResponse(resp, request)
		}

		r, _ := http.NewRequest("GET", request.URL.String(), nil)
		r.Header.Set("Authorization", request.Header.Get("Authorization"))
		r.Header.Set("Accept-Encoding", request.Header.Get("Accept-Encoding"))
		*request = *r
	}
	return &httputil.ReverseProxy{
		Director: director,
	}
}
示例#6
0
		encryptedPwd, err := bcrypt.GenerateFromPassword(pwd, 5)
		if err != nil {
			fmt.Println(xerrors.InternalError)
			logrus.Fatalf("encrypting password: %v", err)
		}
		usr.Password = string(encryptedPwd)

		users[reg] = usr

		s, err := xstrings.ToIndentJSON(users)
		if err != nil {
			fmt.Println(xerrors.InternalError)
			logrus.Fatalf("indenting login: %v", err)
		}
		ioutil.WriteFile(config.HyperclairConfig(), s, os.ModePerm)
		client := httpclient.Get()
		req, err := http.NewRequest("GET", HyperclairURI+"/login?realm="+reg, nil)
		if err != nil {
			fmt.Println(xerrors.InternalError)
			logrus.Fatalf("creating login request: %v", err)
		}
		req.SetBasicAuth(usr.Username, string(pwd))

		resp, err := client.Do(req)
		if err != nil || (resp.StatusCode != http.StatusUnauthorized && resp.StatusCode != http.StatusOK) {
			fmt.Println(xerrors.InternalError)
			logrus.Fatalf("log in: %v", err)
		}

		if resp.StatusCode == http.StatusUnauthorized {
			fmt.Println("Unauthorized: Wrong login/password, please try again")