func (ca *Cagent) CheckHubCredentials(ctx context.Context, fieldHubURL, fieldHubUser, fieldHubPassword string) error {
	ca.initHubClientOnce()
	err := ca.validateHubURL(fieldHubURL)
	if err != nil {
		return err
	}
	req, _ := http.NewRequest("HEAD", ca.Config.HubURL, nil)
	req.Header.Add("User-Agent", ca.userAgent())
	if len(ca.Config.HubUser) > 0 {
		req.SetBasicAuth(ca.Config.HubUser, ca.Config.HubPassword)
	}
	ctx, cancelFn := context.WithTimeout(ctx, time.Minute)
	req = req.WithContext(ctx)
	resp, err := ca.hubClient.Do(req)
	cancelFn()
	if err = ca.checkClientError(resp, err, fieldHubUser, fieldHubPassword); err != nil {
		return errors.WithStack(err)
	}
	return nil
}
CheckHubCredentials performs credentials check for a Hub config, returning errors that reference
field names as in source config. Since config may be filled from file or UI, the field names can be different.
Consider also localization of UI, we want to decouple credential checking logic from their actual view in UI.

Examples:
* for TOML: CheckHubCredentials(ctx, "hub_url", "hub_user", "hub_password")
* for WinUI: CheckHubCredentials(ctx, "URL", "User", "Password")
package cagent
import (
	"bytes"
	"compress/gzip"
	"context"
	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"github.com/cloudradar-monitoring/cagent/pkg/common"
	"github.com/cloudradar-monitoring/cagent/pkg/proxydetect"
)
func (ca *Cagent) initHubClientOnce() {
	ca.hubClientOnce.Do(func() {
		transport := *(http.DefaultTransport.(*http.Transport))
		transport.ResponseHeaderTimeout = 15 * time.Second
		rootCAs, err := common.CustomRootCertPool()
		if err != nil {
			if err != common.ErrorCustomRootCertPoolNotImplementedForOS {
				logrus.Errorf("failed to add root certs: %s", err.Error())
			}
		} else if rootCAs != nil {
			transport.TLSClientConfig = &tls.Config{
				RootCAs: rootCAs,
			}
		}
		transport.Proxy = proxydetect.GetProxyForRequest
		proxydetect.UserAgent = ca.userAgent()
		if len(ca.Config.HubProxy) > 0 {
			if !strings.HasPrefix(ca.Config.HubProxy, "http://") {
				ca.Config.HubProxy = "http://" + ca.Config.HubProxy
			}
			proxyURL, err := url.Parse(ca.Config.HubProxy)
			if err != nil {
				logrus.WithFields(logrus.Fields{
					"url": ca.Config.HubProxy,
				}).Warningln("failed to parse hub_proxy URL")
			} else {
				if len(ca.Config.HubProxyUser) > 0 {
					proxyURL.User = url.UserPassword(ca.Config.HubProxyUser, ca.Config.HubProxyPassword)
				}
				transport.Proxy = func(_ *http.Request) (*url.URL, error) {
					return proxyURL, nil
				}
			}
		}
		ca.hubClient = &http.Client{
			Timeout:   time.Duration(ca.Config.HubRequestTimeout) * time.Second,
			Transport: &transport,
		}
	})
}
func (ca *Cagent) validateHubURL(fieldHubURL string) error {
	if len(ca.Config.HubURL) == 0 {
		return newEmptyFieldError(fieldHubURL)
	} else if u, err := url.Parse(ca.Config.HubURL); err != nil {
		err = errors.WithStack(err)
		return newFieldError(fieldHubURL, err)
	} else if u.Scheme != "http" && u.Scheme != "https" {
		err := errors.Errorf("wrong scheme '%s', URL must start with http:// or https://", u.Scheme)
		return newFieldError(fieldHubURL, err)
	}
	return nil
}