feat(helm): add --renegotiate flag to 'helm repo' and refactor repofind

Add TLS renegotiation support when working with chart repos and refactor
repofind code into a builder pattern.

Signed-off-by: Antonia Stevens <astevens@securitycompass.com>

Closes #7344
pull/7472/head
Antonia Stevens 6 years ago committed by Antonia Stevens
parent de9118b879
commit f35c79201e

@ -47,6 +47,7 @@ func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
f.StringVar(&c.CertFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") f.StringVar(&c.CertFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&c.KeyFile, "key-file", "", "identify HTTPS client using this SSL key file") f.StringVar(&c.KeyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&c.CaFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") f.StringVar(&c.CaFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.StringVar(&c.Renegotiate, "renegotiate", "never", "TLS renegotiation strategy, valid options include 'never', 'once' and 'freely'")
} }
// bindOutputFlag will add the output flag to the given command and bind the // bindOutputFlag will add the output flag to the given command and bind the

@ -49,6 +49,8 @@ type repoAddOptions struct {
repoFile string repoFile string
repoCache string repoCache string
renegotiate string
} }
func newRepoAddCmd(out io.Writer) *cobra.Command { func newRepoAddCmd(out io.Writer) *cobra.Command {
@ -75,6 +77,7 @@ func newRepoAddCmd(out io.Writer) *cobra.Command {
f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.StringVar(&o.renegotiate, "renegotiate", "never", "TLS renegotiation strategy, valid options include 'never', 'once' and 'freely'")
return cmd return cmd
} }
@ -120,6 +123,7 @@ func (o *repoAddOptions) run(out io.Writer) error {
CertFile: o.certFile, CertFile: o.certFile,
KeyFile: o.keyFile, KeyFile: o.keyFile,
CAFile: o.caFile, CAFile: o.caFile,
Renegotiate: o.renegotiate,
} }
r, err := repo.NewChartRepository(&c, getter.All(settings)) r, err := repo.NewChartRepository(&c, getter.All(settings))

@ -20,12 +20,47 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"io/ioutil" "io/ioutil"
"strings"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// NewClientTLS returns tls.Config appropriate for client auth. type TLSRenegotiationStrategy string
const (
RenegotiateNever string = "never"
RenegotiateOnceAsClient string = "once"
RenegotiateFreelyAsClient string = "freely"
)
// Validate and return TLS renegotiation settings
func GetRenegotiation(option string) (strategy tls.RenegotiationSupport, err error) {
option = strings.ToLower(option)
switch option {
// RenegotiateNever disables renegotiation.
case RenegotiateNever:
return tls.RenegotiateNever, nil
// RenegotiateOnceAsClient allows a remote server to request
// renegotiation once per connection.
case RenegotiateOnceAsClient:
return tls.RenegotiateOnceAsClient, nil
// RenegotiateFreelyAsClient allows a remote server to repeatedly
// request renegotiation.
case RenegotiateFreelyAsClient:
return tls.RenegotiateFreelyAsClient, nil
}
return tls.RenegotiateNever, errors.New("invalid TLS Renegotiation strategy selected")
}
// NewClientTLS returns tls.Config compatible with client auth but without
// support for TLS renegotiation
func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) { func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) {
return NewClientTLSWithRenegotiate(certFile, keyFile, caFile, RenegotiateNever)
}
// NewClientTLS returns tls.Config compatible with both client auth and TLS
// Renegotiation
func NewClientTLSWithRenegotiate(certFile, keyFile, caFile string, renegotiate string) (*tls.Config, error) {
config := tls.Config{} config := tls.Config{}
if certFile != "" && keyFile != "" { if certFile != "" && keyFile != "" {
@ -44,6 +79,12 @@ func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) {
config.RootCAs = cp config.RootCAs = cp
} }
renegotiation, err := GetRenegotiation(renegotiate)
if err != nil {
return nil, errors.Wrapf(err, "valid options include '%s', '%s' and '%s'", RenegotiateNever, RenegotiateOnceAsClient, RenegotiateFreelyAsClient)
}
config.Renegotiation = renegotiation
return &config, nil return &config, nil
} }

@ -61,12 +61,12 @@ func testfile(t *testing.T, file string) (path string) {
return path return path
} }
func TestNewClientTLS(t *testing.T) { func TestNewClientTLSWithRenegotiate(t *testing.T) {
certFile := testfile(t, testCertFile) certFile := testfile(t, testCertFile)
keyFile := testfile(t, testKeyFile) keyFile := testfile(t, testKeyFile)
caCertFile := testfile(t, testCaCertFile) caCertFile := testfile(t, testCaCertFile)
cfg, err := NewClientTLS(certFile, keyFile, caCertFile) cfg, err := NewClientTLSWithRenegotiate(certFile, keyFile, caCertFile, RenegotiateNever)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -81,7 +81,7 @@ func TestNewClientTLS(t *testing.T) {
t.Fatalf("mismatch tls RootCAs, expecting non-nil") t.Fatalf("mismatch tls RootCAs, expecting non-nil")
} }
cfg, err = NewClientTLS("", "", caCertFile) cfg, err = NewClientTLSWithRenegotiate("", "", caCertFile, RenegotiateNever)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -96,7 +96,7 @@ func TestNewClientTLS(t *testing.T) {
t.Fatalf("mismatch tls RootCAs, expecting non-nil") t.Fatalf("mismatch tls RootCAs, expecting non-nil")
} }
cfg, err = NewClientTLS(certFile, keyFile, "") cfg, err = NewClientTLSWithRenegotiate(certFile, keyFile, "", RenegotiateNever)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -110,4 +110,12 @@ func TestNewClientTLS(t *testing.T) {
if cfg.RootCAs != nil { if cfg.RootCAs != nil {
t.Fatalf("mismatch tls RootCAs, expecting nil") t.Fatalf("mismatch tls RootCAs, expecting nil")
} }
cfgNoRenegotiate, err = NewClientTLS(certFile, keyFile, "")
if err != nil {
t.Error(err)
}
if cfg != cfgNoRenegotiate {
t.Fatalf("config mismatch, configs from NewClientTLS and NewClientTLSWithRenegotiate don't match")
}
} }

@ -71,3 +71,12 @@ func ExtractHostname(addr string) (string, error) {
} }
return u.Hostname(), nil return u.Hostname(), nil
} }
// ExtractScheme returns scheme from URL
func ExtractScheme(addr string) (string, error) {
u, err := url.Parse(addr)
if err != nil {
return "", err
}
return u.Scheme, nil
}

@ -102,6 +102,7 @@ type ChartPathOptions struct {
Username string // --username Username string // --username
Verify bool // --verify Verify bool // --verify
Version string // --version Version string // --version
Renegotiate string // --renegotiate
} }
// NewInstall creates a new Install object with the given configuration. // NewInstall creates a new Install object with the given configuration.
@ -670,8 +671,12 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
dl.Verify = downloader.VerifyAlways dl.Verify = downloader.VerifyAlways
} }
if c.RepoURL != "" { if c.RepoURL != "" {
chartURL, err := repo.FindChartInAuthRepoURL(c.RepoURL, c.Username, c.Password, name, version, finder := repo.NewChartFinder(c.RepoURL, name, version)
c.CertFile, c.KeyFile, c.CaFile, getter.All(settings)) finder.SetCredentials(c.Username, c.Password)
finder.SetTLSFiles(c.CertFile, c.KeyFile, c.CaFile)
finder.SetTLSRenegotiation(c.Renegotiate)
finder.SetProvider(getter.All(settings))
chartURL, err := finder.GetURL()
if err != nil { if err != nil {
return "", err return "", err
} }

@ -64,6 +64,7 @@ func (p *Pull) Run(chartRef string) (string, error) {
Options: []getter.Option{ Options: []getter.Option{
getter.WithBasicAuth(p.Username, p.Password), getter.WithBasicAuth(p.Username, p.Password),
getter.WithTLSClientConfig(p.CertFile, p.KeyFile, p.CaFile), getter.WithTLSClientConfig(p.CertFile, p.KeyFile, p.CaFile),
getter.WithTLSRenegotiate(p.Renegotiate),
}, },
RepositoryConfig: p.Settings.RepositoryConfig, RepositoryConfig: p.Settings.RepositoryConfig,
RepositoryCache: p.Settings.RepositoryCache, RepositoryCache: p.Settings.RepositoryCache,
@ -88,7 +89,12 @@ func (p *Pull) Run(chartRef string) (string, error) {
} }
if p.RepoURL != "" { if p.RepoURL != "" {
chartURL, err := repo.FindChartInAuthRepoURL(p.RepoURL, p.Username, p.Password, chartRef, p.Version, p.CertFile, p.KeyFile, p.CaFile, getter.All(p.Settings)) finder := repo.NewChartFinder(p.RepoURL, chartRef, p.Version)
finder.SetCredentials(p.Username, p.Password)
finder.SetTLSFiles(p.CertFile, p.KeyFile, p.CaFile)
finder.SetProvider(getter.All(p.Settings))
finder.SetTLSRenegotiation(p.Renegotiate)
chartURL, err := finder.GetURL()
if err != nil { if err != nil {
return out.String(), err return out.String(), err
} }

@ -182,6 +182,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er
c.Options, c.Options,
getter.WithURL(rc.URL), getter.WithURL(rc.URL),
getter.WithTLSClientConfig(rc.CertFile, rc.KeyFile, rc.CAFile), getter.WithTLSClientConfig(rc.CertFile, rc.KeyFile, rc.CAFile),
getter.WithTLSRenegotiate(rc.Renegotiate),
) )
if rc.Username != "" && rc.Password != "" { if rc.Username != "" && rc.Password != "" {
c.Options = append( c.Options = append(
@ -218,6 +219,10 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er
c.Options = append(c.Options, getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile)) c.Options = append(c.Options, getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile))
} }
if r.Config.Renegotiate != "" {
c.Options = append(c.Options, getter.WithTLSRenegotiate(r.Config.Renegotiate))
}
// Next, we need to load the index, and actually look up the chart. // Next, we need to load the index, and actually look up the chart.
idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name)) idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name))
i, err := repo.LoadIndexFile(idxFile) i, err := repo.LoadIndexFile(idxFile)

@ -91,6 +91,7 @@ func TestResolveChartOpts(t *testing.T) {
expect: []getter.Option{ expect: []getter.Option{
getter.WithURL("https://example.com/foo-1.2.3.tgz"), getter.WithURL("https://example.com/foo-1.2.3.tgz"),
getter.WithTLSClientConfig("cert", "key", "ca"), getter.WithTLSClientConfig("cert", "key", "ca"),
getter.WithTLSRenegotiate("never"),
}, },
}, },
} }

@ -535,7 +535,9 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*
return return
} }
} }
url, err = repo.FindChartInRepoURL(repoURL, name, version, "", "", "", m.Getters) finder := repo.NewChartFinder(repoURL, name, version)
finder.SetProvider(m.Getters)
url, err = finder.GetURL()
if err == nil { if err == nil {
return return
} }

@ -21,3 +21,4 @@ repositories:
certFile: "cert" certFile: "cert"
keyFile: "key" keyFile: "key"
caFile: "ca" caFile: "ca"
renegotiate: "never"

@ -35,6 +35,7 @@ type options struct {
username string username string
password string password string
userAgent string userAgent string
renegotiate string
} }
// Option allows specifying various settings configurable by the user for overriding the defaults // Option allows specifying various settings configurable by the user for overriding the defaults
@ -73,6 +74,13 @@ func WithTLSClientConfig(certFile, keyFile, caFile string) Option {
} }
} }
// WithTLSRenegotiate sets the TLS renegotiation support
func WithTLSRenegotiate(option string) Option {
return func(opts *options) {
opts.renegotiate = option
}
}
// Getter is an interface to support GET to the specified URL. // Getter is an interface to support GET to the specified URL.
type Getter interface { type Getter interface {
// Get file content by url string // Get file content by url string

@ -89,17 +89,24 @@ func NewHTTPGetter(options ...Option) (Getter, error) {
} }
func (g *HTTPGetter) httpClient() (*http.Client, error) { func (g *HTTPGetter) httpClient() (*http.Client, error) {
if (g.opts.certFile != "" && g.opts.keyFile != "") || g.opts.caFile != "" { scheme, err := urlutil.ExtractScheme(g.opts.url)
tlsConf, err := tlsutil.NewClientTLS(g.opts.certFile, g.opts.keyFile, g.opts.caFile)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "can't create TLS config for client") return nil, err
}
if scheme == "https" {
tlsConf, err := tlsutil.NewClientTLSWithRenegotiate(g.opts.certFile, g.opts.keyFile, g.opts.caFile, g.opts.renegotiate)
if err != nil {
return nil, errors.Wrap(err, "can't create TLS config")
} }
tlsConf.BuildNameToCertificate() tlsConf.BuildNameToCertificate()
sni, err := urlutil.ExtractHostname(g.opts.url) sni, err := urlutil.ExtractHostname(g.opts.url)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConf.ServerName = sni tlsConf.ServerName = sni
client := &http.Client{ client := &http.Client{

@ -148,7 +148,7 @@ func TestDownloadTLS(t *testing.T) {
ca, pub, priv := filepath.Join(cd, "rootca.crt"), filepath.Join(cd, "crt.pem"), filepath.Join(cd, "key.pem") ca, pub, priv := filepath.Join(cd, "rootca.crt"), filepath.Join(cd, "crt.pem"), filepath.Join(cd, "key.pem")
tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
tlsConf, err := tlsutil.NewClientTLS(pub, priv, ca) tlsConf, err := tlsutil.NewClientTLSWithRenegotiate(pub, priv, ca, tlsutil.RenegotiateNever)
if err != nil { if err != nil {
t.Fatal(errors.Wrap(err, "can't create TLS config for client")) t.Fatal(errors.Wrap(err, "can't create TLS config for client"))
} }
@ -162,6 +162,7 @@ func TestDownloadTLS(t *testing.T) {
g, err := NewHTTPGetter( g, err := NewHTTPGetter(
WithURL(u.String()), WithURL(u.String()),
WithTLSClientConfig(pub, priv, ca), WithTLSClientConfig(pub, priv, ca),
WithTLSRenegotiate(tlsutil.RenegotiateNever),
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -177,7 +178,7 @@ func TestDownloadTLS(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig(pub, priv, ca)); err != nil { if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig(pub, priv, ca), WithTLSRenegotiate(tlsutil.RenegotiateNever)); err != nil {
t.Error(err) t.Error(err)
} }
@ -187,7 +188,18 @@ func TestDownloadTLS(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig("", "", ca)); err != nil { if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig("", "", ca), WithTLSRenegotiate(tlsutil.RenegotiateNever)); err != nil {
t.Error(err) t.Error(err)
} }
// test with OnceAsClient TLS renegotiation
if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig(pub, priv, ca), WithTLSRenegotiate(tlsutil.RenegotiateOnceAsClient)); err != nil {
t.Error(err)
}
// test with FreelyAsClient TLS renegotiation
if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig(pub, priv, ca), WithTLSRenegotiate(tlsutil.RenegotiateFreelyAsClient)); err != nil {
t.Error(err)
}
} }

@ -7,9 +7,11 @@ repositories:
keyFile: "" keyFile: ""
name: stable name: stable
url: https://kubernetes-charts.storage.googleapis.com url: https://kubernetes-charts.storage.googleapis.com
renegotiate: never
- caFile: "" - caFile: ""
cache: repository/cache/local-index.yaml cache: repository/cache/local-index.yaml
certFile: "" certFile: ""
keyFile: "" keyFile: ""
name: local name: local
url: http://127.0.0.1:8879/charts url: http://127.0.0.1:8879/charts
renegotiate: never

@ -31,6 +31,7 @@ import (
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/helmpath"
"helm.sh/helm/v3/pkg/provenance" "helm.sh/helm/v3/pkg/provenance"
@ -45,6 +46,7 @@ type Entry struct {
CertFile string `json:"certFile"` CertFile string `json:"certFile"`
KeyFile string `json:"keyFile"` KeyFile string `json:"keyFile"`
CAFile string `json:"caFile"` CAFile string `json:"caFile"`
Renegotiate string `json:"renegotiate"`
} }
// ChartRepository represents a chart repository // ChartRepository represents a chart repository
@ -76,9 +78,8 @@ func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository,
}, nil }, nil
} }
// Load loads a directory of charts as if it were a repository. // Loads a directory of charts as if it were a repository.
// // requires the presence of an index.yaml file in the directory.
// It requires the presence of an index.yaml file in the directory.
func (r *ChartRepository) Load() error { func (r *ChartRepository) Load() error {
dirInfo, err := os.Stat(r.Config.Name) dirInfo, err := os.Stat(r.Config.Name)
if err != nil { if err != nil {
@ -122,6 +123,7 @@ func (r *ChartRepository) DownloadIndexFile() (string, error) {
resp, err := r.Client.Get(indexURL, resp, err := r.Client.Get(indexURL,
getter.WithURL(r.Config.URL), getter.WithURL(r.Config.URL),
getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile), getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile),
getter.WithTLSRenegotiate(r.Config.Renegotiate),
getter.WithBasicAuth(r.Config.Username, r.Config.Password), getter.WithBasicAuth(r.Config.Username, r.Config.Password),
) )
if err != nil { if err != nil {
@ -180,38 +182,111 @@ func (r *ChartRepository) generateIndex() error {
return nil return nil
} }
// FindChartInRepoURL finds chart in chart repository pointed by repoURL type TLSConfig struct {
// without adding repo to repositories certFile string
func FindChartInRepoURL(repoURL, chartName, chartVersion, certFile, keyFile, caFile string, getters getter.Providers) (string, error) { keyFile string
return FindChartInAuthRepoURL(repoURL, "", "", chartName, chartVersion, certFile, keyFile, caFile, getters) caFile string
renegotiate string
} }
// FindChartInAuthRepoURL finds chart in chart repository pointed by repoURL type Credentials struct {
// without adding repo to repositories, like FindChartInRepoURL, username string
// but it also receives credentials for the chart repository. password string
func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion, certFile, keyFile, caFile string, getters getter.Providers) (string, error) { }
type ChartFinder struct {
repoURL string
chartName string
chartVersion string
credentials Credentials
tlsConfig TLSConfig
providers getter.Providers
}
type FindChart interface {
SetRepoURL(string) FindChart
SetChartName(string) FindChart
SetChartVersion(string) FindChart
SetCredentials(string, string) FindChart
SetTLSFiles(string, string, string) FindChart
SetTLSRenegotiation(string) FindChart
SetProviders(getter.Providers) FindChart
GetURL() (string, error)
}
// Finder to locate charts in a chart repository without adding repo to
// repositories
func NewChartFinder(repoURL string, chartName string, chartVersion string) ChartFinder {
return ChartFinder{
repoURL: repoURL,
chartName: chartName,
chartVersion: chartVersion,
credentials: Credentials{},
tlsConfig: TLSConfig{},
providers: getter.All(&cli.EnvSettings{}),
}
}
func (cf *ChartFinder) SetRepoURL(url string) ChartFinder {
cf.repoURL = url
return *cf
}
func (cf *ChartFinder) SetChartName(name string) ChartFinder {
cf.chartName = name
return *cf
}
func (cf *ChartFinder) SetChartVersion(version string) ChartFinder {
cf.chartVersion = version
return *cf
}
func (cf *ChartFinder) SetTLSFiles(certFile string, keyFile string, caFile string) ChartFinder {
cf.tlsConfig.certFile = certFile
cf.tlsConfig.keyFile = keyFile
cf.tlsConfig.caFile = caFile
return *cf
}
func (cf *ChartFinder) SetCredentials(username string, password string) ChartFinder {
cf.credentials = Credentials{username, password}
return *cf
}
func (cf *ChartFinder) SetTLSRenegotiation(renegotiate string) ChartFinder {
cf.tlsConfig.renegotiate = renegotiate
return *cf
}
func (cf *ChartFinder) SetProvider(providers getter.Providers) ChartFinder {
cf.providers = providers
return *cf
}
func (cf *ChartFinder) GetURL() (string, error) {
// Download and write the index file to a temporary location // Download and write the index file to a temporary location
buf := make([]byte, 20) buf := make([]byte, 20)
rand.Read(buf) rand.Read(buf)
name := strings.ReplaceAll(base64.StdEncoding.EncodeToString(buf), "/", "-") name := strings.ReplaceAll(base64.StdEncoding.EncodeToString(buf), "/", "-")
c := Entry{ c := Entry{
URL: repoURL, URL: cf.repoURL,
Username: username, Username: cf.credentials.username,
Password: password, Password: cf.credentials.password,
CertFile: certFile, CertFile: cf.tlsConfig.certFile,
KeyFile: keyFile, KeyFile: cf.tlsConfig.keyFile,
CAFile: caFile, CAFile: cf.tlsConfig.caFile,
Name: name, Name: name,
Renegotiate: cf.tlsConfig.renegotiate,
} }
r, err := NewChartRepository(&c, getters) r, err := NewChartRepository(&c, cf.providers)
if err != nil { if err != nil {
return "", err return "", err
} }
idx, err := r.DownloadIndexFile() idx, err := r.DownloadIndexFile()
if err != nil { if err != nil {
return "", errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", repoURL) return "", errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", cf.repoURL)
} }
// Read the index file for the repository to get chart information and return chart URL // Read the index file for the repository to get chart information and return chart URL
@ -220,13 +295,13 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion
return "", err return "", err
} }
errMsg := fmt.Sprintf("chart %q", chartName) errMsg := fmt.Sprintf("chart %q", cf.chartName)
if chartVersion != "" { if cf.chartVersion != "" {
errMsg = fmt.Sprintf("%s version %q", errMsg, chartVersion) errMsg = fmt.Sprintf("%s version %q", errMsg, cf.chartVersion)
} }
cv, err := repoIndex.Get(chartName, chartVersion) cv, err := repoIndex.Get(cf.chartName, cf.chartVersion)
if err != nil { if err != nil {
return "", errors.Errorf("%s not found in %s repository", errMsg, repoURL) return "", errors.Errorf("%s not found in %s repository", errMsg, cf.repoURL)
} }
if len(cv.URLs) == 0 { if len(cv.URLs) == 0 {
@ -235,7 +310,7 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion
chartURL := cv.URLs[0] chartURL := cv.URLs[0]
absoluteChartURL, err := ResolveReferenceURL(repoURL, chartURL) absoluteChartURL, err := ResolveReferenceURL(cf.repoURL, chartURL)
if err != nil { if err != nil {
return "", errors.Wrap(err, "failed to make chart URL absolute") return "", errors.Wrap(err, "failed to make chart URL absolute")
} }
@ -243,6 +318,28 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion
return absoluteChartURL, nil return absoluteChartURL, nil
} }
// Obsolete, use NewChartFinder/GetURL instead
// FindChartInRepoURL finds chart in chart repository pointed by repoURL
// without adding repo to repositories
func FindChartInRepoURL(repoURL string, chartName string, chartVersion string, certFile string, keyFile string, caFile string, getters getter.Providers) (string, error) {
finder := NewChartFinder(repoURL, chartName, chartVersion)
finder.SetTLSFiles(certFile, keyFile, caFile)
finder.SetProvider(getters)
return finder.GetURL()
}
// Obsolete, use NewChartFinder/GetURL instead
// FindChartInAuthRepoURL finds chart in chart repository pointed by repoURL
// without adding repo to repositories, like FindChartInRepoURL,
// but it also receives credentials for the chart repository.
func FindChartInAuthRepoURL(repoURL string, username string, password string, chartName string, chartVersion string, certFile string, keyFile string, caFile string, getters getter.Providers) (string, error) {
finder := NewChartFinder(repoURL, chartName, chartVersion)
finder.SetCredentials(username, password)
finder.SetTLSFiles(certFile, keyFile, caFile)
finder.SetProvider(getters)
return finder.GetURL()
}
// ResolveReferenceURL resolves refURL relative to baseURL. // ResolveReferenceURL resolves refURL relative to baseURL.
// If refURL is absolute, it simply returns refURL. // If refURL is absolute, it simply returns refURL.
func ResolveReferenceURL(baseURL, refURL string) (string, error) { func ResolveReferenceURL(baseURL, refURL string) (string, error) {

@ -3,6 +3,8 @@ repositories:
- name: stable - name: stable
url: https://example.com/stable/charts url: https://example.com/stable/charts
cache: stable-index.yaml cache: stable-index.yaml
renegotiate: never
- name: incubator - name: incubator
url: https://example.com/incubator url: https://example.com/incubator
cache: incubator-index.yaml cache: incubator-index.yaml
renegotiate: never

Loading…
Cancel
Save