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

Commit

Permalink
Merge pull request from GHSA-g677-5cc4-732g
Browse files Browse the repository at this point in the history
Add support for client verification via TLS certs.
  • Loading branch information
cpuguy83 authored Dec 3, 2020
2 parents 1ef86fc + 2124633 commit 8449de6
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 8449de6

Please sign in to comment.