Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Commit

Permalink
Add support for client verification via TLS certs.
Browse files Browse the repository at this point in the history
This makes the default require client verification, but can be disabled
with a flag.

In the future we should add support for token auth like
Kubelet supports.

Signed-off-by: Brian Goff <[email protected]>
  • Loading branch information
cpuguy83 committed Nov 30, 2020
1 parent 1ef86fc commit 2124633
Show file tree
Hide file tree
Showing 4 changed files with 410 additions and 10 deletions.
3 changes: 3 additions & 0 deletions internal/commands/root/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func installFlags(flags *pflag.FlagSet, c *opts.Opts) {
flags.Int32Var(&c.KubeAPIBurst, "kube-api-burst", c.KubeAPIBurst,
"kubeAPIBurst is the burst to allow while talking with kubernetes apiserver")

flags.StringVar(&c.ClientCACert, "client-verify-ca", os.Getenv("APISERVER_CA_CERT_LOCATION"), "CA cert to use to verify client requests")
flags.BoolVar(&c.AllowUnauthenticatedClients, "no-verify-clients", false, "Do not require client certificate validation")

flagset := flag.NewFlagSet("klog", flag.PanicOnError)
klog.InitFlags(flagset)
flagset.VisitAll(func(f *flag.Flag) {
Expand Down
53 changes: 43 additions & 10 deletions internal/commands/root/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ package root
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"os"
Expand All @@ -45,17 +47,39 @@ var AcceptedCiphers = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}

func loadTLSConfig(certPath, keyPath string) (*tls.Config, error) {
func loadTLSConfig(certPath, keyPath, caPath string, allowUnauthenticatedClients bool) (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return nil, errors.Wrap(err, "error loading tls certs")
}

var (
caPool *x509.CertPool
clientAuth = tls.RequireAndVerifyClientCert
)

if allowUnauthenticatedClients {
clientAuth = tls.NoClientCert
}

if caPath != "" {
caPool = x509.NewCertPool()
pem, err := ioutil.ReadFile(caPath)
if err != nil {
return nil, err
}
if !caPool.AppendCertsFromPEM(pem) {
return nil, errors.New("error appending ca cert to certificate pool")
}
}

return &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
CipherSuites: AcceptedCiphers,
ClientCAs: caPool,
ClientAuth: clientAuth,
}, nil
}

Expand All @@ -72,19 +96,20 @@ func setupHTTPServer(ctx context.Context, p provider.Provider, cfg *apiServerCon
}
}()

if cfg.CertPath == "" || cfg.KeyPath == "" {
if cfg.CertPath == "" || cfg.KeyPath == "" || (cfg.CACertPath == "" && !cfg.AllowUnauthenticatedClients) {
log.G(ctx).
WithField("certPath", cfg.CertPath).
WithField("keyPath", cfg.KeyPath).
WithField("caPath", cfg.CACertPath).
Error("TLS certificates not provided, not setting up pod http server")
} else {
tlsCfg, err := loadTLSConfig(cfg.CertPath, cfg.KeyPath)
tlsCfg, err := loadTLSConfig(cfg.CertPath, cfg.KeyPath, cfg.CACertPath, cfg.AllowUnauthenticatedClients)
if err != nil {
return nil, err
}
l, err := tls.Listen("tcp", cfg.Addr, tlsCfg)
if err != nil {
return nil, errors.Wrap(err, "error setting up listener for pod http server")
return nil, errors.Wrapf(err, "error setting up listener for pod http server: tlsconfig: \n%+v", tlsCfg)
}

mux := http.NewServeMux()
Expand Down Expand Up @@ -147,12 +172,14 @@ func serveHTTP(ctx context.Context, s *http.Server, l net.Listener, name string)
}

type apiServerConfig struct {
CertPath string
KeyPath string
Addr string
MetricsAddr string
StreamIdleTimeout time.Duration
StreamCreationTimeout time.Duration
CACertPath string
CertPath string
KeyPath string
Addr string
MetricsAddr string
StreamIdleTimeout time.Duration
StreamCreationTimeout time.Duration
AllowUnauthenticatedClients bool
}

func getAPIConfig(c *opts.Opts) (*apiServerConfig, error) {
Expand All @@ -165,6 +192,12 @@ func getAPIConfig(c *opts.Opts) (*apiServerConfig, error) {
config.MetricsAddr = c.MetricsAddr
config.StreamIdleTimeout = c.StreamIdleTimeout
config.StreamCreationTimeout = c.StreamCreationTimeout
config.AllowUnauthenticatedClients = c.AllowUnauthenticatedClients

config.CACertPath = c.ClientCACert
if c.ClientCACert == "" {
config.CACertPath = os.Getenv("APISERVER_CA_CERT_LOCATION")
}

return &config, nil
}
Loading

0 comments on commit 2124633

Please sign in to comment.