diff --git a/pkg/package-server-manager/config.go b/pkg/package-server-manager/config.go index 04ec8a75bb..fc85710d91 100644 --- a/pkg/package-server-manager/config.go +++ b/pkg/package-server-manager/config.go @@ -149,6 +149,21 @@ func ensureCSVHighAvailability(image string, csv *olmv1alpha1.ClusterServiceVers modified = true } + // Ensure pod-level seccompProfile is always set. The openshift-operator-lifecycle-manager + // namespace enforces restricted:latest PodSecurity, which requires seccompProfile. The CSV + // template includes this field, but it may be absent if the cluster CSV was created by an + // older version or if SCC/PSA admission ordering masks the missing field on most clusters. + if deployment.Template.Spec.SecurityContext == nil { + deployment.Template.Spec.SecurityContext = &corev1.PodSecurityContext{} + } + if deployment.Template.Spec.SecurityContext.SeccompProfile == nil || + deployment.Template.Spec.SecurityContext.SeccompProfile.Type != corev1.SeccompProfileTypeRuntimeDefault { + deployment.Template.Spec.SecurityContext.SeccompProfile = &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + } + modified = true + } + if modified { csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec = *deployment } diff --git a/pkg/package-server-manager/controller_test.go b/pkg/package-server-manager/controller_test.go index ae7fa6423c..2293329cf1 100644 --- a/pkg/package-server-manager/controller_test.go +++ b/pkg/package-server-manager/controller_test.go @@ -94,6 +94,21 @@ func withAffinity(affinity *corev1.Affinity) func(*olmv1alpha1.ClusterServiceVer csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec.Affinity = affinity } } + +func withoutSeccompProfile() testCSVOption { + return func(csv *olmv1alpha1.ClusterServiceVersion) { + podSpec := &csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec + if podSpec.SecurityContext != nil { + podSpec.SecurityContext.SeccompProfile = nil + } + } +} + +func withNilPodSecurityContext() testCSVOption { + return func(csv *olmv1alpha1.ClusterServiceVersion) { + csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec.SecurityContext = nil + } +} func withRollingUpdateStrategy(strategy *appsv1.RollingUpdateDeployment) func(*olmv1alpha1.ClusterServiceVersion) { return func(csv *olmv1alpha1.ClusterServiceVersion) { csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Strategy.RollingUpdate = strategy @@ -255,6 +270,27 @@ func TestEnsureCSV(t *testing.T) { inputCSV: newTestCSV(withReplicas(singleReplicas), withRollingUpdateStrategy(emptyRollout), withAffinity(&corev1.Affinity{})), expectedCSV: newTestCSV(withReplicas(singleReplicas), withRollingUpdateStrategy(emptyRollout), withAffinity(&corev1.Affinity{})), }, + { + name: "Modified/HighlyAvailable/MissingSeccompProfile", + want: wanted{true, nil}, + highlyAvailable: true, + inputCSV: newTestCSV(withReplicas(defaultReplicas), withRollingUpdateStrategy(defaultRollout), withAffinity(defaultAffinity), withoutSeccompProfile()), + expectedCSV: newTestCSV(withReplicas(defaultReplicas), withRollingUpdateStrategy(defaultRollout), withAffinity(defaultAffinity)), + }, + { + name: "Modified/SingleReplica/MissingSeccompProfile", + want: wanted{true, nil}, + highlyAvailable: false, + inputCSV: newTestCSV(withReplicas(singleReplicas), withRollingUpdateStrategy(emptyRollout), withAffinity(&corev1.Affinity{}), withoutSeccompProfile()), + expectedCSV: newTestCSV(withReplicas(singleReplicas), withRollingUpdateStrategy(emptyRollout), withAffinity(&corev1.Affinity{})), + }, + { + name: "Modified/HighlyAvailable/NilPodSecurityContext", + want: wanted{true, nil}, + highlyAvailable: true, + inputCSV: newTestCSV(withReplicas(defaultReplicas), withRollingUpdateStrategy(defaultRollout), withAffinity(defaultAffinity), withNilPodSecurityContext()), + expectedCSV: newTestCSV(withReplicas(defaultReplicas), withRollingUpdateStrategy(defaultRollout), withAffinity(defaultAffinity)), + }, } for _, tc := range tt {