diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index 186a37cd1..4542e0b2f 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -65,11 +65,11 @@ Environment: $HELM_NO_PLUGINS disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins. $TILLER_NAMESPACE set an alternative Tiller namespace (default "kube-system") $KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config") - $HELM_TLS_CA_CERT path to TLS CA certificate file to verify Tiller server certificate (default "$HELM_HOME/ca.pem") + $HELM_TLS_CA_CERT path to TLS CA certificate used to verify the Helm client and Tiller server certificates (default "$HELM_HOME/ca.pem") $HELM_TLS_CERT path to TLS client certificate file for authenticating to Tiller (default "$HELM_HOME/cert.pem") - $HELM_TLS_KEY path to TLS cient key file for authenticating to Tiller (default "$HELM_HOME/key.pem") - $HELM_TLS_VERIFY enable TLS for request and verify remote (default "false") - $HELM_TLS_ENABLE enable TLS for request (default "false") + $HELM_TLS_KEY path to TLS client key file for authenticating to Tiller (default "$HELM_HOME/key.pem") + $HELM_TLS_VERIFY enable TLS connection between Helm and Tiller and verify Tiller server certificate (default "false") + $HELM_TLS_ENABLE enable TLS connection between Helm and Tiller (default "false") ` func newRootCmd(args []string) *cobra.Command { diff --git a/cmd/helm/init.go b/cmd/helm/init.go index fbff110e4..a793e032c 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -107,12 +107,8 @@ func newInitCmd(out io.Writer) *cobra.Command { } i.namespace = settings.TillerNamespace i.home = settings.Home - i.client = ensureHelmClient(i.client) - i.tlsEnable = settings.TLSEnable - i.tlsVerify = settings.TLSVerify - i.tlsKeyFile = settings.TLSKeyFile - i.tlsCertFile = settings.TLSCertFile i.tlsCaCertFile = settings.TLSCaCertFile + i.client = ensureHelmClient(i.client) return i.run() }, @@ -128,6 +124,11 @@ func newInitCmd(out io.Writer) *cobra.Command { f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache") f.BoolVar(&i.wait, "wait", false, "block until Tiller is running and ready to receive requests") + f.BoolVar(&i.tlsEnable, "tiller-tls", false, "install Tiller with TLS enabled") + f.BoolVar(&i.tlsVerify, "tiller-tls-verify", false, "install Tiller with TLS and Helm client certificate verification enabled") + f.StringVar(&i.tlsKeyFile, "tiller-tls-key", "", "path to Tiller TLS server key file") + f.StringVar(&i.tlsCertFile, "tiller-tls-cert", "", "path to Tiller TLS server certificate file") + f.StringVar(&stableRepositoryURL, "stable-repo-url", stableRepositoryURL, "URL for stable repository") f.StringVar(&localRepositoryURL, "local-repo-url", localRepositoryURL, "URL for local repository") @@ -154,10 +155,10 @@ func (i *initCmd) tlsOptions() error { return os.IsNotExist(err) } if i.opts.TLSKeyFile = i.tlsKeyFile; i.opts.TLSKeyFile == "" || missing(i.opts.TLSKeyFile) { - return errors.New("missing required TLS key file") + return errors.New("missing required TLS server key file") } if i.opts.TLSCertFile = i.tlsCertFile; i.opts.TLSCertFile == "" || missing(i.opts.TLSCertFile) { - return errors.New("missing required TLS certificate file") + return errors.New("missing required TLS server certificate file") } if i.opts.VerifyTLS { if i.opts.TLSCaCertFile = i.tlsCaCertFile; i.opts.TLSCaCertFile == "" || missing(i.opts.TLSCaCertFile) { diff --git a/cmd/helm/init_test.go b/cmd/helm/init_test.go index 4513315b7..b8a1d452d 100644 --- a/cmd/helm/init_test.go +++ b/cmd/helm/init_test.go @@ -280,13 +280,14 @@ func TestInitCmd_tlsOptions(t *testing.T) { } for _, tt := range tests { - // emulate tls file specific flags - tlsCaCertFile, tlsCertFile, tlsKeyFile = tt.caFile, tt.certFile, tt.keyFile - - // emulate tls enable/verify flags - tlsEnable, tlsVerify = tt.enable, tt.verify - - cmd := &initCmd{} + // emulate tls flags + cmd := &initCmd{ + tlsCaCertFile: tt.caFile, + tlsCertFile: tt.certFile, + tlsKeyFile: tt.keyFile, + tlsVerify: tt.verify, + tlsEnable: tt.enable, + } if err := cmd.tlsOptions(); err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/pkg/helm/environment/environment.go b/pkg/helm/environment/environment.go index 5166a15de..904a689a2 100644 --- a/pkg/helm/environment/environment.go +++ b/pkg/helm/environment/environment.go @@ -47,7 +47,7 @@ type EnvSettings struct { Debug bool // KubeContext is the name of the kubeconfig context. KubeContext string - // TLSCaCertFile is the path to TLS CA certificate file for Helm to verify the Tiller server certificate + // TLSCaCertFile is the path to TLS CA certificate file used to verify the Helm client and Tiller server certificates TLSCaCertFile string // TLSCertFile is the path to Helm TLS client certificate file for authenticating to Tiller TLSCertFile string @@ -66,7 +66,7 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.KubeContext, "kube-context", "", "name of the kubeconfig context to use") fs.BoolVar(&s.Debug, "debug", false, "enable verbose output") fs.StringVar(&s.TillerNamespace, "tiller-namespace", "kube-system", "namespace of Tiller") - fs.StringVar(&s.TLSCaCertFile, "tls-ca-cert", "", "path to TLS CA certificate file for Helm to verify Tiller server certificate") + fs.StringVar(&s.TLSCaCertFile, "tls-ca-cert", "", "path to TLS CA certificate file used to verify the Helm client and Tiller server certificates") fs.StringVar(&s.TLSCertFile, "tls-cert", "", "path to Helm TLS client certificate file for authenticating to Tiller") fs.StringVar(&s.TLSKeyFile, "tls-key", "", "path to Helm TLS client key file for authenticating to Tiller") fs.BoolVar(&s.TLSVerify, "tls-verify", false, "enable TLS connection between Helm and Tiller and verify Tiller server certificate") diff --git a/pkg/helm/environment/environment_test.go b/pkg/helm/environment/environment_test.go index 8f0caa388..19ccd9b40 100644 --- a/pkg/helm/environment/environment_test.go +++ b/pkg/helm/environment/environment_test.go @@ -37,42 +37,103 @@ func TestEnvSettings(t *testing.T) { // expected values home, host, ns, kcontext, plugins string debug bool + tlsca, tlscert, tlskey string + tlsenable, tlsverify bool }{ { - name: "defaults", - args: []string{}, - home: DefaultHelmHome, - plugins: helmpath.Home(DefaultHelmHome).Plugins(), - ns: "kube-system", + name: "defaults", + args: []string{}, + home: DefaultHelmHome, + plugins: helmpath.Home(DefaultHelmHome).Plugins(), + ns: "kube-system", + tlsca: helmpath.Home(DefaultHelmHome).TLSCaCert(), + tlscert: helmpath.Home(DefaultHelmHome).TLSCert(), + tlskey: helmpath.Home(DefaultHelmHome).TLSKey(), + tlsenable: false, + tlsverify: false, }, { - name: "with flags set", - args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, - home: "/foo", - plugins: helmpath.Home("/foo").Plugins(), - host: "here", - ns: "myns", - debug: true, + name: "with flags set", + args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, + home: "/foo", + plugins: helmpath.Home("/foo").Plugins(), + host: "here", + ns: "myns", + debug: true, + tlsca: helmpath.Home("/foo").TLSCaCert(), + tlscert: helmpath.Home("/foo").TLSCert(), + tlskey: helmpath.Home("/foo").TLSKey(), + tlsenable: false, + tlsverify: false, }, { - name: "with envvars set", - args: []string{}, - envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns"}, - home: "/bar", - plugins: helmpath.Home("/bar").Plugins(), - host: "there", - ns: "yourns", - debug: true, + name: "with envvars set", + args: []string{}, + envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns"}, + home: "/bar", + plugins: helmpath.Home("/bar").Plugins(), + host: "there", + ns: "yourns", + debug: true, + tlsca: helmpath.Home("/bar").TLSCaCert(), + tlscert: helmpath.Home("/bar").TLSCert(), + tlskey: helmpath.Home("/bar").TLSKey(), + tlsenable: false, + tlsverify: false, }, { - name: "with flags and envvars set", - args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, - envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"}, - home: "/foo", - plugins: "glade", - host: "here", - ns: "myns", - debug: true, + name: "with flags and envvars set", + args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, + envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"}, + home: "/foo", + plugins: "glade", + host: "here", + ns: "myns", + debug: true, + tlsca: helmpath.Home("/foo").TLSCaCert(), + tlscert: helmpath.Home("/foo").TLSCert(), + tlskey: helmpath.Home("/foo").TLSKey(), + tlsenable: false, + tlsverify: false, + }, + { + name: "with TLS flags set", + args: []string{"--home", "/bar", "--tls-ca-cert", "/a/ca.crt", "--tls-cert=/a/client.crt", "--tls-key", "/a/client.key", "--tls-verify", "--tls"}, + home: "/bar", + plugins: helmpath.Home("/bar").Plugins(), + ns: "kube-system", + debug: false, + tlsca: "/a/ca.crt", + tlscert: "/a/client.crt", + tlskey: "/a/client.key", + tlsenable: true, + tlsverify: true, + }, + { + name: "with TLS envvars set", + args: []string{}, + envars: map[string]string{"HELM_HOME": "/bar", "HELM_TLS_CA_CERT": "/e/ca.crt", "HELM_TLS_CERT": "/e/client.crt", "HELM_TLS_KEY": "/e/client.key", "HELM_TLS_VERIFY": "true", "HELM_TLS_ENABLE": "true"}, + home: "/bar", + plugins: helmpath.Home("/bar").Plugins(), + ns: "kube-system", + tlsca: "/e/ca.crt", + tlscert: "/e/client.crt", + tlskey: "/e/client.key", + tlsenable: true, + tlsverify: true, + }, + { + name: "with TLS flags and envvars set", + args: []string{"--tls-ca-cert", "/a/ca.crt", "--tls-cert=/a/client.crt", "--tls-key", "/a/client.key", "--tls-verify"}, + envars: map[string]string{"HELM_HOME": "/bar", "HELM_TLS_CA_CERT": "/e/ca.crt", "HELM_TLS_CERT": "/e/client.crt", "HELM_TLS_KEY": "/e/client.key", "HELM_TLS_VERIFY": "true", "HELM_TLS_ENABLE": "true"}, + home: "/bar", + plugins: helmpath.Home("/bar").Plugins(), + ns: "kube-system", + tlsca: "/a/ca.crt", + tlscert: "/a/client.crt", + tlskey: "/a/client.key", + tlsenable: true, + tlsverify: true, }, } @@ -111,7 +172,25 @@ func TestEnvSettings(t *testing.T) { if settings.KubeContext != tt.kcontext { t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext) } + if settings.TLSCaCertFile != tt.tlsca { + t.Errorf("expected tls-ca-cert %q, got %q", tt.tlsca, settings.TLSCaCertFile) + } + if settings.TLSCertFile != tt.tlscert { + t.Errorf("expected tls-cert %q, got %q", tt.tlscert, settings.TLSCertFile) + } + if settings.TLSKeyFile != tt.tlskey { + t.Errorf("expected tls-key %q, got %q", tt.tlskey, settings.TLSKeyFile) + } + if settings.TLSEnable != tt.tlsenable { + t.Errorf("expected tls %t, got %t", tt.tlsenable, settings.TLSEnable) + } + if settings.TLSVerify != tt.tlsverify { + t.Errorf("expected tls-verify %t, got %t", tt.tlsverify, settings.TLSVerify) + } + for k := range tt.envars { + os.Unsetenv(k) + } cleanup() }) }