Skip to content

Commit 9b911a2

Browse files
committed
Add TLS configuration support for machineset controller webhooks
Introduce command-line flags for TLS cipher suites and minimum version in the machineset controller. Update the container creation logic to utilize these TLS settings
1 parent 5d8f69d commit 9b911a2

3 files changed

Lines changed: 120 additions & 6 deletions

File tree

cmd/machineset/main.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"crypto/tls"
2021
"flag"
2122
"fmt"
2223
"log"
@@ -29,6 +30,7 @@ import (
2930
osconfigv1 "github.com/openshift/api/config/v1"
3031
apifeatures "github.com/openshift/api/features"
3132
machinev1 "github.com/openshift/api/machine/v1beta1"
33+
utiltls "github.com/openshift/controller-runtime-common/pkg/tls"
3234
mapiwebhooks "github.com/openshift/machine-api-operator/pkg/webhooks"
3335

3436
"k8s.io/apiserver/pkg/util/feature"
@@ -85,6 +87,12 @@ func main() {
8587
webhookCertdir := flag.String("webhook-cert-dir", defaultWebhookCertdir,
8688
"Webhook cert dir, only used when webhook-enabled is true.")
8789

90+
tlsCipherSuites := flag.String("tls-cipher-suites", "",
91+
"Comma-separated list of TLS cipher suites.")
92+
93+
tlsMinVersion := flag.String("tls-min-version", "",
94+
"Minimum TLS version supported.")
95+
8896
healthAddr := flag.String(
8997
"health-addr",
9098
":9441",
@@ -159,9 +167,19 @@ func main() {
159167
}
160168

161169
if *webhookEnabled {
170+
tlsProfile := osconfigv1.TLSProfileSpec{
171+
MinTLSVersion: osconfigv1.TLSProtocolVersion(*tlsMinVersion),
172+
}
173+
if *tlsCipherSuites != "" {
174+
tlsProfile.Ciphers = strings.Split(*tlsCipherSuites, ",")
175+
}
176+
177+
tlsOpts, _ := utiltls.NewTLSConfigFromProfile(tlsProfile)
178+
162179
opts.WebhookServer = webhook.NewServer(webhook.Options{
163180
Port: *webhookPort,
164181
CertDir: *webhookCertdir,
182+
TLSOpts: []func(*tls.Config){tlsOpts},
165183
})
166184
}
167185

pkg/operator/sync.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,10 @@ func newRBACConfigVolumes() []corev1.Volume {
511511
}
512512

513513
func newPodTemplateSpec(config *OperatorConfig, features map[string]bool) *corev1.PodTemplateSpec {
514-
containers := newContainers(config, features)
514+
tlsArgs := getTLSArgs(config.TLSProfile)
515+
containers := newContainers(config, features, tlsArgs)
515516
withMHCProxy := config.Controllers.MachineHealthCheck != ""
516-
proxyContainers := newKubeProxyContainers(config.Controllers.KubeRBACProxy, withMHCProxy, config.TLSProfile)
517+
proxyContainers := newKubeProxyContainers(config.Controllers.KubeRBACProxy, withMHCProxy, tlsArgs)
517518
tolerations := []corev1.Toleration{
518519
{
519520
Key: "node-role.kubernetes.io/master",
@@ -655,7 +656,7 @@ func buildFeatureGatesString(featureGates map[string]bool) string {
655656
return "--feature-gates=" + strings.Join(parts, ",")
656657
}
657658

658-
func newContainers(config *OperatorConfig, features map[string]bool) []corev1.Container {
659+
func newContainers(config *OperatorConfig, features map[string]bool, tlsArgs []string) []corev1.Container {
659660
resources := corev1.ResourceRequirements{
660661
Requests: map[corev1.ResourceName]resource.Quantity{
661662
corev1.ResourceMemory: resource.MustParse("20Mi"),
@@ -680,14 +681,17 @@ func newContainers(config *OperatorConfig, features map[string]bool) []corev1.Co
680681
machineControllerArgs = append(machineControllerArgs, "--max-concurrent-reconciles=10")
681682
}
682683

684+
machineSetControllerArgs := append([]string{}, featureGateArgs...)
685+
machineSetControllerArgs = append(machineSetControllerArgs, tlsArgs...)
686+
683687
proxyEnvArgs := getProxyArgs(config)
684688

685689
containers := []corev1.Container{
686690
{
687691
Name: "machineset-controller",
688692
Image: config.Controllers.MachineSet,
689693
Command: []string{"/machineset-controller"},
690-
Args: featureGateArgs,
694+
Args: machineSetControllerArgs,
691695
Resources: resources,
692696
Env: proxyEnvArgs,
693697
Ports: []corev1.ContainerPort{
@@ -856,7 +860,7 @@ func newContainers(config *OperatorConfig, features map[string]bool) []corev1.Co
856860
return containers
857861
}
858862

859-
func newKubeProxyContainers(image string, withMHCProxy bool, tlsProfile configv1.TLSProfileSpec) []corev1.Container {
863+
func getTLSArgs(tlsProfile configv1.TLSProfileSpec) []string {
860864
// Compute TLS arguments once from the profile
861865
tlsConfigFn, _ := utiltls.NewTLSConfigFromProfile(tlsProfile)
862866
tlsConf := &tls.Config{}
@@ -870,6 +874,10 @@ func newKubeProxyContainers(image string, withMHCProxy bool, tlsProfile configv1
870874
}
871875
tlsArgs = append(tlsArgs, fmt.Sprintf("--tls-min-version=%s", tlsProfile.MinTLSVersion))
872876

877+
return tlsArgs
878+
}
879+
880+
func newKubeProxyContainers(image string, withMHCProxy bool, tlsArgs []string) []corev1.Container {
873881
proxyContainers := []corev1.Container{
874882
newKubeProxyContainer(image, "machineset-mtrc", metrics.DefaultMachineSetMetricsAddress, machineSetExposeMetricsPort, tlsArgs),
875883
newKubeProxyContainer(image, "machine-mtrc", metrics.DefaultMachineMetricsAddress, machineExposeMetricsPort, tlsArgs),

pkg/operator/sync_test.go

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ func TestNewKubeProxyContainers(t *testing.T) {
574574
t.Run(tc.name, func(t *testing.T) {
575575
g := NewWithT(t)
576576

577-
containers := newKubeProxyContainers(tc.image, tc.withMHCProxy, tc.tlsProfile)
577+
containers := newKubeProxyContainers(tc.image, tc.withMHCProxy, getTLSArgs(tc.tlsProfile))
578578

579579
// Verify we get the expected number of containers
580580
g.Expect(containers).To(HaveLen(len(tc.expectedPorts)))
@@ -617,3 +617,91 @@ func TestNewKubeProxyContainers(t *testing.T) {
617617
})
618618
}
619619
}
620+
621+
func TestNewContainersTLSArgs(t *testing.T) {
622+
testCases := []struct {
623+
name string
624+
config *OperatorConfig
625+
tlsProfile configv1.TLSProfileSpec
626+
}{
627+
{
628+
name: "TLS 1.2 with cipher suites",
629+
config: &OperatorConfig{
630+
TargetNamespace: targetNamespace,
631+
PlatformType: configv1.AWSPlatformType,
632+
Controllers: Controllers{
633+
Provider: "provider-image:latest",
634+
MachineSet: "machineset-image:latest",
635+
NodeLink: "nodelink-image:latest",
636+
MachineHealthCheck: "mhc-image:latest",
637+
},
638+
},
639+
tlsProfile: configv1.TLSProfileSpec{
640+
Ciphers: []string{
641+
"ECDHE-ECDSA-AES128-GCM-SHA256",
642+
"ECDHE-RSA-AES128-GCM-SHA256",
643+
},
644+
MinTLSVersion: configv1.VersionTLS12,
645+
},
646+
},
647+
{
648+
name: "TLS 1.3 without cipher suites",
649+
config: &OperatorConfig{
650+
TargetNamespace: targetNamespace,
651+
PlatformType: configv1.GCPPlatformType,
652+
Controllers: Controllers{
653+
Provider: "provider-image:latest",
654+
MachineSet: "machineset-image:latest",
655+
NodeLink: "nodelink-image:latest",
656+
MachineHealthCheck: "",
657+
},
658+
},
659+
tlsProfile: configv1.TLSProfileSpec{
660+
Ciphers: []string{},
661+
MinTLSVersion: configv1.VersionTLS13,
662+
},
663+
},
664+
}
665+
666+
for _, tc := range testCases {
667+
t.Run(tc.name, func(t *testing.T) {
668+
g := NewWithT(t)
669+
670+
tlsArgs := getTLSArgs(tc.tlsProfile)
671+
containers := newContainers(tc.config, map[string]bool{}, tlsArgs)
672+
673+
containerArgs := map[string][]string{}
674+
for _, c := range containers {
675+
containerArgs[c.Name] = c.Args
676+
}
677+
678+
g.Expect(containerArgs).To(HaveKey("machineset-controller"))
679+
g.Expect(containerArgs).To(HaveKey("machine-controller"))
680+
g.Expect(containerArgs).To(HaveKey("nodelink-controller"))
681+
682+
// Only machineset-controller should receive TLS args.
683+
machineSetJoined := strings.Join(containerArgs["machineset-controller"], " ")
684+
g.Expect(machineSetJoined).To(ContainSubstring("--tls-min-version="+string(tc.tlsProfile.MinTLSVersion)),
685+
"machineset-controller should have --tls-min-version")
686+
if len(tc.tlsProfile.Ciphers) > 0 {
687+
g.Expect(machineSetJoined).To(ContainSubstring("--tls-cipher-suites="),
688+
"machineset-controller should have --tls-cipher-suites when ciphers are specified")
689+
}
690+
691+
for _, name := range []string{"machine-controller", "nodelink-controller"} {
692+
joined := strings.Join(containerArgs[name], " ")
693+
g.Expect(joined).ToNot(ContainSubstring("--tls-min-version="),
694+
"%s should not have TLS args", name)
695+
g.Expect(joined).ToNot(ContainSubstring("--tls-cipher-suites="),
696+
"%s should not have TLS args", name)
697+
}
698+
699+
if tc.config.Controllers.MachineHealthCheck != "" {
700+
g.Expect(containerArgs).To(HaveKey("machine-healthcheck-controller"))
701+
mhcJoined := strings.Join(containerArgs["machine-healthcheck-controller"], " ")
702+
g.Expect(mhcJoined).ToNot(ContainSubstring("--tls-min-version="),
703+
"machine-healthcheck-controller should not have TLS args")
704+
}
705+
})
706+
}
707+
}

0 commit comments

Comments
 (0)