Graduate AdditionalCertificateOutputFormats feature gate

Signed-off-by: Erik Godding Boye <egboye@gmail.com>
This commit is contained in:
Erik Godding Boye 2025-05-10 10:53:40 +02:00
parent e3775009a5
commit affd56e5e3
No known key found for this signature in database
15 changed files with 23 additions and 90 deletions

View File

@ -381,7 +381,7 @@ config:
# Feature gates as of v1.18.0. Listed with their default values.
# See https://cert-manager.io/docs/cli/controller/
featureGates:
AdditionalCertificateOutputFormats: true # BETA - default=true
AdditionalCertificateOutputFormats: true # GA - default=true
AllAlpha: false # ALPHA - default=false
AllBeta: false # BETA - default=false
ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false

View File

@ -579,7 +579,7 @@
},
"helm-values.config": {
"default": {},
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.18.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # BETA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # GA - default=true\n ValidateCAA: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics",
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.18.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # GA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # GA - default=true\n ValidateCAA: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics",
"type": "object"
},
"helm-values.containerSecurityContext": {

View File

@ -237,7 +237,7 @@ enableCertificateOwnerRef: false
# # Feature gates as of v1.18.0. Listed with their default values.
# # See https://cert-manager.io/docs/cli/controller/
# featureGates:
# AdditionalCertificateOutputFormats: true # BETA - default=true
# AdditionalCertificateOutputFormats: true # GA - default=true
# AllAlpha: false # ALPHA - default=false
# AllBeta: false # BETA - default=false
# ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false

View File

@ -87,10 +87,6 @@ spec:
description: |-
Defines extra output formats of the private key and signed certificate chain
to be written to this Certificate's target Secret.
This is a Beta Feature enabled by default. It can be disabled with the
`--feature-gates=AdditionalCertificateOutputFormats=false` option set on both
the controller and webhook components.
type: array
items:
description: |-

View File

@ -258,10 +258,6 @@ type CertificateSpec struct {
// Defines extra output formats of the private key and signed certificate chain
// to be written to this Certificate's target Secret.
//
// This is a Beta Feature enabled by default. It can be disabled with the
// `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both
// the controller and webhook components.
AdditionalOutputFormats []CertificateAdditionalOutputFormat
// x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate.

View File

@ -394,13 +394,6 @@ func ValidateDuration(crt *internalcmapi.CertificateSpec, fldPath *field.Path) f
func validateAdditionalOutputFormats(crt *internalcmapi.CertificateSpec, fldPath *field.Path) field.ErrorList {
var el field.ErrorList
if !utilfeature.DefaultFeatureGate.Enabled(feature.AdditionalCertificateOutputFormats) {
if len(crt.AdditionalOutputFormats) > 0 {
el = append(el, field.Forbidden(fldPath.Child("additionalOutputFormats"), "feature gate AdditionalCertificateOutputFormats must be enabled"))
}
return el
}
// Ensure the set of output formats is unique, keyed on "Type".
aofSet := sets.NewString()
for _, val := range crt.AdditionalOutputFormats {

View File

@ -1076,50 +1076,16 @@ func TestValidateDuration(t *testing.T) {
func Test_validateAdditionalOutputFormats(t *testing.T) {
tests := map[string]struct {
featureEnabled bool
spec *internalcmapi.CertificateSpec
expErr field.ErrorList
spec *internalcmapi.CertificateSpec
expErr field.ErrorList
}{
"if feature disabled and no formats defined, expect no error": {
featureEnabled: false,
"if no formats defined, expect no error": {
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{},
},
expErr: nil,
},
"if feature disabled and 1 format defined, expect error": {
featureEnabled: false,
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
},
},
expErr: field.ErrorList{
field.Forbidden(field.NewPath("spec", "additionalOutputFormats"), "feature gate AdditionalCertificateOutputFormats must be enabled"),
},
},
"if feature disabled and multiple formats defined, expect error": {
featureEnabled: false,
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
{Type: internalcmapi.CertificateOutputFormatType("bar")},
{Type: internalcmapi.CertificateOutputFormatType("random")},
},
},
expErr: field.ErrorList{
field.Forbidden(field.NewPath("spec", "additionalOutputFormats"), "feature gate AdditionalCertificateOutputFormats must be enabled"),
},
},
"if feature enabled and no formats defined, expect no error": {
featureEnabled: true,
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{},
},
expErr: nil,
},
"if feature enabled and single format defined, expect no error": {
featureEnabled: true,
"if single format defined, expect no error": {
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
@ -1127,8 +1093,7 @@ func Test_validateAdditionalOutputFormats(t *testing.T) {
},
expErr: nil,
},
"if feature enabled and multiple unique formats defined, expect no error": {
featureEnabled: true,
"if multiple unique formats defined, expect no error": {
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
@ -1138,8 +1103,7 @@ func Test_validateAdditionalOutputFormats(t *testing.T) {
},
expErr: nil,
},
"if feature enabled and multiple formats defined but 2 non-unique, expect error": {
featureEnabled: true,
"if multiple formats defined but 2 non-unique, expect error": {
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
@ -1152,8 +1116,7 @@ func Test_validateAdditionalOutputFormats(t *testing.T) {
field.Duplicate(field.NewPath("spec", "additionalOutputFormats").Key("type"), "foo"),
},
},
"if feature enabled and multiple formats defined but multiple non-unique, expect error": {
featureEnabled: true,
"if multiple formats defined but multiple non-unique, expect error": {
spec: &internalcmapi.CertificateSpec{
AdditionalOutputFormats: []internalcmapi.CertificateAdditionalOutputFormat{
{Type: internalcmapi.CertificateOutputFormatType("foo")},
@ -1178,7 +1141,6 @@ func Test_validateAdditionalOutputFormats(t *testing.T) {
for name, test := range tests {
t.Run(name, func(t *testing.T) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate, feature.AdditionalCertificateOutputFormats, test.featureEnabled)
gotErr := validateAdditionalOutputFormats(test.spec, field.NewPath("spec"))
assert.Equal(t, test.expErr, gotErr)
})

View File

@ -59,6 +59,7 @@ const (
// Owner: @joshvanl
// Alpha: v1.7
// Beta: v1.15
// GA: v1.18
//
// AdditionalCertificateOutputFormats enable output additional format
AdditionalCertificateOutputFormats featuregate.Feature = "AdditionalCertificateOutputFormats"
@ -187,7 +188,7 @@ var defaultCertManagerFeatureGates = map[featuregate.Feature]featuregate.Feature
ExperimentalCertificateSigningRequestControllers: {Default: false, PreRelease: featuregate.Alpha},
ExperimentalGatewayAPISupport: {Default: true, PreRelease: featuregate.Beta},
AdditionalCertificateOutputFormats: {Default: true, PreRelease: featuregate.Beta},
AdditionalCertificateOutputFormats: {Default: true, PreRelease: featuregate.GA},
ServerSideApply: {Default: false, PreRelease: featuregate.Alpha},
LiteralCertificateSubject: {Default: true, PreRelease: featuregate.Beta},
UseCertificateRequestBasicConstraints: {Default: false, PreRelease: featuregate.Alpha},

View File

@ -44,6 +44,7 @@ const (
// Owner: @joshvanl
// Alpha: v1.7.1
// Beta: v1.15
// GA: v1.18
//
// AdditionalCertificateOutputFormats enable output additional format
AdditionalCertificateOutputFormats featuregate.Feature = "AdditionalCertificateOutputFormats"
@ -97,7 +98,7 @@ func init() {
var webhookFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
DisallowInsecureCSRUsageDefinition: {Default: true, PreRelease: featuregate.GA},
AdditionalCertificateOutputFormats: {Default: true, PreRelease: featuregate.Beta},
AdditionalCertificateOutputFormats: {Default: true, PreRelease: featuregate.GA},
LiteralCertificateSubject: {Default: true, PreRelease: featuregate.Beta},
NameConstraints: {Default: true, PreRelease: featuregate.Beta},
OtherNames: {Default: false, PreRelease: featuregate.Alpha},

View File

@ -222,7 +222,7 @@ $(call local-image-tar,vaultretagged): $(call image-tar,vault)
tar cf $@ -C /tmp/vault .
@rm -rf /tmp/vault
FEATURE_GATES ?= AdditionalCertificateOutputFormats=true,ExperimentalCertificateSigningRequestControllers=true,ExperimentalGatewayAPISupport=true,ServerSideApply=true,LiteralCertificateSubject=true,UseCertificateRequestBasicConstraints=true,NameConstraints=true,OtherNames=true
FEATURE_GATES ?= ExperimentalCertificateSigningRequestControllers=true,ExperimentalGatewayAPISupport=true,ServerSideApply=true,LiteralCertificateSubject=true,UseCertificateRequestBasicConstraints=true,NameConstraints=true,OtherNames=true
## Set this environment variable to a non empty string to cause cert-manager to
## be installed using best-practice configuration settings, and to install
@ -263,8 +263,8 @@ comma = ,
# Helm's "--set" interprets commas, which means we want to escape commas
# for "--set featureGates". That's why we have "\$(comma)".
feature_gates_controller := $(subst $(space),\$(comma),$(filter AllAlpha=% AllBeta=% AdditionalCertificateOutputFormats=% ExperimentalCertificateSigningRequestControllers=% ExperimentalGatewayAPISupport=% ServerSideApply=% LiteralCertificateSubject=% UseCertificateRequestBasicConstraints=% NameConstraints=% SecretsFilteredCaching=% OtherNames=%, $(subst $(comma),$(space),$(FEATURE_GATES))))
feature_gates_webhook := $(subst $(space),\$(comma),$(filter AllAlpha=% AllBeta=% AdditionalCertificateOutputFormats=% LiteralCertificateSubject=% NameConstraints=% OtherNames=%, $(subst $(comma),$(space),$(FEATURE_GATES))))
feature_gates_controller := $(subst $(space),\$(comma),$(filter AllAlpha=% AllBeta=% ExperimentalCertificateSigningRequestControllers=% ExperimentalGatewayAPISupport=% ServerSideApply=% LiteralCertificateSubject=% UseCertificateRequestBasicConstraints=% NameConstraints=% SecretsFilteredCaching=% OtherNames=%, $(subst $(comma),$(space),$(FEATURE_GATES))))
feature_gates_webhook := $(subst $(space),\$(comma),$(filter AllAlpha=% AllBeta=% LiteralCertificateSubject=% NameConstraints=% OtherNames=%, $(subst $(comma),$(space),$(FEATURE_GATES))))
feature_gates_cainjector := $(subst $(space),\$(comma),$(filter AllAlpha=% AllBeta=% ServerSideApply=% CAInjectorMerging=%, $(subst $(comma),$(space),$(FEATURE_GATES))))
# When testing an published chart the repo can be configured using

View File

@ -77,7 +77,7 @@ flake_attempts=1
ginkgo_skip=
ginkgo_focus=
feature_gates=AdditionalCertificateOutputFormats=true,ExperimentalCertificateSigningRequestControllers=true,ExperimentalGatewayAPISupport=true,LiteralCertificateSubject=true,OtherNames=true
feature_gates=ExperimentalCertificateSigningRequestControllers=true,ExperimentalGatewayAPISupport=true,LiteralCertificateSubject=true,OtherNames=true
artifacts="./$BINDIR/artifacts"

View File

@ -299,10 +299,6 @@ type CertificateSpec struct {
// Defines extra output formats of the private key and signed certificate chain
// to be written to this Certificate's target Secret.
//
// This is a Beta Feature enabled by default. It can be disabled with the
// `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both
// the controller and webhook components.
// +optional
AdditionalOutputFormats []CertificateAdditionalOutputFormat `json:"additionalOutputFormats,omitempty"`

View File

@ -29,12 +29,10 @@ import (
coreclient "k8s.io/client-go/kubernetes/typed/core/v1"
"github.com/cert-manager/cert-manager/internal/controller/certificates"
"github.com/cert-manager/cert-manager/internal/controller/feature"
internalinformers "github.com/cert-manager/cert-manager/internal/informers"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
logf "github.com/cert-manager/cert-manager/pkg/logs"
utilfeature "github.com/cert-manager/cert-manager/pkg/util/feature"
utilpki "github.com/cert-manager/cert-manager/pkg/util/pki"
)
@ -142,11 +140,9 @@ func (s *SecretsManager) setValues(crt *cmapi.Certificate, secret *corev1.Secret
return fmt.Errorf("failed to add keystores to Secret: %w", err)
}
// Add additional output formats if feature enabled.
if utilfeature.DefaultFeatureGate.Enabled(feature.AdditionalCertificateOutputFormats) {
if err := setAdditionalOutputFormats(crt, secret, data); err != nil {
return fmt.Errorf("failed to add additional output formats to Secret: %w", err)
}
// Add additional output formats if enabled.
if err := setAdditionalOutputFormats(crt, secret, data); err != nil {
return fmt.Errorf("failed to add additional output formats to Secret: %w", err)
}
secret.Data[corev1.TLSPrivateKeyKey] = data.PrivateKey

View File

@ -41,10 +41,10 @@ import (
. "github.com/onsi/gomega/gstruct"
)
// This test ensures that the Certificates AdditionalCertificateOutputFormats
// This test ensures that the Certificates additionalOutputFormats
// is reflected on the Certificate's target Secret, and is reconciled on modify
// events.
var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFormats", func() {
var _ = framework.CertManagerDescribe("Certificate additionalOutputFormats", func() {
const (
issuerName = "certificate-additional-output-formats"
secretName = "test-additional-output-formats"
@ -54,8 +54,6 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
f := framework.NewDefaultFramework("certificates-additional-output-formats")
createCertificate := func(f *framework.Framework, aof []cmapi.CertificateAdditionalOutputFormat) (string, *cmapi.Certificate) {
framework.RequireFeatureGate(utilfeature.DefaultFeatureGate, feature.AdditionalCertificateOutputFormats)
crt := &cmapi.Certificate{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-additional-output-formats-",

View File

@ -25,10 +25,8 @@ import (
"github.com/cert-manager/cert-manager/e2e-tests/framework"
"github.com/cert-manager/cert-manager/e2e-tests/framework/helper/validation/certificates"
"github.com/cert-manager/cert-manager/e2e-tests/util"
"github.com/cert-manager/cert-manager/internal/controller/feature"
v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
utilfeature "github.com/cert-manager/cert-manager/pkg/util/feature"
"github.com/cert-manager/cert-manager/test/unit/gen"
. "github.com/onsi/ginkgo/v2"
@ -158,10 +156,6 @@ var _ = framework.CertManagerDescribe("CA Certificate", func() {
})
It("should be able to create a certificate with additional output formats", func() {
// Output formats is only enabled via this feature gate being enabled.
// Don't run test if the gate isn't enabled.
framework.RequireFeatureGate(utilfeature.DefaultFeatureGate, feature.AdditionalCertificateOutputFormats)
certClient := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name)
By("Creating a Certificate")