diff --git a/deploy/crds/crd-certificates.yaml b/deploy/crds/crd-certificates.yaml index b2bbc60ee..030921837 100644 --- a/deploy/crds/crd-certificates.yaml +++ b/deploy/crds/crd-certificates.yaml @@ -202,6 +202,11 @@ spec: - create - passwordSecretRef properties: + alias: + description: |- + Alias specifies the alias of the key in the keystore, required by the JKS format. + If not provided, the default alias `certificate` will be used. + type: string create: description: |- Create enables JKS keystore creation for the Certificate. diff --git a/internal/apis/certmanager/types_certificate.go b/internal/apis/certmanager/types_certificate.go index dbffdbc06..f966a1328 100644 --- a/internal/apis/certmanager/types_certificate.go +++ b/internal/apis/certmanager/types_certificate.go @@ -410,6 +410,11 @@ type JKSKeystore struct { // PasswordSecretRef is a reference to a key in a Secret resource // containing the password used to encrypt the JKS keystore. PasswordSecretRef cmmeta.SecretKeySelector + + // Alias specifies the alias of the key in the keystore, required by the JKS format. + // If not provided, the default alias `certificate` will be used. + // +optional + Alias *string `json:"alias,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the diff --git a/internal/apis/certmanager/v1/zz_generated.conversion.go b/internal/apis/certmanager/v1/zz_generated.conversion.go index d88ce84bc..ed4d3b3c1 100644 --- a/internal/apis/certmanager/v1/zz_generated.conversion.go +++ b/internal/apis/certmanager/v1/zz_generated.conversion.go @@ -1266,6 +1266,7 @@ func autoConvert_v1_JKSKeystore_To_certmanager_JKSKeystore(in *v1.JKSKeystore, o if err := internalapismetav1.Convert_v1_SecretKeySelector_To_meta_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } @@ -1279,6 +1280,7 @@ func autoConvert_certmanager_JKSKeystore_To_v1_JKSKeystore(in *certmanager.JKSKe if err := internalapismetav1.Convert_meta_SecretKeySelector_To_v1_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } diff --git a/internal/apis/certmanager/v1alpha2/types_certificate.go b/internal/apis/certmanager/v1alpha2/types_certificate.go index 332058ae3..efb4cfa40 100644 --- a/internal/apis/certmanager/v1alpha2/types_certificate.go +++ b/internal/apis/certmanager/v1alpha2/types_certificate.go @@ -335,6 +335,11 @@ type JKSKeystore struct { // PasswordSecretRef is a reference to a key in a Secret resource // containing the password used to encrypt the JKS keystore. PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` + + // Alias specifies the alias of the key in the keystore, required by the JKS format. + // If not provided, the default alias `certificate` will be used. + // +optional + Alias *string `json:"alias,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the diff --git a/internal/apis/certmanager/v1alpha2/zz_generated.conversion.go b/internal/apis/certmanager/v1alpha2/zz_generated.conversion.go index b1759810c..b07a368cb 100644 --- a/internal/apis/certmanager/v1alpha2/zz_generated.conversion.go +++ b/internal/apis/certmanager/v1alpha2/zz_generated.conversion.go @@ -1272,6 +1272,7 @@ func autoConvert_v1alpha2_JKSKeystore_To_certmanager_JKSKeystore(in *JKSKeystore if err := apismetav1.Convert_v1_SecretKeySelector_To_meta_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } @@ -1285,6 +1286,7 @@ func autoConvert_certmanager_JKSKeystore_To_v1alpha2_JKSKeystore(in *certmanager if err := apismetav1.Convert_meta_SecretKeySelector_To_v1_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } diff --git a/internal/apis/certmanager/v1alpha2/zz_generated.deepcopy.go b/internal/apis/certmanager/v1alpha2/zz_generated.deepcopy.go index 330390150..37c3397ca 100644 --- a/internal/apis/certmanager/v1alpha2/zz_generated.deepcopy.go +++ b/internal/apis/certmanager/v1alpha2/zz_generated.deepcopy.go @@ -129,7 +129,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.JKS != nil { in, out := &in.JKS, &out.JKS *out = new(JKSKeystore) - **out = **in + (*in).DeepCopyInto(*out) } if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 @@ -786,6 +786,11 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(string) + **out = **in + } return } diff --git a/internal/apis/certmanager/v1alpha3/types_certificate.go b/internal/apis/certmanager/v1alpha3/types_certificate.go index 8303549df..1fc37bbad 100644 --- a/internal/apis/certmanager/v1alpha3/types_certificate.go +++ b/internal/apis/certmanager/v1alpha3/types_certificate.go @@ -339,6 +339,11 @@ type JKSKeystore struct { // PasswordSecretRef is a reference to a key in a Secret resource // containing the password used to encrypt the JKS keystore. PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` + + // Alias specifies the alias of the key in the keystore, required by the JKS format. + // If not provided, the default alias `certificate` will be used. + // +optional + Alias *string `json:"alias,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the diff --git a/internal/apis/certmanager/v1alpha3/zz_generated.conversion.go b/internal/apis/certmanager/v1alpha3/zz_generated.conversion.go index d34cdab9c..c0d2b8aeb 100644 --- a/internal/apis/certmanager/v1alpha3/zz_generated.conversion.go +++ b/internal/apis/certmanager/v1alpha3/zz_generated.conversion.go @@ -1271,6 +1271,7 @@ func autoConvert_v1alpha3_JKSKeystore_To_certmanager_JKSKeystore(in *JKSKeystore if err := apismetav1.Convert_v1_SecretKeySelector_To_meta_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } @@ -1284,6 +1285,7 @@ func autoConvert_certmanager_JKSKeystore_To_v1alpha3_JKSKeystore(in *certmanager if err := apismetav1.Convert_meta_SecretKeySelector_To_v1_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } diff --git a/internal/apis/certmanager/v1alpha3/zz_generated.deepcopy.go b/internal/apis/certmanager/v1alpha3/zz_generated.deepcopy.go index 52d0d5e6b..3e02b1843 100644 --- a/internal/apis/certmanager/v1alpha3/zz_generated.deepcopy.go +++ b/internal/apis/certmanager/v1alpha3/zz_generated.deepcopy.go @@ -129,7 +129,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.JKS != nil { in, out := &in.JKS, &out.JKS *out = new(JKSKeystore) - **out = **in + (*in).DeepCopyInto(*out) } if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 @@ -781,6 +781,11 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(string) + **out = **in + } return } diff --git a/internal/apis/certmanager/v1beta1/types_certificate.go b/internal/apis/certmanager/v1beta1/types_certificate.go index 6446e80cf..7ed3eadd8 100644 --- a/internal/apis/certmanager/v1beta1/types_certificate.go +++ b/internal/apis/certmanager/v1beta1/types_certificate.go @@ -340,6 +340,11 @@ type JKSKeystore struct { // PasswordSecretRef is a reference to a key in a Secret resource // containing the password used to encrypt the JKS keystore. PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` + + // Alias specifies the alias of the key in the keystore, required by the JKS format. + // If not provided, the default alias `certificate` will be used. + // +optional + Alias *string `json:"alias,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the diff --git a/internal/apis/certmanager/v1beta1/zz_generated.conversion.go b/internal/apis/certmanager/v1beta1/zz_generated.conversion.go index c895df576..8df77513b 100644 --- a/internal/apis/certmanager/v1beta1/zz_generated.conversion.go +++ b/internal/apis/certmanager/v1beta1/zz_generated.conversion.go @@ -1254,6 +1254,7 @@ func autoConvert_v1beta1_JKSKeystore_To_certmanager_JKSKeystore(in *JKSKeystore, if err := apismetav1.Convert_v1_SecretKeySelector_To_meta_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } @@ -1267,6 +1268,7 @@ func autoConvert_certmanager_JKSKeystore_To_v1beta1_JKSKeystore(in *certmanager. if err := apismetav1.Convert_meta_SecretKeySelector_To_v1_SecretKeySelector(&in.PasswordSecretRef, &out.PasswordSecretRef, s); err != nil { return err } + out.Alias = (*string)(unsafe.Pointer(in.Alias)) return nil } diff --git a/internal/apis/certmanager/v1beta1/zz_generated.deepcopy.go b/internal/apis/certmanager/v1beta1/zz_generated.deepcopy.go index dc1da740a..59492f6ae 100644 --- a/internal/apis/certmanager/v1beta1/zz_generated.deepcopy.go +++ b/internal/apis/certmanager/v1beta1/zz_generated.deepcopy.go @@ -129,7 +129,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.JKS != nil { in, out := &in.JKS, &out.JKS *out = new(JKSKeystore) - **out = **in + (*in).DeepCopyInto(*out) } if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 @@ -781,6 +781,11 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(string) + **out = **in + } return } diff --git a/internal/apis/certmanager/zz_generated.deepcopy.go b/internal/apis/certmanager/zz_generated.deepcopy.go index 631f68e1d..49380ee89 100644 --- a/internal/apis/certmanager/zz_generated.deepcopy.go +++ b/internal/apis/certmanager/zz_generated.deepcopy.go @@ -129,7 +129,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.JKS != nil { in, out := &in.JKS, &out.JKS *out = new(JKSKeystore) - **out = **in + (*in).DeepCopyInto(*out) } if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 @@ -781,6 +781,11 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(string) + **out = **in + } return } diff --git a/pkg/apis/certmanager/v1/types_certificate.go b/pkg/apis/certmanager/v1/types_certificate.go index 743cd3e35..0d0556b76 100644 --- a/pkg/apis/certmanager/v1/types_certificate.go +++ b/pkg/apis/certmanager/v1/types_certificate.go @@ -460,6 +460,11 @@ type JKSKeystore struct { // PasswordSecretRef is a reference to a key in a Secret resource // containing the password used to encrypt the JKS keystore. PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` + + // Alias specifies the alias of the key in the keystore, required by the JKS format. + // If not provided, the default alias `certificate` will be used. + // +optional + Alias *string `json:"alias,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the diff --git a/pkg/apis/certmanager/v1/zz_generated.deepcopy.go b/pkg/apis/certmanager/v1/zz_generated.deepcopy.go index 453560285..27331ba59 100644 --- a/pkg/apis/certmanager/v1/zz_generated.deepcopy.go +++ b/pkg/apis/certmanager/v1/zz_generated.deepcopy.go @@ -129,7 +129,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.JKS != nil { in, out := &in.JKS, &out.JKS *out = new(JKSKeystore) - **out = **in + (*in).DeepCopyInto(*out) } if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 @@ -781,6 +781,11 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(string) + **out = **in + } return } diff --git a/pkg/controller/certificates/issuing/internal/keystore.go b/pkg/controller/certificates/issuing/internal/keystore.go index 3f05fccb7..1ad79c44b 100644 --- a/pkg/controller/certificates/issuing/internal/keystore.go +++ b/pkg/controller/certificates/issuing/internal/keystore.go @@ -92,7 +92,7 @@ func encodePKCS12Truststore(profile cmapi.PKCS12Profile, password string, caPem } } -func encodeJKSKeystore(password []byte, rawKey []byte, certPem []byte, caPem []byte) ([]byte, error) { +func encodeJKSKeystore(password []byte, keyAlias string, rawKey []byte, certPem []byte, caPem []byte) ([]byte, error) { // encode the private key to PKCS8 key, err := pki.DecodePrivateKeyBytes(rawKey) if err != nil { @@ -117,7 +117,7 @@ func encodeJKSKeystore(password []byte, rawKey []byte, certPem []byte, caPem []b } ks := jks.New() - if err = ks.SetPrivateKeyEntry("certificate", jks.PrivateKeyEntry{ + if err = ks.SetPrivateKeyEntry(keyAlias, jks.PrivateKeyEntry{ CreationTime: time.Now(), PrivateKey: keyDER, CertificateChain: certs, diff --git a/pkg/controller/certificates/issuing/internal/keystore_test.go b/pkg/controller/certificates/issuing/internal/keystore_test.go index 969d86107..4f666580e 100644 --- a/pkg/controller/certificates/issuing/internal/keystore_test.go +++ b/pkg/controller/certificates/issuing/internal/keystore_test.go @@ -157,11 +157,13 @@ func mustLeafWithChain(t *testing.T) leafWithChain { func TestEncodeJKSKeystore(t *testing.T) { tests := map[string]struct { password string + alias string rawKey, certPEM, caPEM []byte verify func(t *testing.T, out []byte, err error) }{ "encode a JKS bundle for a PKCS1 key and certificate only": { password: "password", + alias: "alias", rawKey: mustGeneratePrivateKey(t, cmapi.PKCS1), certPEM: mustSelfSignCertificate(t, nil), verify: func(t *testing.T, out []byte, err error) { @@ -177,7 +179,7 @@ func TestEncodeJKSKeystore(t *testing.T) { return } - if !ks.IsPrivateKeyEntry("certificate") { + if !ks.IsPrivateKeyEntry("alias") { t.Errorf("no certificate data found in keystore") } @@ -188,6 +190,7 @@ func TestEncodeJKSKeystore(t *testing.T) { }, "encode a JKS bundle for a PKCS8 key and certificate only": { password: "password", + alias: "alias", rawKey: mustGeneratePrivateKey(t, cmapi.PKCS8), certPEM: mustSelfSignCertificate(t, nil), verify: func(t *testing.T, out []byte, err error) { @@ -201,7 +204,7 @@ func TestEncodeJKSKeystore(t *testing.T) { t.Errorf("error decoding keystore: %v", err) return } - if !ks.IsPrivateKeyEntry("certificate") { + if !ks.IsPrivateKeyEntry("alias") { t.Errorf("no certificate data found in keystore") } @@ -212,6 +215,7 @@ func TestEncodeJKSKeystore(t *testing.T) { }, "encode a JKS bundle for a key, certificate and ca": { password: "password", + alias: "alias", rawKey: mustGeneratePrivateKey(t, cmapi.PKCS8), certPEM: mustSelfSignCertificate(t, nil), caPEM: mustSelfSignCertificate(t, nil), @@ -226,7 +230,7 @@ func TestEncodeJKSKeystore(t *testing.T) { t.Errorf("error decoding keystore: %v", err) return } - if !ks.IsPrivateKeyEntry("certificate") { + if !ks.IsPrivateKeyEntry("alias") { t.Errorf("no certificate data found in keystore") } if !ks.IsTrustedCertificateEntry("ca") { @@ -236,6 +240,7 @@ func TestEncodeJKSKeystore(t *testing.T) { }, "encode a JKS bundle for a key, certificate and multiple cas": { password: "password", + alias: "alias", rawKey: mustGeneratePrivateKey(t, cmapi.PKCS8), certPEM: mustSelfSignCertificate(t, nil), caPEM: mustSelfSignCertificates(t, 3), @@ -250,7 +255,7 @@ func TestEncodeJKSKeystore(t *testing.T) { t.Errorf("error decoding keystore: %v", err) return } - if !ks.IsPrivateKeyEntry("certificate") { + if !ks.IsPrivateKeyEntry("alias") { t.Errorf("no certificate data found in keystore") } if !ks.IsTrustedCertificateEntry("ca") { @@ -270,7 +275,7 @@ func TestEncodeJKSKeystore(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - out, err := encodeJKSKeystore([]byte(test.password), test.rawKey, test.certPEM, test.caPEM) + out, err := encodeJKSKeystore([]byte(test.password), test.alias, test.rawKey, test.certPEM, test.caPEM) test.verify(t, out, err) }) } @@ -559,7 +564,7 @@ func TestManyPasswordLengths(t *testing.T) { } g.Go(func() error { defer s.Release(1) - keystore, err := encodeJKSKeystore([]byte(passwords[testi]), rawKey, certPEM, caPEM) + keystore, err := encodeJKSKeystore([]byte(passwords[testi]), "alias", rawKey, certPEM, caPEM) if err != nil { t.Errorf("couldn't encode JKS Keystore with password %s (length %d): %s", passwords[testi], len(passwords[testi]), err.Error()) return err @@ -572,7 +577,7 @@ func TestManyPasswordLengths(t *testing.T) { t.Errorf("error decoding keystore with password %s (length %d): %v", passwords[testi], len(passwords[testi]), err) return err } - if !ks.IsPrivateKeyEntry("certificate") { + if !ks.IsPrivateKeyEntry("alias") { t.Errorf("no certificate data found in keystore") } if !ks.IsTrustedCertificateEntry("ca") { diff --git a/pkg/controller/certificates/issuing/internal/secret.go b/pkg/controller/certificates/issuing/internal/secret.go index 68d49648b..c259f754e 100644 --- a/pkg/controller/certificates/issuing/internal/secret.go +++ b/pkg/controller/certificates/issuing/internal/secret.go @@ -287,7 +287,11 @@ func (s *SecretsManager) setKeystores(crt *cmapi.Certificate, secret *corev1.Sec return fmt.Errorf("JKS keystore password Secret contains no data for key %q", ref.Key) } pw := pwSecret.Data[ref.Key] - keystoreData, err := encodeJKSKeystore(pw, data.PrivateKey, data.Certificate, data.CA) + alias := "certificate" + if crt.Spec.Keystores.JKS.Alias != nil { + alias = *crt.Spec.Keystores.JKS.Alias + } + keystoreData, err := encodeJKSKeystore(pw, alias, data.PrivateKey, data.Certificate, data.CA) if err != nil { return fmt.Errorf("error encoding JKS bundle: %w", err) }