diff --git a/pkg/cmd/openshift-apiserver/openshiftadmission/register.go b/pkg/cmd/openshift-apiserver/openshiftadmission/register.go index 99a5647d7..144bf6d78 100644 --- a/pkg/cmd/openshift-apiserver/openshiftadmission/register.go +++ b/pkg/cmd/openshift-apiserver/openshiftadmission/register.go @@ -1,6 +1,9 @@ package openshiftadmission import ( + "fmt" + "slices" + "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission/plugin/resourcequota" genericapiserver "k8s.io/apiserver/pkg/server" @@ -13,6 +16,7 @@ import ( imageadmission "github.com/openshift/openshift-apiserver/pkg/image/apiserver/admission/limitrange" projectrequestlimit "github.com/openshift/openshift-apiserver/pkg/project/apiserver/admission/requestlimit" requiredrouteannotations "github.com/openshift/openshift-apiserver/pkg/route/apiserver/admission/requiredrouteannotations" + "k8s.io/apiserver/pkg/server/options" ) // TODO register this per apiserver or at least per process @@ -44,23 +48,48 @@ func RegisterOpenshiftAdmissionPlugins(plugins *admission.Plugins) { var ( // OpenShiftAdmissionPlugins gives the in-order default admission chain for openshift resources. - OpenShiftAdmissionPlugins = []string{ - // these are from the kbue chain - "NamespaceLifecycle", - "OwnerReferencesPermissionEnforcement", + OpenShiftAdmissionPlugins = func() []string { + downstreamPlugins := []string{ + // these are from the kube chain + "NamespaceLifecycle", + "OwnerReferencesPermissionEnforcement", + + // all custom admission goes here to simulate being part of a webhook + "project.openshift.io/ProjectRequestLimit", + "build.openshift.io/BuildConfigSecretInjector", + "build.openshift.io/BuildByStrategy", + "image.openshift.io/ImageLimitRange", + "image.openshift.io/ImagePolicy", + "quota.openshift.io/ClusterResourceQuota", + "route.openshift.io/RequiredRouteAnnotations", + + // the rest of the kube chain goes here + "MutatingAdmissionPolicy", + "MutatingAdmissionWebhook", + "ValidatingAdmissionPolicy", + "ValidatingAdmissionWebhook", + "ResourceQuota", + } + + // Upstream plugins that are omitted intentionally. If a given plugin is enabled by + // default for generic API servers, it must either be enabled by default downstream + // or included in this list with an explanation. + omittedPlugins := []string{} - // all custom admission goes here to simulate being part of a webhook - "project.openshift.io/ProjectRequestLimit", - "build.openshift.io/BuildConfigSecretInjector", - "build.openshift.io/BuildByStrategy", - "image.openshift.io/ImageLimitRange", - "image.openshift.io/ImagePolicy", - "quota.openshift.io/ClusterResourceQuota", - "route.openshift.io/RequiredRouteAnnotations", + upstreamPlugins := options.NewAdmissionOptions().RecommendedPluginOrder + enumeratedPlugins := append(downstreamPlugins, omittedPlugins...) + for _, upstreamPluginName := range upstreamPlugins { + if !slices.Contains(enumeratedPlugins, upstreamPluginName) { + // If you are reading this because you are changing the version of + // the k8s.io/apiserver dependency, upstream may have introduced a + // new default-enabled admission plugin. If there is a good reason + // against enabling it in openshift-apiserver, its name must be + // included in omittedPlugins, otherwise, it should in the + // appropriate position in downstreamPlugins. + panic(fmt.Sprintf("k8s.io/apiserver default admission plugins includes %q which is in neither downstreamPlugins nor omittedPlugins: %v", upstreamPluginName, upstreamPlugins)) + } + } - // the rest of the kube chain goes here - "MutatingAdmissionWebhook", - "ValidatingAdmissionWebhook", - "ResourceQuota", - } + return downstreamPlugins + }() ) diff --git a/pkg/cmd/openshift-apiserver/openshiftapiserver/config.go b/pkg/cmd/openshift-apiserver/openshiftapiserver/config.go index 656c66eb5..22f2419e2 100644 --- a/pkg/cmd/openshift-apiserver/openshiftapiserver/config.go +++ b/pkg/cmd/openshift-apiserver/openshiftapiserver/config.go @@ -214,8 +214,7 @@ func NewOpenshiftAPIConfig(config *openshiftcontrolplanev1.OpenShiftAPIServerCon } admissionOptions.DisablePlugins = config.AdmissionConfig.DisabledAdmissionPlugins admissionOptions.ConfigFile = admissionConfigFile - // TODO: - if err := admissionOptions.ApplyTo(&genericConfig.Config, kubeInformers, kubeClient, dynamicClient, nil, admissionInitializer); err != nil { + if err := admissionOptions.ApplyTo(&genericConfig.Config, kubeInformers, kubeClient, dynamicClient, feature.DefaultFeatureGate, admissionInitializer); err != nil { return nil, err }