Skip to content

Commit 28d232c

Browse files
committed
add ability to configure mTLS on LBC webhook
1 parent 3979361 commit 28d232c

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,11 @@ func main() {
140140
setupLog.Error(err, "unable to build REST config")
141141
os.Exit(1)
142142
}
143-
rtOpts := config.BuildRuntimeOptions(controllerCFG.RuntimeConfig, scheme)
143+
rtOpts, err := config.BuildRuntimeOptions(controllerCFG.RuntimeConfig, scheme)
144+
if err != nil {
145+
setupLog.Error(err, "unable to build runtime options")
146+
os.Exit(1)
147+
}
144148
mgr, err := ctrl.NewManager(restCFG, rtOpts)
145149
if err != nil {
146150
setupLog.Error(err, "unable to start manager")

pkg/config/runtime_config.go

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package config
22

33
import (
44
"crypto/tls"
5+
"crypto/x509"
6+
"github.com/pkg/errors"
7+
"os"
58
"time"
69

710
"github.com/spf13/pflag"
@@ -30,6 +33,7 @@ const (
3033
flagWebhookCertDir = "webhook-cert-dir"
3134
flagWebhookCertName = "webhook-cert-file"
3235
flagWebhookKeyName = "webhook-key-file"
36+
flagKubernetesCaPemFilepath = "kube-ca-pem-filepath"
3337

3438
defaultKubeconfig = ""
3539
defaultLeaderElectionID = "aws-load-balancer-controller-leader"
@@ -65,6 +69,7 @@ type RuntimeConfig struct {
6569
WebhookCertDir string
6670
WebhookCertName string
6771
WebhookKeyName string
72+
KubernetesCaPemFilePath string
6873
}
6974

7075
// BindFlags binds the command line flags to the fields in the config object
@@ -91,6 +96,7 @@ func (c *RuntimeConfig) BindFlags(fs *pflag.FlagSet) {
9196
fs.StringVar(&c.WebhookCertDir, flagWebhookCertDir, defaultWebhookCertDir, "WebhookCertDir is the directory that contains the webhook server key and certificate.")
9297
fs.StringVar(&c.WebhookCertName, flagWebhookCertName, defaultWebhookCertName, "WebhookCertName is the webhook server certificate name.")
9398
fs.StringVar(&c.WebhookKeyName, flagWebhookKeyName, defaultWebhookKeyName, "WebhookKeyName is the webhook server key name.")
99+
fs.StringVar(&c.KubernetesCaPemFilePath, flagKubernetesCaPemFilepath, "", "Location of Kubernetes CA file on disk.")
94100

95101
}
96102

@@ -115,7 +121,39 @@ func BuildRestConfig(rtCfg RuntimeConfig) (*rest.Config, error) {
115121
}
116122

117123
// BuildRuntimeOptions builds the options for the controller runtime based on config
118-
func BuildRuntimeOptions(rtCfg RuntimeConfig, scheme *runtime.Scheme) ctrl.Options {
124+
func BuildRuntimeOptions(rtCfg RuntimeConfig, scheme *runtime.Scheme) (ctrl.Options, error) {
125+
baseOpts := []func(config *tls.Config){
126+
func(config *tls.Config) {
127+
config.MinVersion = tls.VersionTLS12
128+
config.CipherSuites = []uint16{
129+
// AEADs w/ ECDHE
130+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
131+
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
132+
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
133+
134+
// AEADs w/o ECDHE
135+
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
136+
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
137+
}
138+
},
139+
}
140+
141+
if rtCfg.KubernetesCaPemFilePath != "" {
142+
caCertPool := x509.NewCertPool()
143+
data, err := os.ReadFile(rtCfg.KubernetesCaPemFilePath)
144+
if err != nil {
145+
return ctrl.Options{}, err
146+
}
147+
if !caCertPool.AppendCertsFromPEM(data) {
148+
return ctrl.Options{}, errors.Errorf("Unable to append CA PEM to pool")
149+
}
150+
// This ensures that only the CA configured in the LBC options is allowed to invoke the webhook.
151+
baseOpts = append(baseOpts, func(config *tls.Config) {
152+
config.ClientCAs = caCertPool
153+
config.ClientAuth = tls.RequireAndVerifyClientCert
154+
})
155+
}
156+
119157
opt := ctrl.Options{
120158
Scheme: scheme,
121159
HealthProbeBindAddress: rtCfg.HealthProbeBindAddress,
@@ -139,21 +177,7 @@ func BuildRuntimeOptions(rtCfg RuntimeConfig, scheme *runtime.Scheme) ctrl.Optio
139177
CertDir: rtCfg.WebhookCertDir,
140178
CertName: rtCfg.WebhookCertName,
141179
KeyName: rtCfg.WebhookKeyName,
142-
TLSOpts: []func(config *tls.Config){
143-
func(config *tls.Config) {
144-
config.MinVersion = tls.VersionTLS12
145-
config.CipherSuites = []uint16{
146-
// AEADs w/ ECDHE
147-
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
148-
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
149-
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
150-
151-
// AEADs w/o ECDHE
152-
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
153-
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
154-
}
155-
},
156-
},
180+
TLSOpts: baseOpts,
157181
}),
158182
}
159183

@@ -165,5 +189,5 @@ func BuildRuntimeOptions(rtCfg RuntimeConfig, scheme *runtime.Scheme) ctrl.Optio
165189
}
166190
}
167191

168-
return opt
192+
return opt, nil
169193
}

0 commit comments

Comments
 (0)