Skip to content

Commit

Permalink
Extract the logic for creating http client
Browse files Browse the repository at this point in the history
  • Loading branch information
pmatseykanets committed Dec 6, 2024
1 parent 51d8c10 commit 703ffd0
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 55 deletions.
10 changes: 2 additions & 8 deletions cliclient/cliclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"strings"
"time"

errorsPkg "github.com/pkg/errors"
"github.com/rancher/cli/config"
Expand Down Expand Up @@ -181,19 +180,14 @@ func createClientOpts(config *config.ServerConfig) *clientbase.ClientOpts {
serverURL = config.URL + "/v3"
}

options := &clientbase.ClientOpts{
return &clientbase.ClientOpts{
URL: serverURL,
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
CACerts: config.CACerts,
ProxyURL: config.ProxyURL,
Timeout: config.GetHTTPTimeout(),
}

if config.HTTPTimeoutSeconds > 0 {
options.Timeout = time.Duration(config.HTTPTimeoutSeconds) * time.Second
}

return options
}

func SplitOnColon(s string) []string {
Expand Down
33 changes: 33 additions & 0 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package cmd
import (
"bufio"
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"os"
"os/exec"
Expand Down Expand Up @@ -39,6 +41,7 @@ const (
letters = "abcdefghijklmnopqrstuvwxyz0123456789"
cfgFile = "cli2.json"
kubeConfigKeyFormat = "%s-%s"
defaultHTTPTimeout = time.Minute // Matches the default timeout of the Norman Api Client.
)

var (
Expand Down Expand Up @@ -624,3 +627,33 @@ func ConfigDir() (string, error) {
}
return filepath.Join(homeDir, ".rancher"), nil
}

func newHTTPClient(serverConfig *config.ServerConfig, tlsConfig *tls.Config) (*http.Client, error) {
var proxy func(*http.Request) (*url.URL, error)
if serverConfig.ProxyURL != "" {
proxyURL, err := url.Parse(serverConfig.ProxyURL)
if err != nil {
return nil, fmt.Errorf("invalid proxy address %s: %w", serverConfig.ProxyURL, err)
}
proxy = http.ProxyURL(proxyURL)
} else {
proxy = http.ProxyFromEnvironment
}

tr := &http.Transport{
Proxy: proxy,
}
if tlsConfig != nil {
tr.TLSClientConfig = tlsConfig
}

timeout := serverConfig.GetHTTPTimeout()
if timeout == 0 {
timeout = defaultHTTPTimeout
}

return &http.Client{
Transport: tr,
Timeout: timeout,
}, nil
}
37 changes: 11 additions & 26 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"os"
"strconv"
"strings"
"time"

"github.com/sirupsen/logrus"

Expand Down Expand Up @@ -253,32 +252,18 @@ func getProjectContext(ctx *cli.Context, c *cliclient.MasterClient) (string, err
return projectCollection.Data[selection].ID, nil
}

func getCertFromServer(ctx *cli.Context, cf *config.ServerConfig) (*cliclient.MasterClient, error) {
req, err := http.NewRequest("GET", cf.URL+"/v3/settings/cacerts", nil)
func getCertFromServer(ctx *cli.Context, serverConfig *config.ServerConfig) (*cliclient.MasterClient, error) {
req, err := http.NewRequest("GET", serverConfig.URL+"/v3/settings/cacerts", nil)
if err != nil {
return nil, err
}

req.SetBasicAuth(cf.AccessKey, cf.SecretKey)
req.SetBasicAuth(serverConfig.AccessKey, serverConfig.SecretKey)

var proxy func(*http.Request) (*url.URL, error)
if cf.ProxyURL != "" {
proxyURL, err := url.Parse(cf.ProxyURL)
if err != nil {
return nil, fmt.Errorf("invalid proxy address %s: %w", cf.ProxyURL, err)
}
proxy = http.ProxyURL(proxyURL)
} else {
proxy = http.ProxyFromEnvironment
}

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Proxy: proxy,
}
client := &http.Client{Transport: tr}
if cf.HTTPTimeoutSeconds > 0 {
client.Timeout = time.Duration(cf.HTTPTimeoutSeconds) * time.Second
tlsConfig := &tls.Config{InsecureSkipVerify: true}
client, err := newHTTPClient(serverConfig, tlsConfig)
if err != nil {
return nil, err
}

res, err := client.Do(req)
Expand All @@ -296,7 +281,7 @@ func getCertFromServer(ctx *cli.Context, cf *config.ServerConfig) (*cliclient.Ma
var certReponse *CACertResponse
err = json.Unmarshal(content, &certReponse)
if err != nil {
return nil, fmt.Errorf("Unable to parse response from %s/v3/settings/cacerts\nError: %s\nResponse:\n%s", cf.URL, err, content)
return nil, fmt.Errorf("Unable to parse response from %s/v3/settings/cacerts\nError: %s\nResponse:\n%s", serverConfig.URL, err, content)
}

cert, err := verifyCert([]byte(certReponse.Value))
Expand All @@ -311,14 +296,14 @@ func getCertFromServer(ctx *cli.Context, cf *config.ServerConfig) (*cliclient.Ma
}

if !ctx.Bool("skip-verify") {
if ok := verifyUserAcceptsCert(serverCerts, cf.URL); !ok {
if ok := verifyUserAcceptsCert(serverCerts, serverConfig.URL); !ok {
return nil, errors.New("CACert of server was not accepted, unable to login")
}
}

cf.CACerts = cert
serverConfig.CACerts = cert

return cliclient.NewManagementClient(cf)
return cliclient.NewManagementClient(serverConfig)
}

func verifyUserAcceptsCert(certs []string, url string) bool {
Expand Down
26 changes: 5 additions & 21 deletions cmd/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"os/exec"
"path"
"strings"
"time"

"github.com/pkg/errors"
"github.com/rancher/cli/cliclient"
Expand Down Expand Up @@ -172,35 +170,21 @@ func getSSHKey(c *cliclient.MasterClient, link, nodeName string) ([]byte, string
req.SetBasicAuth(c.UserConfig.AccessKey, c.UserConfig.SecretKey)
req.Header.Add("Accept-Encoding", "zip")

var proxy func(*http.Request) (*url.URL, error)
if c.UserConfig.ProxyURL != "" {
proxyURL, err := url.Parse(c.UserConfig.ProxyURL)
if err != nil {
return nil, "", fmt.Errorf("invalid proxy address %s: %w", c.UserConfig.ProxyURL, err)
}
proxy = http.ProxyURL(proxyURL)
} else {
proxy = http.ProxyFromEnvironment
}

tr := &http.Transport{
Proxy: proxy,
}

var tlsConfig *tls.Config
if c.UserConfig.CACerts != "" {
roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM([]byte(c.UserConfig.CACerts))
if !ok {
return []byte{}, "", err
}
tr.TLSClientConfig = &tls.Config{
tlsConfig = &tls.Config{
RootCAs: roots,
}
}

client := &http.Client{Transport: tr}
if c.UserConfig.HTTPTimeoutSeconds > 0 {
client.Timeout = time.Duration(c.UserConfig.HTTPTimeoutSeconds) * time.Second
client, err := newHTTPClient(c.UserConfig, tlsConfig)
if err != nil {
return nil, "", err
}

resp, err := client.Do(req)
Expand Down
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/sirupsen/logrus"
"k8s.io/client-go/tools/clientcmd/api"
Expand Down Expand Up @@ -38,6 +39,10 @@ type ServerConfig struct {
HTTPTimeoutSeconds int `json:"httpTimeoutSeconds"`
}

func (c *ServerConfig) GetHTTPTimeout() time.Duration {
return time.Duration(c.HTTPTimeoutSeconds) * time.Second
}

// LoadFromPath attempts to load a config from the given file path. If the file
// doesn't exist, an empty config is returned.
func LoadFromPath(path string) (Config, error) {
Expand Down

0 comments on commit 703ffd0

Please sign in to comment.