Skip to content

Commit feb04b2

Browse files
committed
tls: use centralized TLS profile + operands
1 parent f4be3a4 commit feb04b2

3 files changed

Lines changed: 76 additions & 16 deletions

File tree

cmd/cluster-capi-operator/main.go

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package main
1515

1616
import (
1717
"context"
18+
"crypto/tls"
1819
"flag"
1920
"fmt"
2021
"os"
@@ -65,6 +66,7 @@ import (
6566
"github.com/openshift/cluster-capi-operator/pkg/operatorstatus"
6667
"github.com/openshift/cluster-capi-operator/pkg/util"
6768
"github.com/openshift/cluster-capi-operator/pkg/webhook"
69+
utiltls "github.com/openshift/library-go/pkg/controllerruntime/tls"
6870
)
6971

7072
const (
@@ -148,6 +150,29 @@ func main() {
148150
capiflags.AddManagerOptions(pflag.CommandLine, &capiManagerOptions)
149151
pflag.Parse()
150152

153+
cfg := ctrl.GetConfigOrDie()
154+
155+
k8sClient, err := client.New(cfg, client.Options{Scheme: scheme})
156+
if err != nil {
157+
klog.Error(err, "unable to create Kubernetes client")
158+
os.Exit(1)
159+
}
160+
161+
// Fetch the TLS profile from the APIServer resource.
162+
tlsSecurityProfileSpec, err := utiltls.FetchAPIServerTLSProfile(context.Background(), k8sClient)
163+
if err != nil {
164+
klog.Error(err, "unable to get TLS profile from API server")
165+
os.Exit(1)
166+
}
167+
168+
// Create the TLS configuration function for the server endpoints.
169+
tlsConfig, unsupportedCiphers := utiltls.NewTLSConfigFromProfile(tlsSecurityProfileSpec)
170+
if len(unsupportedCiphers) > 0 {
171+
klog.Info("TLS configuration contains unsupported ciphers that will be ignored",
172+
"unsupportedCiphers", unsupportedCiphers,
173+
)
174+
}
175+
151176
if err := setFeatureGatesEnvVars(); err != nil {
152177
klog.Error(err, "unable to set feature gates environment variables")
153178
os.Exit(1)
@@ -157,21 +182,23 @@ func main() {
157182
klog.LogToStderr(*logToStderr)
158183
}
159184

160-
_, diagnosticsOpts, err := capiflags.GetManagerOptions(capiManagerOptions)
185+
_, metricsOptions, err := capiflags.GetManagerOptions(capiManagerOptions)
161186
if err != nil {
162187
klog.Error(err, "unable to get manager options")
163188
os.Exit(1)
164189
}
165190

191+
// Override the TLS options for the metrics server with the ones specified centrally in the APIServer resource.
192+
tlsOptions := []func(config *tls.Config){tlsConfig}
193+
metricsOptions.TLSOpts = tlsOptions
194+
166195
syncPeriod := 10 * time.Minute
167196

168197
cacheOpts := getDefaultCacheOptions(*managedNamespace, syncPeriod)
169198

170-
cfg := ctrl.GetConfigOrDie()
171-
172199
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
173200
Scheme: scheme,
174-
Metrics: *diagnosticsOpts,
201+
Metrics: *metricsOptions,
175202
HealthProbeBindAddress: *healthAddr,
176203
LeaderElectionNamespace: leaderElectionConfig.ResourceNamespace,
177204
LeaderElection: leaderElectionConfig.LeaderElect,
@@ -183,6 +210,7 @@ func main() {
183210
WebhookServer: crwebhook.NewServer(crwebhook.Options{
184211
Port: *webhookPort,
185212
CertDir: *webhookCertDir,
213+
TLSOpts: tlsOptions,
186214
}),
187215
})
188216
if err != nil {
@@ -220,7 +248,7 @@ func main() {
220248
os.Exit(1)
221249
}
222250

223-
setupPlatformReconcilers(mgr, infra, platform, containerImages, applyClient, apiextensionsClient, *managedNamespace)
251+
setupPlatformReconcilers(mgr, infra, platform, containerImages, applyClient, apiextensionsClient, *managedNamespace, tlsOptions)
224252

225253
// +kubebuilder:scaffold:builder
226254

@@ -252,17 +280,17 @@ func getClusterOperatorStatusClient(mgr manager.Manager, controller string, plat
252280
}
253281
}
254282

255-
func setupPlatformReconcilers(mgr manager.Manager, infra *configv1.Infrastructure, platform configv1.PlatformType, containerImages map[string]string, applyClient *kubernetes.Clientset, apiextensionsClient *apiextensionsclient.Clientset, managedNamespace string) {
283+
func setupPlatformReconcilers(mgr manager.Manager, infra *configv1.Infrastructure, platform configv1.PlatformType, containerImages map[string]string, applyClient *kubernetes.Clientset, apiextensionsClient *apiextensionsclient.Clientset, managedNamespace string, tlsOptions []func(config *tls.Config)) {
256284
// Only setup reconcile controllers and webhooks when the platform is supported.
257285
// This avoids unnecessary CAPI providers discovery, installs and reconciles when the platform is not supported.
258286
isUnsupportedPlatform := false
259287

260288
switch platform {
261289
case configv1.AWSPlatformType:
262-
setupReconcilers(mgr, infra, platform, &awsv1.AWSCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
290+
setupReconcilers(mgr, infra, platform, &awsv1.AWSCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
263291
setupWebhooks(mgr)
264292
case configv1.GCPPlatformType:
265-
setupReconcilers(mgr, infra, platform, &gcpv1.GCPCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
293+
setupReconcilers(mgr, infra, platform, &gcpv1.GCPCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
266294
setupWebhooks(mgr)
267295
case configv1.AzurePlatformType:
268296
azureCloudEnvironment := getAzureCloudEnvironment(infra.Status.PlatformStatus)
@@ -272,20 +300,20 @@ func setupPlatformReconcilers(mgr manager.Manager, infra *configv1.Infrastructur
272300
isUnsupportedPlatform = true
273301
} else {
274302
// The ClusterOperator Controller must run in all cases.
275-
setupReconcilers(mgr, infra, platform, &azurev1.AzureCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
303+
setupReconcilers(mgr, infra, platform, &azurev1.AzureCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
276304
setupWebhooks(mgr)
277305
}
278306
case configv1.PowerVSPlatformType:
279-
setupReconcilers(mgr, infra, platform, &ibmpowervsv1.IBMPowerVSCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
307+
setupReconcilers(mgr, infra, platform, &ibmpowervsv1.IBMPowerVSCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
280308
setupWebhooks(mgr)
281309
case configv1.VSpherePlatformType:
282-
setupReconcilers(mgr, infra, platform, &vspherev1.VSphereCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
310+
setupReconcilers(mgr, infra, platform, &vspherev1.VSphereCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
283311
setupWebhooks(mgr)
284312
case configv1.OpenStackPlatformType:
285-
setupReconcilers(mgr, infra, platform, &openstackv1.OpenStackCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
313+
setupReconcilers(mgr, infra, platform, &openstackv1.OpenStackCluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
286314
setupWebhooks(mgr)
287315
case configv1.BareMetalPlatformType:
288-
setupReconcilers(mgr, infra, platform, &metal3v1.Metal3Cluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace)
316+
setupReconcilers(mgr, infra, platform, &metal3v1.Metal3Cluster{}, containerImages, applyClient, apiextensionsClient, managedNamespace, tlsOptions)
289317
setupWebhooks(mgr)
290318
default:
291319
klog.Infof("Detected platform %q is not supported, skipping capi controllers setup", platform)
@@ -297,7 +325,7 @@ func setupPlatformReconcilers(mgr manager.Manager, infra *configv1.Infrastructur
297325
setupClusterOperatorController(mgr, platform, managedNamespace, isUnsupportedPlatform)
298326
}
299327

300-
func setupReconcilers(mgr manager.Manager, infra *configv1.Infrastructure, platform configv1.PlatformType, infraClusterObject client.Object, containerImages map[string]string, applyClient *kubernetes.Clientset, apiextensionsClient *apiextensionsclient.Clientset, managedNamespace string) {
328+
func setupReconcilers(mgr manager.Manager, infra *configv1.Infrastructure, platform configv1.PlatformType, infraClusterObject client.Object, containerImages map[string]string, applyClient *kubernetes.Clientset, apiextensionsClient *apiextensionsclient.Clientset, managedNamespace string, tlsOptions []func(config *tls.Config)) {
301329
if err := (&corecluster.CoreClusterController{
302330
ClusterOperatorStatusClient: getClusterOperatorStatusClient(mgr, "cluster-capi-operator-cluster-resource-controller", platform, managedNamespace),
303331
Cluster: &clusterv1.Cluster{},
@@ -333,6 +361,7 @@ func setupReconcilers(mgr manager.Manager, infra *configv1.Infrastructure, platf
333361
Platform: platform,
334362
ApplyClient: applyClient,
335363
APIExtensionsClient: apiextensionsClient,
364+
TLSOpts: tlsOptions,
336365
}).SetupWithManager(mgr); err != nil {
337366
klog.Error(err, "unable to create capi installer controller", "controller", "CAPIInstaller")
338367
os.Exit(1)

cmd/machine-api-migration/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func main() {
125125
klog.LogToStderr(*logToStderr)
126126
}
127127

128-
_, diagnosticsOpts, err := capiflags.GetManagerOptions(capiManagerOptions)
128+
_, metricsOpts, err := capiflags.GetManagerOptions(capiManagerOptions)
129129
if err != nil {
130130
klog.Error(err, "unable to get manager options")
131131
os.Exit(1)
@@ -139,7 +139,7 @@ func main() {
139139

140140
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
141141
Scheme: scheme,
142-
Metrics: *diagnosticsOpts,
142+
Metrics: *metricsOpts,
143143
HealthProbeBindAddress: *healthAddr,
144144
LeaderElectionNamespace: leaderElectionConfig.ResourceNamespace,
145145
LeaderElection: leaderElectionConfig.LeaderElect,

pkg/controllers/capiinstaller/capi_installer_controller.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package capiinstaller
1717

1818
import (
1919
"context"
20+
"crypto/tls"
2021
"errors"
2122
"fmt"
2223
"regexp"
@@ -25,6 +26,8 @@ import (
2526
"github.com/drone/envsubst/v2"
2627
"github.com/go-logr/logr"
2728

29+
openshiftcrypto "github.com/openshift/library-go/pkg/crypto"
30+
2831
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
2932
appsv1 "k8s.io/api/apps/v1"
3033
corev1 "k8s.io/api/core/v1"
@@ -87,6 +90,7 @@ type CapiInstallerController struct {
8790
Platform configv1.PlatformType
8891
ApplyClient *kubernetes.Clientset
8992
APIExtensionsClient *apiextensionsclient.Clientset
93+
TLSOpts []func(config *tls.Config)
9094
}
9195

9296
// Reconcile reconciles the cluster-api ClusterOperator object.
@@ -234,6 +238,8 @@ func (r *CapiInstallerController) applyProviderComponents(ctx context.Context, c
234238
return fmt.Errorf("error casting object to Deployment: %w", err)
235239
}
236240

241+
injectTLSConfigIntoDeployment(deployment, r.TLSOpts)
242+
237243
if _, _, err := resourceapply.ApplyDeployment(
238244
ctx,
239245
r.ApplyClient.AppsV1(),
@@ -530,3 +536,28 @@ func yamlToUnstructured(sch *runtime.Scheme, m string) (*unstructured.Unstructur
530536

531537
return u, nil
532538
}
539+
540+
// injectTLSConfigIntoDeployment injects TLS configuration into the deployment spec,
541+
// setting --tls-min-version and --tls-cipher-suites on the container named "manager"
542+
// as described in https://github.com/kubernetes-sigs/cluster-api/blob/55e16f424c0ed8d3739070125d4c32a036997465/util/flags/manager.go#L59-L71.
543+
func injectTLSConfigIntoDeployment(deployment *appsv1.Deployment, tlsOpts []func(*tls.Config)) {
544+
tlsConfig := &tls.Config{}
545+
for _, tlsOpt := range tlsOpts {
546+
tlsOpt(tlsConfig)
547+
}
548+
549+
for i := range deployment.Spec.Template.Spec.Containers {
550+
if deployment.Spec.Template.Spec.Containers[i].Name == "manager" {
551+
deployment.Spec.Template.Spec.Containers[i].Args = append(
552+
deployment.Spec.Template.Spec.Containers[i].Args,
553+
fmt.Sprintf("--tls-min-version=%s", openshiftcrypto.TLSVersionToNameOrDie(tlsConfig.MinVersion)),
554+
)
555+
if len(tlsConfig.CipherSuites) > 0 {
556+
deployment.Spec.Template.Spec.Containers[i].Args = append(
557+
deployment.Spec.Template.Spec.Containers[i].Args,
558+
fmt.Sprintf("--tls-cipher-suites=%s", strings.Join(openshiftcrypto.CipherSuitesToNamesOrDie(tlsConfig.CipherSuites), ",")),
559+
)
560+
}
561+
}
562+
}
563+
}

0 commit comments

Comments
 (0)