Commit a8e09833 authored by Brian's avatar Brian Committed by GitHub

Merge pull request #2108 from fibonacci1729/feat/tls

feat/tls: Support optional TLS for helm / tiller
parents f958b3be 735f4e3d
...@@ -87,10 +87,3 @@ func (g *getCmd) run() error { ...@@ -87,10 +87,3 @@ func (g *getCmd) run() error {
} }
return printRelease(g.out, res.Release) return printRelease(g.out, res.Release)
} }
func ensureHelmClient(h helm.Interface) helm.Interface {
if h != nil {
return h
}
return helm.NewClient(helm.Host(tillerHost))
}
...@@ -32,10 +32,12 @@ import ( ...@@ -32,10 +32,12 @@ import (
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/helm/portforwarder" "k8s.io/helm/pkg/helm/portforwarder"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/tiller/environment"
"k8s.io/helm/pkg/tlsutil"
) )
const ( const (
...@@ -95,6 +97,11 @@ func newRootCmd(out io.Writer) *cobra.Command { ...@@ -95,6 +97,11 @@ func newRootCmd(out io.Writer) *cobra.Command {
Short: "The Helm package manager for Kubernetes.", Short: "The Helm package manager for Kubernetes.",
Long: globalUsage, Long: globalUsage,
SilenceUsage: true, SilenceUsage: true,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
tlsCaCertFile = os.ExpandEnv(tlsCaCertFile)
tlsCertFile = os.ExpandEnv(tlsCertFile)
tlsKeyFile = os.ExpandEnv(tlsKeyFile)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) { PersistentPostRun: func(cmd *cobra.Command, args []string) {
teardown() teardown()
}, },
...@@ -120,21 +127,21 @@ func newRootCmd(out io.Writer) *cobra.Command { ...@@ -120,21 +127,21 @@ func newRootCmd(out io.Writer) *cobra.Command {
newVerifyCmd(out), newVerifyCmd(out),
// release commands // release commands
newDeleteCmd(nil, out), addFlagsTLS(newDeleteCmd(nil, out)),
newGetCmd(nil, out), addFlagsTLS(newGetCmd(nil, out)),
newHistoryCmd(nil, out), addFlagsTLS(newHistoryCmd(nil, out)),
newInstallCmd(nil, out), addFlagsTLS(newInstallCmd(nil, out)),
newListCmd(nil, out), addFlagsTLS(newListCmd(nil, out)),
newRollbackCmd(nil, out), addFlagsTLS(newRollbackCmd(nil, out)),
newStatusCmd(nil, out), addFlagsTLS(newStatusCmd(nil, out)),
newUpgradeCmd(nil, out), addFlagsTLS(newUpgradeCmd(nil, out)),
newCompletionCmd(out), newCompletionCmd(out),
newHomeCmd(out), newHomeCmd(out),
newInitCmd(out), newInitCmd(out),
newResetCmd(nil, out), addFlagsTLS(newResetCmd(nil, out)),
newVersionCmd(nil, out), addFlagsTLS(newVersionCmd(nil, out)),
newReleaseTestCmd(nil, out), addFlagsTLS(newReleaseTestCmd(nil, out)),
// Hidden documentation generator command: 'helm docs' // Hidden documentation generator command: 'helm docs'
newDocsCmd(out), newDocsCmd(out),
...@@ -229,7 +236,9 @@ func defaultHelmHome() string { ...@@ -229,7 +236,9 @@ func defaultHelmHome() string {
} }
func homePath() string { func homePath() string {
return os.ExpandEnv(helmHome) s := os.ExpandEnv(helmHome)
os.Setenv(homeEnvVar, s)
return s
} }
func defaultHelmHost() string { func defaultHelmHost() string {
...@@ -262,3 +271,49 @@ func getKubeClient(context string) (*restclient.Config, *internalclientset.Clien ...@@ -262,3 +271,49 @@ func getKubeClient(context string) (*restclient.Config, *internalclientset.Clien
func getKubeCmd(context string) *kube.Client { func getKubeCmd(context string) *kube.Client {
return kube.New(kube.GetConfig(context)) return kube.New(kube.GetConfig(context))
} }
// ensureHelmClient returns a new helm client impl. if h is not nil.
func ensureHelmClient(h helm.Interface) helm.Interface {
if h != nil {
return h
}
return newClient()
}
func newClient() helm.Interface {
options := []helm.Option{helm.Host(tillerHost)}
if tlsVerify || tlsEnable {
tlsopts := tlsutil.Options{KeyFile: tlsKeyFile, CertFile: tlsCertFile, InsecureSkipVerify: true}
if tlsVerify {
tlsopts.CaCertFile = tlsCaCertFile
tlsopts.InsecureSkipVerify = false
}
tlscfg, err := tlsutil.ClientConfig(tlsopts)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
options = append(options, helm.WithTLS(tlscfg))
}
return helm.NewClient(options...)
}
// addFlagsTLS adds the flags for supporting client side TLS to the
// helm command (only those that invoke communicate to Tiller.)
func addFlagsTLS(cmd *cobra.Command) *cobra.Command {
// defaults
var (
tlsCaCertDefault = "$HELM_HOME/ca.pem"
tlsCertDefault = "$HELM_HOME/cert.pem"
tlsKeyDefault = "$HELM_HOME/key.pem"
)
// add flags
cmd.Flags().StringVar(&tlsCaCertFile, "tls-ca-cert", tlsCaCertDefault, "path to TLS CA certificate file")
cmd.Flags().StringVar(&tlsCertFile, "tls-cert", tlsCertDefault, "path to TLS certificate file")
cmd.Flags().StringVar(&tlsKeyFile, "tls-key", tlsKeyDefault, "path to TLS key file")
cmd.Flags().BoolVar(&tlsVerify, "tls-verify", false, "enable TLS for request and verify remote")
cmd.Flags().BoolVar(&tlsEnable, "tls", false, "enable TLS for request")
return cmd
}
...@@ -102,11 +102,11 @@ func newInitCmd(out io.Writer) *cobra.Command { ...@@ -102,11 +102,11 @@ func newInitCmd(out io.Writer) *cobra.Command {
f.BoolVar(&i.dryRun, "dry-run", false, "do not install local or remote") f.BoolVar(&i.dryRun, "dry-run", false, "do not install local or remote")
f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache") f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache")
// f.BoolVar(&tlsEnable, "tiller-tls", false, "install tiller with TLS enabled") f.BoolVar(&tlsEnable, "tiller-tls", false, "install tiller with TLS enabled")
// f.BoolVar(&tlsVerify, "tiller-tls-verify", false, "install tiller with TLS enabled and to verify remote certificates") f.BoolVar(&tlsVerify, "tiller-tls-verify", false, "install tiller with TLS enabled and to verify remote certificates")
// f.StringVar(&tlsKeyFile, "tiller-tls-key", "", "path to TLS key file to install with tiller") f.StringVar(&tlsKeyFile, "tiller-tls-key", "", "path to TLS key file to install with tiller")
// f.StringVar(&tlsCertFile, "tiller-tls-cert", "", "path to TLS certificate file to install with tiller") f.StringVar(&tlsCertFile, "tiller-tls-cert", "", "path to TLS certificate file to install with tiller")
// f.StringVar(&tlsCaCertFile, "tls-ca-cert", "", "path to CA root certificate") f.StringVar(&tlsCaCertFile, "tls-ca-cert", "", "path to CA root certificate")
return cmd return cmd
} }
......
...@@ -17,25 +17,42 @@ limitations under the License. ...@@ -17,25 +17,42 @@ limitations under the License.
package main // import "k8s.io/helm/cmd/tiller" package main // import "k8s.io/helm/cmd/tiller"
import ( import (
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
"net/http" "net/http"
"os" "os"
"path/filepath"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/proto/hapi/services" "k8s.io/helm/pkg/proto/hapi/services"
"k8s.io/helm/pkg/storage" "k8s.io/helm/pkg/storage"
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
"k8s.io/helm/pkg/tiller" "k8s.io/helm/pkg/tiller"
"k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/tiller/environment"
"k8s.io/helm/pkg/tlsutil"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"
) )
const (
// tlsEnableEnvVar names the environment variable that enables TLS.
tlsEnableEnvVar = "TILLER_TLS_ENABLE"
// tlsVerifyEnvVar names the environment variable that enables
// TLS, as well as certificate verification of the remote.
tlsVerifyEnvVar = "TILLER_TLS_VERIFY"
// tlsCertsEnvVar names the environment variable that points to
// the directory where Tiller's TLS certificates are located.
tlsCertsEnvVar = "TILLER_TLS_CERTS"
)
const ( const (
storageMemory = "memory" storageMemory = "memory"
storageConfigMap = "configmap" storageConfigMap = "configmap"
...@@ -44,7 +61,7 @@ const ( ...@@ -44,7 +61,7 @@ const (
// rootServer is the root gRPC server. // rootServer is the root gRPC server.
// //
// Each gRPC service registers itself to this server during init(). // Each gRPC service registers itself to this server during init().
var rootServer = tiller.NewServer() var rootServer *grpc.Server
// env is the default environment. // env is the default environment.
// //
...@@ -59,6 +76,14 @@ var ( ...@@ -59,6 +76,14 @@ var (
store = storageConfigMap store = storageConfigMap
) )
var (
tlsEnable bool
tlsVerify bool
keyFile string
certFile string
caCertFile string
)
const globalUsage = `The Kubernetes Helm server. const globalUsage = `The Kubernetes Helm server.
Tiller is the server for Helm. It provides in-cluster resource management. Tiller is the server for Helm. It provides in-cluster resource management.
...@@ -83,6 +108,12 @@ func main() { ...@@ -83,6 +108,12 @@ func main() {
p.StringVar(&store, "storage", storageConfigMap, "storage driver to use. One of 'configmap' or 'memory'") p.StringVar(&store, "storage", storageConfigMap, "storage driver to use. One of 'configmap' or 'memory'")
p.BoolVar(&enableTracing, "trace", false, "enable rpc tracing") p.BoolVar(&enableTracing, "trace", false, "enable rpc tracing")
p.BoolVar(&tlsEnable, "tls", tlsEnableEnvVarDefault(), "enable TLS")
p.BoolVar(&tlsVerify, "tls-verify", tlsVerifyEnvVarDefault(), "enable TLS and verify remote certificate")
p.StringVar(&keyFile, "tls-key", tlsDefaultsFromEnv("tls-key"), "path to TLS private key file")
p.StringVar(&certFile, "tls-cert", tlsDefaultsFromEnv("tls-cert"), "path to TLS certificate file")
p.StringVar(&caCertFile, "tls-ca-cert", tlsDefaultsFromEnv("tls-ca-cert"), "trust certificates signed by this CA")
if err := rootCommand.Execute(); err != nil { if err := rootCommand.Execute(); err != nil {
fmt.Fprint(os.Stderr, err) fmt.Fprint(os.Stderr, err)
os.Exit(1) os.Exit(1)
...@@ -103,13 +134,33 @@ func start(c *cobra.Command, args []string) { ...@@ -103,13 +134,33 @@ func start(c *cobra.Command, args []string) {
env.Releases = storage.Init(driver.NewConfigMaps(clientset.Core().ConfigMaps(namespace()))) env.Releases = storage.Init(driver.NewConfigMaps(clientset.Core().ConfigMaps(namespace())))
} }
if tlsEnable || tlsVerify {
opts := tlsutil.Options{CertFile: certFile, KeyFile: keyFile}
if tlsVerify {
opts.CaCertFile = caCertFile
}
}
var opts []grpc.ServerOption
if tlsEnable || tlsVerify {
cfg, err := tlsutil.ServerConfig(tlsOptions())
if err != nil {
fmt.Fprintf(os.Stderr, "Could not create server TLS configuration: %v\n", err)
os.Exit(1)
}
opts = append(opts, grpc.Creds(credentials.NewTLS(cfg)))
}
rootServer = tiller.NewServer(opts...)
lstn, err := net.Listen("tcp", grpcAddr) lstn, err := net.Listen("tcp", grpcAddr)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Server died: %s\n", err) fmt.Fprintf(os.Stderr, "Server died: %s\n", err)
os.Exit(1) os.Exit(1)
} }
fmt.Printf("Starting Tiller %s\n", version.GetVersion()) fmt.Printf("Starting Tiller %s (tls=%t)\n", version.GetVersion(), tlsEnable || tlsVerify)
fmt.Printf("GRPC listening on %s\n", grpcAddr) fmt.Printf("GRPC listening on %s\n", grpcAddr)
fmt.Printf("Probes listening on %s\n", probeAddr) fmt.Printf("Probes listening on %s\n", probeAddr)
fmt.Printf("Storage driver is %s\n", env.Releases.Name()) fmt.Printf("Storage driver is %s\n", env.Releases.Name())
...@@ -159,3 +210,27 @@ func namespace() string { ...@@ -159,3 +210,27 @@ func namespace() string {
return environment.DefaultTillerNamespace return environment.DefaultTillerNamespace
} }
func tlsOptions() tlsutil.Options {
opts := tlsutil.Options{CertFile: certFile, KeyFile: keyFile}
if tlsVerify {
opts.CaCertFile = caCertFile
opts.ClientAuth = tls.RequireAndVerifyClientCert
}
return opts
}
func tlsDefaultsFromEnv(name string) (value string) {
switch certsDir := os.Getenv(tlsCertsEnvVar); name {
case "tls-key":
return filepath.Join(certsDir, "tls.key")
case "tls-cert":
return filepath.Join(certsDir, "tls.crt")
case "tls-ca-cert":
return filepath.Join(certsDir, "ca.crt")
}
return ""
}
func tlsEnableEnvVarDefault() bool { return os.Getenv(tlsEnableEnvVar) != "" }
func tlsVerifyEnvVarDefault() bool { return os.Getenv(tlsVerifyEnvVar) != "" }
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
...@@ -279,9 +280,28 @@ func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-ch ...@@ -279,9 +280,28 @@ func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-ch
return h.test(ctx, req) return h.test(ctx, req)
} }
// connect returns a grpc connection to tiller or error. The grpc dial options
// are constructed here.
func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error) {
opts := []grpc.DialOption{
grpc.WithTimeout(5 * time.Second),
grpc.WithBlock(),
}
switch {
case h.opts.useTLS:
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(h.opts.tlsConfig)))
default:
opts = append(opts, grpc.WithInsecure())
}
if conn, err = grpc.Dial(h.opts.host, opts...); err != nil {
return nil, err
}
return conn, nil
}
// Executes tiller.ListReleases RPC. // Executes tiller.ListReleases RPC.
func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) { func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -298,7 +318,7 @@ func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.L ...@@ -298,7 +318,7 @@ func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.L
// Executes tiller.InstallRelease RPC. // Executes tiller.InstallRelease RPC.
func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) { func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -310,7 +330,7 @@ func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (* ...@@ -310,7 +330,7 @@ func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*
// Executes tiller.UninstallRelease RPC. // Executes tiller.UninstallRelease RPC.
func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) { func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -322,7 +342,7 @@ func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) ( ...@@ -322,7 +342,7 @@ func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (
// Executes tiller.UpdateRelease RPC. // Executes tiller.UpdateRelease RPC.
func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) { func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -334,7 +354,7 @@ func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rl ...@@ -334,7 +354,7 @@ func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rl
// Executes tiller.RollbackRelease RPC. // Executes tiller.RollbackRelease RPC.
func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) { func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -346,7 +366,7 @@ func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) ...@@ -346,7 +366,7 @@ func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest)
// Executes tiller.GetReleaseStatus RPC. // Executes tiller.GetReleaseStatus RPC.
func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) { func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -358,7 +378,7 @@ func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) ( ...@@ -358,7 +378,7 @@ func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (
// Executes tiller.GetReleaseContent RPC. // Executes tiller.GetReleaseContent RPC.
func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) { func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -370,7 +390,7 @@ func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) ...@@ -370,7 +390,7 @@ func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest)
// Executes tiller.GetVersion RPC. // Executes tiller.GetVersion RPC.
func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) { func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure(), grpc.WithTimeout(5*time.Second), grpc.WithBlock()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -382,7 +402,7 @@ func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls. ...@@ -382,7 +402,7 @@ func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.
// Executes tiller.GetHistory RPC. // Executes tiller.GetHistory RPC.
func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) { func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) {
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -395,7 +415,7 @@ func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls. ...@@ -395,7 +415,7 @@ func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.
// Executes tiller.TestRelease RPC. // Executes tiller.TestRelease RPC.
func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) { func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) {
errc := make(chan error, 1) errc := make(chan error, 1)
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) c, err := h.connect(ctx)
if err != nil { if err != nil {
errc <- err errc <- err
return nil, errc return nil, errc
......
...@@ -17,6 +17,8 @@ limitations under the License. ...@@ -17,6 +17,8 @@ limitations under the License.
package helm package helm
import ( import (
"crypto/tls"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
...@@ -38,6 +40,8 @@ type options struct { ...@@ -38,6 +40,8 @@ type options struct {
host string host string
// if set dry-run helm client calls // if set dry-run helm client calls
dryRun bool dryRun bool
// if set enable TLS on helm client calls
useTLS bool
// if set, re-use an existing name // if set, re-use an existing name
reuseName bool reuseName bool
// if set, performs pod restart during upgrade/rollback // if set, performs pod restart during upgrade/rollback
...@@ -46,6 +50,8 @@ type options struct { ...@@ -46,6 +50,8 @@ type options struct {
disableHooks bool disableHooks bool
// name of release // name of release
releaseName string releaseName string
// tls.Config to use for rpc if tls enabled
tlsConfig *tls.Config
// release list options are applied directly to the list releases request // release list options are applied directly to the list releases request
listReq rls.ListReleasesRequest listReq rls.ListReleasesRequest
// release install options are applied directly to the install release request // release install options are applied directly to the install release request
...@@ -79,6 +85,14 @@ func Host(host string) Option { ...@@ -79,6 +85,14 @@ func Host(host string) Option {
} }
} }
// WithTLS specifies the tls configuration if the helm client is enabled to use TLS.
func WithTLS(cfg *tls.Config) Option {
return func(opts *options) {
opts.useTLS = true
opts.tlsConfig = cfg
}
}
// BeforeCall returns an option that allows intercepting a helm client rpc // BeforeCall returns an option that allows intercepting a helm client rpc
// before being sent OTA to tiller. The intercepting function should return // before being sent OTA to tiller. The intercepting function should return
// an error to indicate that the call should not proceed or nil otherwise. // an error to indicate that the call should not proceed or nil otherwise.
......
...@@ -32,13 +32,18 @@ import ( ...@@ -32,13 +32,18 @@ import (
// grpc library default is 4MB // grpc library default is 4MB
var maxMsgSize = 1024 * 1024 * 10 var maxMsgSize = 1024 * 1024 * 10
// NewServer creates a new grpc server. // DefaultServerOpts returns the set of default grpc ServerOption's that Tiller requires.
func NewServer() *grpc.Server { func DefaultServerOpts() []grpc.ServerOption {
return grpc.NewServer( return []grpc.ServerOption{
grpc.MaxMsgSize(maxMsgSize), grpc.MaxMsgSize(maxMsgSize),
grpc.UnaryInterceptor(newUnaryInterceptor()), grpc.UnaryInterceptor(newUnaryInterceptor()),
grpc.StreamInterceptor(newStreamInterceptor()), grpc.StreamInterceptor(newStreamInterceptor()),
) }
}
// NewServer creates a new grpc server.
func NewServer(opts ...grpc.ServerOption) *grpc.Server {
return grpc.NewServer(append(DefaultServerOpts(), opts...)...)
} }
func newUnaryInterceptor() grpc.UnaryServerInterceptor { func newUnaryInterceptor() grpc.UnaryServerInterceptor {
......
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tlsutil
import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"
)
// Options represents configurable options used to create client and server TLS configurations.
type Options struct {
CaCertFile string
// If either the KeyFile or CertFile is empty, ClientConfig() will not load them,
// preventing helm from authenticating to Tiller. They are required to be non-empty
// when calling ServerConfig, otherwise an error is returned.
KeyFile string
CertFile string
// Client-only options
InsecureSkipVerify bool
// Server-only options
ClientAuth tls.ClientAuthType
}
// ClientConfig retusn a TLS configuration for use by a Helm client.
func ClientConfig(opts Options) (cfg *tls.Config, err error) {
var cert *tls.Certificate
var pool *x509.CertPool
if opts.CertFile != "" || opts.KeyFile != "" {
if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil {
return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err)
}
}
if !opts.InsecureSkipVerify && opts.CaCertFile != "" {
if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil {
return nil, err
}
}
cfg = &tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify, Certificates: []tls.Certificate{*cert}, RootCAs: pool}
return cfg, nil
}
// ServerConfig returns a TLS configuration for use by the Tiller server.
func ServerConfig(opts Options) (cfg *tls.Config, err error) {
var cert *tls.Certificate
var pool *x509.CertPool
if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err)
}
return nil, fmt.Errorf("could not read x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err)
}
if opts.ClientAuth >= tls.VerifyClientCertIfGiven && opts.CaCertFile != "" {
if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil {
return nil, err
}
}
cfg = &tls.Config{MinVersion: tls.VersionTLS12, ClientAuth: opts.ClientAuth, Certificates: []tls.Certificate{*cert}, ClientCAs: pool}
return cfg, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment