mirror of https://github.com/portainer/portainer
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package registryhttp
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"oras.land/oras-go/v2/registry/remote/retry"
|
|
)
|
|
|
|
// CreateClient creates an HTTP client with appropriate TLS configuration based on registry type.
|
|
// All registries use retry clients for better resilience.
|
|
// Returns the HTTP client, whether to use plainHTTP, and any error.
|
|
func CreateClient(registry *portainer.Registry) (httpClient *http.Client, usePlainHttp bool, err error) {
|
|
switch registry.Type {
|
|
case portainer.AzureRegistry, portainer.EcrRegistry, portainer.GithubRegistry, portainer.GitlabRegistry, portainer.DockerHubRegistry:
|
|
// Cloud registries use the default retry client with built-in TLS
|
|
return retry.DefaultClient, false, nil
|
|
default:
|
|
// For all other registry types, use shared helper to build transport and scheme
|
|
|
|
// if no management configuration, treat as plain HTTP for custom registries
|
|
hasConfiguration := registry.ManagementConfiguration != nil
|
|
if !hasConfiguration {
|
|
return retry.DefaultClient, true, nil
|
|
}
|
|
|
|
tlsCfg := registry.ManagementConfiguration.TLSConfig
|
|
|
|
// If TLS is disabled, use plain HTTP with default client
|
|
if !tlsCfg.TLS {
|
|
return retry.DefaultClient, true, nil
|
|
}
|
|
|
|
// If TLS is enabled and uses trusted system CA (no custom bundle, no skip-verify),
|
|
// use the default retry client over HTTPS
|
|
usesTrustedSystemCA := !tlsCfg.TLSSkipVerify && tlsCfg.TLSCACertPath == "" && tlsCfg.TLSCertPath == "" && tlsCfg.TLSKeyPath == ""
|
|
if usesTrustedSystemCA {
|
|
return retry.DefaultClient, false, nil
|
|
}
|
|
|
|
transport, scheme, err := BuildTransportAndSchemeFromTLSConfig(tlsCfg)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Failed to create TLS configuration")
|
|
return nil, false, err
|
|
}
|
|
|
|
// If scheme is http, we can use the default client and instruct callers to use plainHTTP
|
|
if scheme == "http" {
|
|
return retry.DefaultClient, true, nil
|
|
}
|
|
|
|
// For https, wrap our transport with retry
|
|
retryTransport := retry.NewTransport(transport)
|
|
httpClient := &http.Client{
|
|
Transport: retryTransport,
|
|
}
|
|
return httpClient, false, nil
|
|
}
|
|
}
|