From 84c21c15ddd7244944ea65157cfdce908168c222 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 14 Jun 2022 16:12:41 -0400 Subject: [PATCH] improve: fix prompt for TLS certificate On darwin the error was of the wrong type when using the system cert pool --- internal/cmd/cmd.go | 2 +- internal/cmd/login.go | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index f40194531a..063fbfc0b2 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -104,7 +104,7 @@ func httpTransportForHostConfig(config *ClientHostConfig) *http.Transport { if config.TrustedCertificate != "" { ok := pool.AppendCertsFromPEM([]byte(config.TrustedCertificate)) if !ok { - logging.S.Warnf("Failed to read trusted certificates for server: %v", err) + logging.S.Warnf("Failed to read trusted certificates for server") } } diff --git a/internal/cmd/login.go b/internal/cmd/login.go index 908acfbbaf..a73c4477a4 100644 --- a/internal/cmd/login.go +++ b/internal/cmd/login.go @@ -421,7 +421,7 @@ func newLoginClient(cli *CLI, options loginCmdOptions) (loginClient, error) { } // Prompt user only if server fails the TLS verification - if err := attemptTLSRequest(c.APIClient); err != nil { + if err := attemptTLSRequest(options); err != nil { var uaErr x509.UnknownAuthorityError if !errors.As(err, &uaErr) { return c, err @@ -459,15 +459,43 @@ func newLoginClient(cli *CLI, options loginCmdOptions) (loginClient, error) { return c, nil } -func attemptTLSRequest(client *api.Client) error { - req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, client.URL, nil) +func attemptTLSRequest(options loginCmdOptions) error { + reqURL := "https://" + options.Server + // First attempt with the system cert pool + req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, reqURL, nil) if err != nil { return fmt.Errorf("failed to create request: %w", err) } - logging.S.Debugf("call server: test tls for %q", client.URL) + logging.S.Debugf("call server: test tls for %q", reqURL) + httpClient := http.Client{Timeout: 60 * time.Second} + res, err := httpClient.Do(req) + if err == nil { + res.Body.Close() + return nil + } + + // Second attempt with an empty cert pool. This is necessary because at least + // on darwin, the error is the wrong type when using the system cert pool. + // See https://github.com/golang/go/issues/53401. + req, err = http.NewRequestWithContext(context.TODO(), http.MethodGet, reqURL, nil) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + pool := x509.NewCertPool() + if options.TrustedCertificate != "" { + pool.AppendCertsFromPEM([]byte(options.TrustedCertificate)) + } + + httpClient = http.Client{ + Timeout: 60 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS12}, + }, + } + res, err = httpClient.Do(req) urlErr := &url.Error{} - res, err := client.HTTP.Do(req) switch { case err == nil: res.Body.Close()