From 60d910a5124a3fdfb3c027ad188acb683ef38507 Mon Sep 17 00:00:00 2001 From: youyongsong Date: Fri, 17 Jul 2020 15:17:28 +0800 Subject: [PATCH] support insecure and plain-http options in helm chart pull and push commands This pr tries to resolve issue #8464 and #6324. helm only support `--insecure` option in the helm registry login command. In some cases we want to push or pull a chart to a insecure or http registry anonymously without login, so I add `--insecure` and `--plain-http` options to meet these cases. Signed-off-by: youyongsong --- cmd/helm/chart_pull.go | 11 ++++- cmd/helm/chart_push.go | 11 ++++- internal/experimental/registry/client.go | 42 +++++++++++++++++-- internal/experimental/registry/client_test.go | 10 ++--- pkg/action/chart_pull.go | 4 +- pkg/action/chart_push.go | 4 +- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/cmd/helm/chart_pull.go b/cmd/helm/chart_pull.go index 760ff3e2c..5c18dc3e3 100644 --- a/cmd/helm/chart_pull.go +++ b/cmd/helm/chart_pull.go @@ -32,7 +32,8 @@ This will store the chart in the local registry cache to be used later. ` func newChartPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ + var insecureOpt, plainHTTPOpt bool + cmd := &cobra.Command{ Use: "pull [ref]", Short: "pull a chart from remote", Long: chartPullDesc, @@ -40,7 +41,13 @@ func newChartPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Hidden: !FeatureGateOCI.IsEnabled(), RunE: func(cmd *cobra.Command, args []string) error { ref := args[0] - return action.NewChartPull(cfg).Run(out, ref) + return action.NewChartPull(cfg).Run(out, ref, insecureOpt, plainHTTPOpt) }, } + + f := cmd.Flags() + f.BoolVarP(&insecureOpt, "insecure", "", false, "allow connections to TLS registry without certs") + f.BoolVarP(&plainHTTPOpt, "plain-http", "", false, "use plain http and not https") + + return cmd } diff --git a/cmd/helm/chart_push.go b/cmd/helm/chart_push.go index ff34632b1..9f70b579d 100644 --- a/cmd/helm/chart_push.go +++ b/cmd/helm/chart_push.go @@ -34,7 +34,8 @@ Must first run "helm chart save" or "helm chart pull". ` func newChartPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ + var insecureOpt, plainHTTPOpt bool + cmd := &cobra.Command{ Use: "push [ref]", Short: "push a chart to remote", Long: chartPushDesc, @@ -42,7 +43,13 @@ func newChartPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Hidden: !FeatureGateOCI.IsEnabled(), RunE: func(cmd *cobra.Command, args []string) error { ref := args[0] - return action.NewChartPush(cfg).Run(out, ref) + return action.NewChartPush(cfg).Run(out, ref, insecureOpt, plainHTTPOpt) }, } + + f := cmd.Flags() + f.BoolVarP(&insecureOpt, "insecure", "", false, "allow connections to TLS registry without certs") + f.BoolVarP(&plainHTTPOpt, "plain-http", "", false, "use plain http and not https") + + return cmd } diff --git a/internal/experimental/registry/client.go b/internal/experimental/registry/client.go index 5756030c0..3978b694b 100644 --- a/internal/experimental/registry/client.go +++ b/internal/experimental/registry/client.go @@ -18,12 +18,14 @@ package registry // import "helm.sh/helm/v3/internal/experimental/registry" import ( "context" + "crypto/tls" "fmt" "io" "io/ioutil" "net/http" "sort" + "github.com/containerd/containerd/remotes" auth "github.com/deislabs/oras/pkg/auth/docker" "github.com/deislabs/oras/pkg/oras" "github.com/gosuri/uitable" @@ -74,7 +76,7 @@ func NewClient(opts ...ClientOption) (*Client, error) { } } if client.resolver == nil { - resolver, err := client.authorizer.Resolver(context.Background(), http.DefaultClient, false) + resolver, err := client.newResolver(false, false) if err != nil { return nil, err } @@ -117,7 +119,17 @@ func (c *Client) Logout(hostname string) error { } // PushChart uploads a chart to a registry -func (c *Client) PushChart(ref *Reference) error { +func (c *Client) PushChart(ref *Reference, insecure bool, plainHTTP bool) error { + if insecure || plainHTTP { + resolver, err := c.newResolver(insecure, plainHTTP) + if err != nil { + return err + } + c.resolver = &Resolver{ + Resolver: resolver, + } + } + r, err := c.cache.FetchReference(ref) if err != nil { return err @@ -144,7 +156,17 @@ func (c *Client) PushChart(ref *Reference) error { } // PullChart downloads a chart from a registry -func (c *Client) PullChart(ref *Reference) error { +func (c *Client) PullChart(ref *Reference, insecure bool, plainHTTP bool) error { + if insecure || plainHTTP { + resolver, err := c.newResolver(insecure, plainHTTP) + if err != nil { + return err + } + c.resolver = &Resolver{ + Resolver: resolver, + } + } + if ref.Tag == "" { return errors.New("tag explicitly required") } @@ -279,3 +301,17 @@ func (c *Client) getChartTableRows() ([][]interface{}, error) { } return rows, nil } + +func (c *Client) newResolver(insecure bool, plainHTTP bool) (resolver remotes.Resolver, err error) { + client := http.DefaultClient + if insecure { + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + } + + resolver, err = c.authorizer.Resolver(context.Background(), client, plainHTTP) + return +} diff --git a/internal/experimental/registry/client_test.go b/internal/experimental/registry/client_test.go index 2d208b7b9..c627f81f2 100644 --- a/internal/experimental/registry/client_test.go +++ b/internal/experimental/registry/client_test.go @@ -187,13 +187,13 @@ func (suite *RegistryClientTestSuite) Test_3_PushChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) suite.Nil(err) - err = suite.RegistryClient.PushChart(ref) + err = suite.RegistryClient.PushChart(ref, false, false) suite.NotNil(err) // existing ref ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) suite.Nil(err) - err = suite.RegistryClient.PushChart(ref) + err = suite.RegistryClient.PushChart(ref, false, false) suite.Nil(err) } @@ -202,13 +202,13 @@ func (suite *RegistryClientTestSuite) Test_4_PullChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) suite.Nil(err) - err = suite.RegistryClient.PullChart(ref) + err = suite.RegistryClient.PullChart(ref, false, false) suite.NotNil(err) // existing ref ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) suite.Nil(err) - err = suite.RegistryClient.PullChart(ref) + err = suite.RegistryClient.PullChart(ref, false, false) suite.Nil(err) } @@ -245,7 +245,7 @@ func (suite *RegistryClientTestSuite) Test_8_ManInTheMiddle() { suite.Nil(err) // returns content that does not match the expected digest - err = suite.RegistryClient.PullChart(ref) + err = suite.RegistryClient.PullChart(ref, false, false) suite.NotNil(err) suite.True(errdefs.IsFailedPrecondition(err)) } diff --git a/pkg/action/chart_pull.go b/pkg/action/chart_pull.go index 97abde7cc..8c719d7cb 100644 --- a/pkg/action/chart_pull.go +++ b/pkg/action/chart_pull.go @@ -35,10 +35,10 @@ func NewChartPull(cfg *Configuration) *ChartPull { } // Run executes the chart pull operation -func (a *ChartPull) Run(out io.Writer, ref string) error { +func (a *ChartPull) Run(out io.Writer, ref string, insecure bool, plainHTTP bool) error { r, err := registry.ParseReference(ref) if err != nil { return err } - return a.cfg.RegistryClient.PullChart(r) + return a.cfg.RegistryClient.PullChart(r, insecure, plainHTTP) } diff --git a/pkg/action/chart_push.go b/pkg/action/chart_push.go index 91ec49d38..707d6a59b 100644 --- a/pkg/action/chart_push.go +++ b/pkg/action/chart_push.go @@ -35,10 +35,10 @@ func NewChartPush(cfg *Configuration) *ChartPush { } // Run executes the chart push operation -func (a *ChartPush) Run(out io.Writer, ref string) error { +func (a *ChartPush) Run(out io.Writer, ref string, insecure bool, plainHTTP bool) error { r, err := registry.ParseReference(ref) if err != nil { return err } - return a.cfg.RegistryClient.PushChart(r) + return a.cfg.RegistryClient.PushChart(r, insecure, plainHTTP) }