Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 14 additions & 3 deletions controllers/provisioning_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,20 @@ func (r *ProvisioningReconciler) provisioningInfo(ctx context.Context, provConfi
return nil, err
}

tlsProfileSpec, err := utiltls.FetchAPIServerTLSProfile(ctx, r.Client)
if err != nil {
return nil, fmt.Errorf("unable to get TLS profile from APIServer: %w", err)
// Check tlsAdherence to decide whether to enforce the cluster TLS profile
apiServer := &osconfigv1.APIServer{}
if err := r.Client.Get(ctx, types.NamespacedName{Name: "cluster"}, apiServer); err != nil {
return nil, fmt.Errorf("unable to read APIServer CR for TLS adherence check: %w", err)
}
honorTLS := provisioning.ShouldHonorClusterTLSProfile(apiServer.Spec.TLSAdherence)

var tlsProfileSpec *osconfigv1.TLSProfileSpec
if honorTLS {
spec, err := utiltls.FetchAPIServerTLSProfile(ctx, r.Client)
if err != nil {
return nil, fmt.Errorf("unable to get TLS profile from APIServer: %w", err)
}
tlsProfileSpec = &spec
}

infra, _ := r.OSClient.ConfigV1().Infrastructures().Get(ctx, "cluster", metav1.GetOptions{})
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
module github.com/openshift/cluster-baremetal-operator

go 1.24.0
go 1.25.0

require (
github.com/ghodss/yaml v1.0.0
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/golangci/golangci-lint/v2 v2.1.6
github.com/google/go-cmp v0.7.0
github.com/metal3-io/baremetal-operator/apis v0.0.0
github.com/openshift/api v0.0.0-20260213155647-8fe9fe363807
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13
github.com/openshift/api v0.0.0-20260318185450-1f2fa3f09f4e
github.com/openshift/client-go v0.0.0-20260317180604-743f664b82d1
github.com/openshift/controller-runtime-common v0.0.0-20260213175913-767fef058eca
github.com/openshift/library-go v0.0.0-20260213153706-03f1709971c5
github.com/pkg/errors v0.9.1
github.com/stretchr/stew v0.0.0-20130812190256-80ef0842b48b
github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.47.0
k8s.io/api v0.34.3
k8s.io/apimachinery v0.34.3
k8s.io/client-go v0.34.3
k8s.io/api v0.35.1
k8s.io/apimachinery v0.35.1
k8s.io/client-go v0.35.1
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20260108192941-914a6e750570
sigs.k8s.io/controller-runtime v0.22.5
Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,14 @@ github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsx
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
github.com/openshift/api v0.0.0-20260213155647-8fe9fe363807 h1:coR/haF16EW8KS1E/PwJfDzMSy4mU9K0H1rcHejqYDY=
github.com/openshift/api v0.0.0-20260213155647-8fe9fe363807/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
github.com/openshift/api v0.0.0-20260318185450-1f2fa3f09f4e h1:n2fW82JRX5B/+eCULWIe06MAhJVaE8fUsvy0A0Gn9n4=
github.com/openshift/api v0.0.0-20260318185450-1f2fa3f09f4e/go.mod h1:pyVjK0nZ4sRs4fuQVQ4rubsJdahI1PB94LnQ8sGdvxo=
github.com/openshift/baremetal-operator/apis v0.0.0-20250318213501-20a31adf14bc h1:htUUb9YENM/7dk7pWUp8BEPhb20+yV1SKxF3QudaC30=
github.com/openshift/baremetal-operator/apis v0.0.0-20250318213501-20a31adf14bc/go.mod h1:D0NG169s4/Nt/TT//DVq/DdgfB23my/SqXbwTgIo198=
github.com/openshift/baremetal-operator/pkg/hardwareutils v0.0.0-20250318213501-20a31adf14bc h1:lx6TJV8lMYbMr3dm8e73FkMhwc4L8ucEW6imVEPfP5g=
github.com/openshift/baremetal-operator/pkg/hardwareutils v0.0.0-20250318213501-20a31adf14bc/go.mod h1:f1a/eqi7MA+mf1xFshToVfn02jcPDMw3aYQinLTlMVQ=
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13 h1:6rd4zSo2UaWQcAPZfHK9yzKVqH0BnMv1hqMzqXZyTds=
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13/go.mod h1:YvOmPmV7wcJxpfhTDuFqqs2Xpb3M3ovsM6Qs/i2ptq4=
github.com/openshift/client-go v0.0.0-20260317180604-743f664b82d1 h1:Hr/R38eg5ZJXfbiaHumjJIN1buDZwhsm4ys4npVCXH0=
github.com/openshift/client-go v0.0.0-20260317180604-743f664b82d1/go.mod h1:Za51LlH76ALiQ/aKGBYJXmyJNkA//IDJ+I///30CA2M=
github.com/openshift/controller-runtime-common v0.0.0-20260213175913-767fef058eca h1:EOc/lbyZxtn1b/BvRwnLpbgBg0F+2RUQd3xMiA4/JsQ=
github.com/openshift/controller-runtime-common v0.0.0-20260213175913-767fef058eca/go.mod h1:59nLF3/IfhAtoQZfUzlCyidTAdlVT6KiVeTicUi2wuA=
github.com/openshift/library-go v0.0.0-20260213153706-03f1709971c5 h1:9Pe6iVOMjt9CdA/vaKBNUSoEIjIe1po5Ha3ABRYXLJI=
Expand Down Expand Up @@ -1249,16 +1249,16 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
k8s.io/api v0.34.3 h1:D12sTP257/jSH2vHV2EDYrb16bS7ULlHpdNdNhEw2S4=
k8s.io/api v0.34.3/go.mod h1:PyVQBF886Q5RSQZOim7DybQjAbVs8g7gwJNhGtY5MBk=
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
k8s.io/apiextensions-apiserver v0.34.3 h1:p10fGlkDY09eWKOTeUSioxwLukJnm+KuDZdrW71y40g=
k8s.io/apiextensions-apiserver v0.34.3/go.mod h1:aujxvqGFRdb/cmXYfcRTeppN7S2XV/t7WMEc64zB5A0=
k8s.io/apimachinery v0.34.3 h1:/TB+SFEiQvN9HPldtlWOTp0hWbJ+fjU+wkxysf/aQnE=
k8s.io/apimachinery v0.34.3/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/apiserver v0.34.3 h1:uGH1qpDvSiYG4HVFqc6A3L4CKiX+aBWDrrsxHYK0Bdo=
k8s.io/apiserver v0.34.3/go.mod h1:QPnnahMO5C2m3lm6fPW3+JmyQbvHZQ8uudAu/493P2w=
k8s.io/client-go v0.34.3 h1:wtYtpzy/OPNYf7WyNBTj3iUA0XaBHVqhv4Iv3tbrF5A=
k8s.io/client-go v0.34.3/go.mod h1:OxxeYagaP9Kdf78UrKLa3YZixMCfP6bgPwPwNBQBzpM=
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
k8s.io/component-base v0.34.3 h1:zsEgw6ELqK0XncCQomgO9DpUIzlrYuZYA0Cgo+JWpVk=
k8s.io/component-base v0.34.3/go.mod h1:5iIlD8wPfWE/xSHTRfbjuvUul2WZbI2nOUK65XL0E/c=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
Expand Down
68 changes: 43 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -91,8 +92,8 @@ func main() {

config := ctrl.GetConfigOrDie()

// Read the cluster-wide TLS profile from the APIServer CR and apply it
// to the CBO webhook server.
// Read the APIServer CR to check tlsAdherence and optionally apply
// the cluster-wide TLS profile to the CBO webhook server.
k8sClient, err := client.New(config, client.Options{Scheme: scheme})
if err != nil {
klog.ErrorS(err, "unable to create client for TLS profile fetch")
Expand All @@ -101,17 +102,32 @@ func main() {

tlsFetchCtx, tlsFetchCancel := context.WithTimeout(context.Background(), 60*time.Second)
defer tlsFetchCancel()
tlsProfileSpec, err := utiltls.FetchAPIServerTLSProfile(tlsFetchCtx, k8sClient)
if err != nil {
klog.ErrorS(err, "unable to get TLS profile from APIServer")

apiServer := &osconfigv1.APIServer{}
if err := k8sClient.Get(tlsFetchCtx, types.NamespacedName{Name: "cluster"}, apiServer); err != nil {
klog.ErrorS(err, "unable to read APIServer CR")
os.Exit(1)
}

tlsConfig, unsupportedCiphers := utiltls.NewTLSConfigFromProfile(tlsProfileSpec)
if len(unsupportedCiphers) > 0 {
klog.Infof("TLS configuration contains unsupported ciphers that will be ignored: %v", unsupportedCiphers)
honorTLSProfile := provisioning.ShouldHonorClusterTLSProfile(apiServer.Spec.TLSAdherence)

var webhookTLSOpts []func(*tls.Config)
var tlsProfileSpec osconfigv1.TLSProfileSpec
if honorTLSProfile {
tlsProfileSpec, err = utiltls.FetchAPIServerTLSProfile(tlsFetchCtx, k8sClient)
if err != nil {
klog.ErrorS(err, "unable to get TLS profile from APIServer")
os.Exit(1)
}
tlsConfig, unsupportedCiphers := utiltls.NewTLSConfigFromProfile(tlsProfileSpec)
if len(unsupportedCiphers) > 0 {
klog.Infof("TLS configuration contains unsupported ciphers that will be ignored: %v", unsupportedCiphers)
}
webhookTLSOpts = append(webhookTLSOpts, tlsConfig)
klog.Info("Applying cluster TLS profile to webhook server")
} else {
klog.Info("Cluster TLS adherence does not require enforcement, using defaults")
}
webhookTLSOpts := []func(*tls.Config){tlsConfig}

controllerOptions := ctrl.Options{
Scheme: scheme,
Expand Down Expand Up @@ -225,22 +241,24 @@ func main() {
ctx, cancel := context.WithCancel(ctrl.SetupSignalHandler())
defer cancel()

// Set up the TLS security profile watcher controller.
// This triggers a graceful shutdown when the TLS profile changes,
// so that CBO restarts with the new TLS configuration.
if err := (&utiltls.SecurityProfileWatcher{
Client: mgr.GetClient(),
InitialTLSProfileSpec: tlsProfileSpec,
OnProfileChange: func(ctx context.Context, oldSpec, newSpec osconfigv1.TLSProfileSpec) {
klog.Infof("TLS profile has changed, initiating a shutdown to reload it. %q: %+v, %q: %+v",
"old profile", oldSpec,
"new profile", newSpec,
)
cancel()
},
}).SetupWithManager(mgr); err != nil {
klog.ErrorS(err, "unable to create TLS security profile watcher controller")
os.Exit(1)
// Set up the TLS security profile watcher controller when TLS adherence
// requires enforcement. This triggers a graceful shutdown when the TLS
// profile changes, so that CBO restarts with the new TLS configuration.
if honorTLSProfile {
if err := (&utiltls.SecurityProfileWatcher{
Client: mgr.GetClient(),
InitialTLSProfileSpec: tlsProfileSpec,
OnProfileChange: func(ctx context.Context, oldSpec, newSpec osconfigv1.TLSProfileSpec) {
klog.Infof("TLS profile has changed, initiating a shutdown to reload it. %q: %+v, %q: %+v",
"old profile", oldSpec,
"new profile", newSpec,
)
cancel()
},
}).SetupWithManager(mgr); err != nil {
klog.ErrorS(err, "unable to create TLS security profile watcher controller")
os.Exit(1)
}
}
// +kubebuilder:scaffold:builder

Expand Down
8 changes: 6 additions & 2 deletions provisioning/baremetal_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,9 @@ func createContainerMetal3Httpd(images *Images, info *ProvisioningInfo) corev1.C
TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
}

container.Env = append(container.Env, tlsProfileToApacheEnvVars(info.TLSProfileSpec)...)
if info.TLSProfileSpec != nil {
container.Env = append(container.Env, tlsProfileToApacheEnvVars(*info.TLSProfileSpec)...)
}

return container
}
Expand Down Expand Up @@ -668,7 +670,9 @@ func createContainerMetal3Ironic(images *Images, info *ProvisioningInfo, config
)
}

container.Env = append(container.Env, tlsProfileToApacheEnvVars(info.TLSProfileSpec)...)
if info.TLSProfileSpec != nil {
container.Env = append(container.Env, tlsProfileToApacheEnvVars(*info.TLSProfileSpec)...)
}

return container
}
Expand Down
77 changes: 73 additions & 4 deletions provisioning/baremetal_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,11 @@ func TestNewMetal3Containers(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Logf("Testing tc : %s", tc.name)
info := &ProvisioningInfo{
Images: &images,
ProvConfig: &metal3iov1alpha1.Provisioning{Spec: *tc.config},
SSHKey: tc.sshkey,
NetworkStack: NetworkStackV6,
Images: &images,
ProvConfig: &metal3iov1alpha1.Provisioning{Spec: *tc.config},
SSHKey: tc.sshkey,
TLSProfileSpec: &osconfigv1.TLSProfileSpec{},
NetworkStack: NetworkStackV6,
Client: fakekube.NewSimpleClientset(&corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: "openshift-machine-api",
Expand Down Expand Up @@ -535,6 +536,74 @@ func TestNewMetal3Containers(t *testing.T) {
}
}

func TestNewMetal3ContainersNoTLSProfile(t *testing.T) {
images := Images{
BaremetalOperator: expectedBaremetalOperator,
Ironic: expectedIronic,
MachineOsDownloader: expectedMachineOsDownloader,
StaticIpManager: expectedIronicStaticIpManager,
}
info := &ProvisioningInfo{
Images: &images,
ProvConfig: &metal3iov1alpha1.Provisioning{Spec: *managedProvisioning().build()},
SSHKey: "sshkey",
NetworkStack: NetworkStackV6,
Client: fakekube.NewSimpleClientset(&corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: "openshift-machine-api",
Labels: map[string]string{
"k8s-app": metal3AppName,
cboLabelName: stateService,
},
},
Status: corev1.PodStatus{
PodIPs: []corev1.PodIP{
{IP: "192.168.111.22"},
{IP: "fd2e:6f44:5dd8:c956::16"},
},
}}),
OSClient: fakeconfigclientset.NewSimpleClientset(
&osconfigv1.Infrastructure{
TypeMeta: metav1.TypeMeta{
Kind: "Infrastructure",
APIVersion: "config.openshift.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Status: osconfigv1.InfrastructureStatus{
PlatformStatus: &osconfigv1.PlatformStatus{
Type: osconfigv1.BareMetalPlatformType,
BareMetal: &osconfigv1.BareMetalPlatformStatus{
APIServerInternalIPs: []string{
"192.168.1.1",
"fd2e:6f44:5dd8:c956::16",
},
},
},
},
}),
}

containers := newMetal3Containers(info)

tlsEnvNames := []string{
"IRONIC_SSL_PROTOCOL",
"IRONIC_VMEDIA_SSL_PROTOCOL",
"IRONIC_TLS_12_CIPHERS",
"IRONIC_TLS_13_CIPHERS",
}
for _, container := range containers {
for _, envName := range tlsEnvNames {
for _, env := range container.Env {
assert.NotEqual(t, envName, env.Name,
"container %s should not have TLS env var %s when TLSProfileSpec is nil",
container.Name, envName)
}
}
}
}

func TestProxyAndCAInjection(t *testing.T) {
info := &ProvisioningInfo{
Images: &Images{
Expand Down
4 changes: 3 additions & 1 deletion provisioning/bmo_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ func createContainerBaremetalOperator(info *ProvisioningInfo) (corev1.Container,
TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
}

container.Args = append(container.Args, tlsProfileToBMOArgs(info.TLSProfileSpec)...)
if info.TLSProfileSpec != nil {
container.Args = append(container.Args, tlsProfileToBMOArgs(*info.TLSProfileSpec)...)
}

if !info.BaremetalWebhookEnabled {
// Webhook dependencies are not ready, thus we disable webhook explicitly,
Expand Down
Loading