internal/app/http_client.go (82 lines of code) (raw):

package app import ( "crypto/tls" "crypto/x509" "errors" "fmt" "net/http" "os" "path/filepath" "runtime" "strings" securejoin "github.com/cyphar/filepath-securejoin" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" "gitlab.com/gitlab-org/release-cli/internal/flags" "gitlab.com/gitlab-org/release-cli/internal/gitlab" ) func newHTTPClient(ctx *cli.Context, log logrus.FieldLogger) (gitlab.HTTPClient, error) { extraCA := ctx.String(flags.AdditionalCACertBundle) rootCAs, err := x509.SystemCertPool() if err != nil { // SystemCertPool is not supported on Windows, safe to call x509.NewCertPool() below if runtime.GOOS != "windows" { return nil, fmt.Errorf("getting system cert pool: %w", err) } rootCAs = x509.NewCertPool() } if extraCA != "" { if err := loadExtraCACert(rootCAs, extraCA, log); err != nil { return nil, err } } transport := http.DefaultTransport.(*http.Transport).Clone() transport.TLSClientConfig = &tls.Config{ // nolint: gosec // G402: TLS InsecureSkipVerify may be true // set to true at your own risk InsecureSkipVerify: ctx.Bool(flags.InsecureHTTPS), RootCAs: rootCAs, } return &http.Client{ Timeout: ctx.Duration(flags.Timeout), Transport: transport, }, nil } func loadExtraCACert(rootCAs *x509.CertPool, ca string, log logrus.FieldLogger) error { l := log.WithFields(logrus.Fields{ flags.AdditionalCACertBundle: ca, }) caBytes, err := getCA(ca) if err != nil { return err } // Append our cert to the system pool if ok := rootCAs.AppendCertsFromPEM(caBytes); !ok { l.Warn("No certs appended, using system certs only") } return nil } func getCA(ca string) ([]byte, error) { // If a new line is found it means that we were given a CA block rather than a path. if strings.ContainsRune(ca, '\n') { return []byte(ca), nil } baseDir, err := os.Getwd() if err != nil { return nil, err } filePath, err := securejoin.SecureJoin(baseDir, ca) if err != nil { return nil, err } if _, statErr := os.Stat(filePath); errors.Is(statErr, os.ErrNotExist) { buildsDir := os.Getenv("CI_BUILDS_DIR") if buildsDir == "" { return nil, statErr } rel, err := filepath.Rel(buildsDir, ca) if err != nil { return nil, err } filePath, err = securejoin.SecureJoin(buildsDir, rel) if err != nil { return nil, err } } return os.ReadFile(filepath.Clean(filePath)) }