Implement chart registry TLS configuration

* Implements --insecure-skip-tls-verify
* Implements custom cert, key and ca file

Solves https://github.com/helm/helm/issues/6324

Signed-off-by: Morten Linderud <morten@linderud.pw>
pull/7844/head
Morten Linderud 6 years ago
parent 193850a9e2
commit 6e3a147367
No known key found for this signature in database
GPG Key ID: E742683BA08CB2FF

@ -20,6 +20,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
) )
@ -30,6 +31,11 @@ The subcommands can be used to push, pull, tag, list, or remove Helm charts.
` `
func newChartCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newChartCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
var certFile string
var keyFile string
var caFile string
var insecureSkipTLSverify bool
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "chart", Use: "chart",
Short: "push, pull, tag, or remove Helm charts", Short: "push, pull, tag, or remove Helm charts",
@ -37,13 +43,39 @@ func newChartCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Hidden: !FeatureGateOCI.IsEnabled(), Hidden: !FeatureGateOCI.IsEnabled(),
PersistentPreRunE: checkOCIFeatureGate(), PersistentPreRunE: checkOCIFeatureGate(),
} }
cmd.AddCommand(
newChartListCmd(cfg, out), Cmds := []*cobra.Command{
newChartExportCmd(cfg, out),
newChartPullCmd(cfg, out), newChartPullCmd(cfg, out),
newChartPushCmd(cfg, out), newChartPushCmd(cfg, out),
newChartRemoveCmd(cfg, out), newChartRemoveCmd(cfg, out),
}
for _, subCmd := range Cmds {
f := subCmd.Flags()
f.StringVar(&certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
f.StringVar(&keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
f.StringVar(&caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&insecureSkipTLSverify, "insecure-skip-tls-verify", false, "skip tls certificate checks for the repository")
subCmd.PreRunE = func(cmd *cobra.Command, args []string) error {
registryClient, err := registry.NewClient(
registry.ClientOptDebug(settings.Debug),
registry.ClientOptWriter(out),
registry.ClientOptInsecureClient(insecureSkipTLSverify),
registry.ClientOptTLSConfig(certFile, keyFile, caFile),
)
if err != nil {
return err
}
cfg.RegistryClient = registryClient
return nil
}
}
// These commands does not need to have an initialized RegistryClient
cmd.AddCommand(
newChartListCmd(cfg, out),
newChartExportCmd(cfg, out),
newChartSaveCmd(cfg, out), newChartSaveCmd(cfg, out),
) )
cmd.AddCommand(Cmds...)
return cmd return cmd
} }

@ -27,7 +27,6 @@ import (
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"helm.sh/helm/v3/internal/completion" "helm.sh/helm/v3/internal/completion"
"helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
) )
@ -172,15 +171,6 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
) )
// Add *experimental* subcommands // Add *experimental* subcommands
registryClient, err := registry.NewClient(
registry.ClientOptDebug(settings.Debug),
registry.ClientOptWriter(out),
)
if err != nil {
// TODO: don't panic here, refactor newRootCmd to return error
panic(err)
}
actionConfig.RegistryClient = registryClient
cmd.AddCommand( cmd.AddCommand(
newRegistryCmd(actionConfig, out), newRegistryCmd(actionConfig, out),
newChartCmd(actionConfig, out), newChartCmd(actionConfig, out),

@ -18,6 +18,7 @@ package registry // import "helm.sh/helm/v3/internal/experimental/registry"
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -30,6 +31,7 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"helm.sh/helm/v3/internal/tlsutil"
"helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/helmpath"
) )
@ -42,11 +44,15 @@ const (
type ( type (
// Client works with OCI-compliant registries and local Helm chart cache // Client works with OCI-compliant registries and local Helm chart cache
Client struct { Client struct {
debug bool debug bool
out io.Writer certFile string
authorizer *Authorizer keyFile string
resolver *Resolver caFile string
cache *Cache insecureSkipTLSverify bool
out io.Writer
authorizer *Authorizer
resolver *Resolver
cache *Cache
} }
) )
@ -69,8 +75,32 @@ func NewClient(opts ...ClientOption) (*Client, error) {
Client: authClient, Client: authClient,
} }
} }
httpClient := http.DefaultClient
if (client.certFile != "" && client.keyFile != "") || client.caFile != "" {
tlsConf, err := tlsutil.NewClientTLS(client.certFile, client.keyFile, client.caFile)
if err != nil {
return nil, errors.Wrap(err, "can't create TLS config for client")
}
tlsConf.BuildNameToCertificate()
httpClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConf,
Proxy: http.ProxyFromEnvironment,
},
}
} else if client.insecureSkipTLSverify {
httpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
Proxy: http.ProxyFromEnvironment,
}
}
if client.resolver == nil { if client.resolver == nil {
resolver, err := client.authorizer.Resolver(context.Background(), http.DefaultClient, false) resolver, err := client.authorizer.Resolver(context.Background(), httpClient, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -60,3 +60,19 @@ func ClientOptCache(cache *Cache) ClientOption {
client.cache = cache client.cache = cache
} }
} }
// ClientOptInsecure returns a function that sets the insecure tls verify setting on a client options set
func ClientOptInsecureClient(insecureSkipTLSverify bool) ClientOption {
return func(client *Client) {
client.insecureSkipTLSverify = insecureSkipTLSverify
}
}
// ClientOptTLSConfig returns a function that sets the tls settings on a client options set
func ClientOptTLSConfig(certFile, keyFile, caFile string) ClientOption {
return func(client *Client) {
client.certFile = certFile
client.keyFile = keyFile
client.caFile = caFile
}
}

Loading…
Cancel
Save