Skip to content

Commit

Permalink
proxy: Use our own http transport with crc's proxy config
Browse files Browse the repository at this point in the history
At the moment, when a proxy is used, crc starts by setting `NO_PROXY`
with some generic values (localhost), and once it knows which bundle
it's going to be using, it adds the domain(s) used by the bundle to the
`NO_PROXY` environment variable.

Early during startup, it's sending HTTP request to check the latest crc
version available, and it uses `http.DefaultTransport`/`ProxyFromEnvironment`
for that.

This is causing problems further down the road, as `ProxyFromEnvironment`
will only read NO_PROXY/HTTP_PROXY/HTTPS_PROXY once, and will use these
cached values for the lifetime of the process. This means
`ProxyFromEnvironment` will never know about `.testing` which is only
added later.

This causes errors at the very end of the startup process when a proxy
is used:
`Cannot update kubeconfig: Head "https://oauth-openshift.apps-crc.testing": Service not available`
`oauth-openshift.apps-crc.testing` is accessed through the proxy as
`NO_PROXY` is not up to date.

In order to avoid this issue, this commit introduces a crc specific
`ProxyFunc` which will use directly the http_proxy/https_proxy/no_proxy
settings from crc rather than getting these from the environment.

This can still be problematic as `oc` code does not always use the http
transport that we pass to it:
openshift/oc#837
but for now this seems to be working well enough.
  • Loading branch information
cfergeau authored and praveenkumar committed Sep 22, 2021
1 parent a87e27f commit 1972b9e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
35 changes: 24 additions & 11 deletions cmd/crc/cmd/root.go
Expand Up @@ -58,6 +58,11 @@ func init() {
if err != nil {
logging.Fatal(err.Error())
}

if err := setProxyDefaults(); err != nil {
logging.Fatal(err.Error())
}

// Initiate segment client
if segmentClient, err = segment.NewClient(config, httpTransport()); err != nil {
logging.Fatal(err.Error())
Expand All @@ -77,9 +82,6 @@ func runPrerun(cmd *cobra.Command) error {
logFile = constants.DaemonLogFilePath
}
logging.InitLogrus(logging.LogLevel, logFile)
if err := setProxyDefaults(); err != nil {
return err
}

for _, str := range defaultVersion().lines() {
logging.Debugf(str)
Expand Down Expand Up @@ -211,22 +213,33 @@ func attachMiddleware(names []string, cmd *cobra.Command) {
}
}

func defaultTransport() *http.Transport {
transport := http.DefaultTransport.(*http.Transport)
proxyConfig, err := network.NewProxyConfig()
if err != nil {
return transport
}

transport = transport.Clone()
transport.Proxy = proxyConfig.ProxyFunc()
return transport
}

func httpTransport() http.RoundTripper {
if config.Get(crcConfig.ProxyCAFile).IsDefault {
return http.DefaultTransport
return defaultTransport()
}
caCert, err := ioutil.ReadFile(config.Get(crcConfig.ProxyCAFile).AsString())
if err != nil {
logging.Errorf("Cannot read proxy-ca-file, using default http transport: %v", err)
return http.DefaultTransport
return defaultTransport()
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: caCertPool,
},
transport := defaultTransport()
transport.TLSClientConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: caCertPool,
}
return transport
}
3 changes: 2 additions & 1 deletion pkg/crc/machine/kubeconfig.go
Expand Up @@ -133,7 +133,8 @@ func addContext(cfg *api.Config, ip string, clusterConfig *types.ClusterConfig,
return fmt.Errorf("failed to parse root certificate")
}
token, err := tokencmd.RequestToken(&restclient.Config{
Host: clusterConfig.ClusterAPI,
Proxy: clusterConfig.ProxyConfig.ProxyFunc(),
Host: clusterConfig.ClusterAPI,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: roots,
Expand Down
18 changes: 18 additions & 0 deletions pkg/crc/network/proxy.go
Expand Up @@ -2,6 +2,8 @@ package network

import (
"fmt"
"net/http"
"net/url"
"os"
"strings"

Expand Down Expand Up @@ -119,6 +121,22 @@ func (p *ProxyConfig) ApplyToEnvironment() {
}
}

// This wraps https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config.ProxyFunc
// This can be called on a nil *ProxyConfig
func (p *ProxyConfig) ProxyFunc() func(req *http.Request) (*url.URL, error) {
var cfg httpproxy.Config

if p != nil {
cfg = httpproxy.Config{
HTTPProxy: p.HTTPProxy,
HTTPSProxy: p.HTTPSProxy,
NoProxy: p.GetNoProxyString(),
}
}

return func(req *http.Request) (*url.URL, error) { return cfg.ProxyFunc()(req.URL) }
}

// Enabled returns true if at least one proxy (HTTP or HTTPS) is configured. Returns false otherwise.
func (p *ProxyConfig) IsEnabled() bool {
return p.HTTPProxy != "" || p.HTTPSProxy != ""
Expand Down

0 comments on commit 1972b9e

Please sign in to comment.