Merge pull request #5239 from oGi4i/issue-4997
Add private key Ingress annotations to set private key properties for Certificate
This commit is contained in:
commit
3ecf7ae5bb
@ -59,6 +59,33 @@ const (
|
||||
// Minimum value is 1.
|
||||
// If unset all CertificateRequests will be kept.
|
||||
RevisionHistoryLimitAnnotationKey = "cert-manager.io/revision-history-limit"
|
||||
|
||||
// Annotation key used to set the PrivateKeyAlgorithm for a Certificate.
|
||||
// If PrivateKeyAlgorithm is specified and `size` is not provided,
|
||||
// key size of 256 will be used for `ECDSA` key algorithm and
|
||||
// key size of 2048 will be used for `RSA` key algorithm.
|
||||
// key size is ignored when using the `Ed25519` key algorithm.
|
||||
// If unset an algorithm `RSA` will be used.
|
||||
PrivateKeyAlgorithmAnnotationKey = "cert-manager.io/private-key-algorithm"
|
||||
|
||||
// Annotation key used to set the PrivateKeyEncoding for a Certificate.
|
||||
// If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1
|
||||
// and PKCS#8, respectively.
|
||||
// If unset an encoding `PKCS1` will be used.
|
||||
PrivateKeyEncodingAnnotationKey = "cert-manager.io/private-key-encoding"
|
||||
|
||||
// Annotation key used to set the size of the private key for a Certificate.
|
||||
// If PrivateKeyAlgorithm is set to `RSA`, valid values are `2048`, `4096` or `8192`,
|
||||
// and will default to `2048` if not specified.
|
||||
// If PrivateKeyAlgorithm is set to `ECDSA`, valid values are `256`, `384` or `521`,
|
||||
// and will default to `256` if not specified.
|
||||
// If PrivateKeyAlgorithm is set to `Ed25519`, Size is ignored.
|
||||
// No other values are allowed.
|
||||
PrivateKeySizeAnnotationKey = "cert-manager.io/private-key-size"
|
||||
|
||||
// Annotation key used to set the PrivateKeyRotationPolicy for a Certificate.
|
||||
// If unset a policy `Never` will be used.
|
||||
PrivateKeyRotationPolicyAnnotationKey = "cert-manager.io/private-key-rotation-policy"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@ -110,5 +110,84 @@ func translateAnnotations(crt *cmapi.Certificate, ingLikeAnnotations map[string]
|
||||
crt.Spec.RevisionHistoryLimit = pointer.Int32(int32(limit))
|
||||
}
|
||||
|
||||
if privateKeyAlgorithm, found := ingLikeAnnotations[cmapi.PrivateKeyAlgorithmAnnotationKey]; found {
|
||||
algorithm := cmapi.PrivateKeyAlgorithm(privateKeyAlgorithm)
|
||||
switch algorithm {
|
||||
case cmapi.RSAKeyAlgorithm,
|
||||
cmapi.ECDSAKeyAlgorithm,
|
||||
cmapi.Ed25519KeyAlgorithm:
|
||||
// ok
|
||||
default:
|
||||
return fmt.Errorf("%w %q: invalid private key algorithm %q", errInvalidIngressAnnotation, cmapi.PrivateKeyAlgorithmAnnotationKey, privateKeyAlgorithm)
|
||||
}
|
||||
|
||||
if crt.Spec.PrivateKey == nil {
|
||||
crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{Algorithm: algorithm}
|
||||
} else {
|
||||
crt.Spec.PrivateKey.Algorithm = algorithm
|
||||
}
|
||||
}
|
||||
|
||||
if privateKeyEncoding, found := ingLikeAnnotations[cmapi.PrivateKeyEncodingAnnotationKey]; found {
|
||||
encoding := cmapi.PrivateKeyEncoding(privateKeyEncoding)
|
||||
if encoding != cmapi.PKCS1 &&
|
||||
encoding != cmapi.PKCS8 {
|
||||
return fmt.Errorf("%w %q: invalid private key encoding %q", errInvalidIngressAnnotation, cmapi.PrivateKeyEncodingAnnotationKey, privateKeyEncoding)
|
||||
}
|
||||
|
||||
if crt.Spec.PrivateKey == nil {
|
||||
crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{Encoding: encoding}
|
||||
} else {
|
||||
crt.Spec.PrivateKey.Encoding = encoding
|
||||
}
|
||||
}
|
||||
|
||||
if privateKeySize, found := ingLikeAnnotations[cmapi.PrivateKeySizeAnnotationKey]; found {
|
||||
size, err := strconv.Atoi(privateKeySize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w %q: %v", errInvalidIngressAnnotation, cmapi.PrivateKeySizeAnnotationKey, err)
|
||||
}
|
||||
|
||||
// default algorithm
|
||||
algorithm := cmapi.RSAKeyAlgorithm
|
||||
if crt.Spec.PrivateKey != nil && crt.Spec.PrivateKey.Algorithm != "" {
|
||||
algorithm = crt.Spec.PrivateKey.Algorithm
|
||||
}
|
||||
|
||||
switch algorithm {
|
||||
case cmapi.RSAKeyAlgorithm:
|
||||
if size < 2048 || size > 8192 {
|
||||
return fmt.Errorf("%w %q: invalid private key size for RSA algorithm %q", errInvalidIngressAnnotation, cmapi.PrivateKeySizeAnnotationKey, privateKeySize)
|
||||
}
|
||||
case cmapi.ECDSAKeyAlgorithm:
|
||||
switch size {
|
||||
case 256, 384, 521:
|
||||
// ok
|
||||
default:
|
||||
return fmt.Errorf("%w %q: invalid private key size for ECDSA algorithm %q", errInvalidIngressAnnotation, cmapi.PrivateKeySizeAnnotationKey, privateKeySize)
|
||||
}
|
||||
}
|
||||
|
||||
if crt.Spec.PrivateKey == nil {
|
||||
crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{Size: size}
|
||||
} else {
|
||||
crt.Spec.PrivateKey.Size = size
|
||||
}
|
||||
}
|
||||
|
||||
if privateKeyRotationPolicy, found := ingLikeAnnotations[cmapi.PrivateKeyRotationPolicyAnnotationKey]; found {
|
||||
rotationPolicy := cmapi.PrivateKeyRotationPolicy(privateKeyRotationPolicy)
|
||||
if rotationPolicy != cmapi.RotationPolicyNever &&
|
||||
rotationPolicy != cmapi.RotationPolicyAlways {
|
||||
return fmt.Errorf("%w %q: invalid private key rotation policy %q", errInvalidIngressAnnotation, cmapi.PrivateKeyRotationPolicyAnnotationKey, privateKeyRotationPolicy)
|
||||
}
|
||||
|
||||
if crt.Spec.PrivateKey == nil {
|
||||
crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{RotationPolicy: rotationPolicy}
|
||||
} else {
|
||||
crt.Spec.PrivateKey.RotationPolicy = rotationPolicy
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -60,6 +60,73 @@ func Test_translateAnnotations(t *testing.T) {
|
||||
a.Equal(pointer.Int32(7), crt.Spec.RevisionHistoryLimit)
|
||||
},
|
||||
},
|
||||
"success rsa private key algorithm": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: map[string]string{
|
||||
cmapi.CommonNameAnnotationKey: "www.example.com",
|
||||
cmapi.DurationAnnotationKey: "168h", // 1 week
|
||||
cmapi.RenewBeforeAnnotationKey: "24h",
|
||||
cmapi.UsagesAnnotationKey: "server auth,signing",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "RSA",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "PKCS1",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "2048",
|
||||
cmapi.PrivateKeyRotationPolicyAnnotationKey: "Always",
|
||||
},
|
||||
check: func(a *assert.Assertions, crt *cmapi.Certificate) {
|
||||
a.Equal("www.example.com", crt.Spec.CommonName)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24 * 7}, crt.Spec.Duration)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24}, crt.Spec.RenewBefore)
|
||||
a.Equal([]cmapi.KeyUsage{cmapi.UsageServerAuth, cmapi.UsageSigning}, crt.Spec.Usages)
|
||||
a.Equal(cmapi.RSAKeyAlgorithm, crt.Spec.PrivateKey.Algorithm)
|
||||
a.Equal(cmapi.PKCS1, crt.Spec.PrivateKey.Encoding)
|
||||
a.Equal(2048, crt.Spec.PrivateKey.Size)
|
||||
a.Equal(cmapi.RotationPolicyAlways, crt.Spec.PrivateKey.RotationPolicy)
|
||||
},
|
||||
},
|
||||
"success ecdsa private key algorithm": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: map[string]string{
|
||||
cmapi.CommonNameAnnotationKey: "www.example.com",
|
||||
cmapi.DurationAnnotationKey: "168h", // 1 week
|
||||
cmapi.RenewBeforeAnnotationKey: "24h",
|
||||
cmapi.UsagesAnnotationKey: "server auth,signing",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "ECDSA",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "PKCS1",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "256",
|
||||
cmapi.PrivateKeyRotationPolicyAnnotationKey: "Always",
|
||||
},
|
||||
check: func(a *assert.Assertions, crt *cmapi.Certificate) {
|
||||
a.Equal("www.example.com", crt.Spec.CommonName)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24 * 7}, crt.Spec.Duration)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24}, crt.Spec.RenewBefore)
|
||||
a.Equal([]cmapi.KeyUsage{cmapi.UsageServerAuth, cmapi.UsageSigning}, crt.Spec.Usages)
|
||||
a.Equal(cmapi.ECDSAKeyAlgorithm, crt.Spec.PrivateKey.Algorithm)
|
||||
a.Equal(cmapi.PKCS1, crt.Spec.PrivateKey.Encoding)
|
||||
a.Equal(256, crt.Spec.PrivateKey.Size)
|
||||
a.Equal(cmapi.RotationPolicyAlways, crt.Spec.PrivateKey.RotationPolicy)
|
||||
},
|
||||
},
|
||||
"success ed25519 private key algorithm": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: map[string]string{
|
||||
cmapi.CommonNameAnnotationKey: "www.example.com",
|
||||
cmapi.DurationAnnotationKey: "168h", // 1 week
|
||||
cmapi.RenewBeforeAnnotationKey: "24h",
|
||||
cmapi.UsagesAnnotationKey: "server auth,signing",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "Ed25519",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "PKCS8",
|
||||
cmapi.PrivateKeyRotationPolicyAnnotationKey: "Always",
|
||||
},
|
||||
check: func(a *assert.Assertions, crt *cmapi.Certificate) {
|
||||
a.Equal("www.example.com", crt.Spec.CommonName)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24 * 7}, crt.Spec.Duration)
|
||||
a.Equal(&metav1.Duration{Duration: time.Hour * 24}, crt.Spec.RenewBefore)
|
||||
a.Equal([]cmapi.KeyUsage{cmapi.UsageServerAuth, cmapi.UsageSigning}, crt.Spec.Usages)
|
||||
a.Equal(cmapi.Ed25519KeyAlgorithm, crt.Spec.PrivateKey.Algorithm)
|
||||
a.Equal(cmapi.PKCS8, crt.Spec.PrivateKey.Encoding)
|
||||
a.Equal(cmapi.RotationPolicyAlways, crt.Spec.PrivateKey.RotationPolicy)
|
||||
},
|
||||
},
|
||||
"nil annotations": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: nil,
|
||||
@ -121,6 +188,64 @@ func Test_translateAnnotations(t *testing.T) {
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key algorithm": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeyAlgorithmAnnotationKey] = "invalid private key algorithm"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key encoding": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeyEncodingAnnotationKey] = "invalid private key encoding"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key rotation policy": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeyRotationPolicyAnnotationKey] = "invalid private key rotation policy"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key size": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeySizeAnnotationKey] = "invalid private key size"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"zero private key size": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeySizeAnnotationKey] = "0"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key size for rsa": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeyAlgorithmAnnotationKey] = "RSA"
|
||||
tc.annotations[cmapi.PrivateKeySizeAnnotationKey] = "1024"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
"bad private key size for ecdsa": {
|
||||
crt: gen.Certificate("example-cert"),
|
||||
annotations: validAnnotations(),
|
||||
mutate: func(tc *testCase) {
|
||||
tc.annotations[cmapi.PrivateKeyAlgorithmAnnotationKey] = "ECDSA"
|
||||
tc.annotations[cmapi.PrivateKeySizeAnnotationKey] = "128"
|
||||
},
|
||||
expectedError: errInvalidIngressAnnotation,
|
||||
},
|
||||
}
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
@ -508,6 +508,65 @@ func certNeedsUpdate(a, b *cmapi.Certificate) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if a.Spec.RevisionHistoryLimit != b.Spec.RevisionHistoryLimit {
|
||||
return true
|
||||
}
|
||||
|
||||
var aAlgorithm, bAlgorithm cmapi.PrivateKeyAlgorithm
|
||||
if a.Spec.PrivateKey != nil && a.Spec.PrivateKey.Algorithm != "" {
|
||||
aAlgorithm = a.Spec.PrivateKey.Algorithm
|
||||
}
|
||||
|
||||
if b.Spec.PrivateKey != nil && b.Spec.PrivateKey.Algorithm != "" {
|
||||
bAlgorithm = b.Spec.PrivateKey.Algorithm
|
||||
}
|
||||
|
||||
if aAlgorithm != bAlgorithm {
|
||||
return true
|
||||
}
|
||||
|
||||
var aEncoding, bEncoding cmapi.PrivateKeyEncoding
|
||||
if a.Spec.PrivateKey != nil && a.Spec.PrivateKey.Encoding != "" {
|
||||
aEncoding = a.Spec.PrivateKey.Encoding
|
||||
}
|
||||
|
||||
if b.Spec.PrivateKey != nil && b.Spec.PrivateKey.Encoding != "" {
|
||||
bEncoding = b.Spec.PrivateKey.Encoding
|
||||
}
|
||||
|
||||
if aEncoding != bEncoding {
|
||||
return true
|
||||
}
|
||||
|
||||
var aRotationPolicy, bRotationPolicy cmapi.PrivateKeyRotationPolicy
|
||||
if a.Spec.PrivateKey != nil && a.Spec.PrivateKey.RotationPolicy != "" {
|
||||
aRotationPolicy = a.Spec.PrivateKey.RotationPolicy
|
||||
}
|
||||
|
||||
if b.Spec.PrivateKey != nil && b.Spec.PrivateKey.RotationPolicy != "" {
|
||||
bRotationPolicy = b.Spec.PrivateKey.RotationPolicy
|
||||
}
|
||||
|
||||
if aRotationPolicy != bRotationPolicy {
|
||||
return true
|
||||
}
|
||||
|
||||
// for Ed25519 private key size is ignored
|
||||
if aAlgorithm != cmapi.Ed25519KeyAlgorithm {
|
||||
var aSize, bSize int
|
||||
if a.Spec.PrivateKey != nil && a.Spec.PrivateKey.Size != 0 {
|
||||
aSize = a.Spec.PrivateKey.Size
|
||||
}
|
||||
|
||||
if b.Spec.PrivateKey != nil && b.Spec.PrivateKey.Size != 0 {
|
||||
bSize = b.Spec.PrivateKey.Size
|
||||
}
|
||||
|
||||
if aSize != bSize {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
"k8s.io/utils/pointer"
|
||||
gwapi "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||
|
||||
cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1"
|
||||
@ -787,6 +788,360 @@ func TestSync(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should update an existing Certificate resource with different revision limit if it does not match specified on the IngressLike",
|
||||
Issuer: acmeIssuer,
|
||||
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
|
||||
IngressLike: &networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.RevisionHistoryLimitAnnotationKey: "1",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
TLS: []networkingv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultIssuerKind: "Issuer",
|
||||
CertificateLister: []runtime.Object{
|
||||
&cmapi.Certificate{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
RevisionHistoryLimit: pointer.Int32(7),
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedEvents: []string{`Normal UpdateCertificate Successfully updated Certificate "cert-secret-name"`},
|
||||
ExpectedUpdate: []*cmapi.Certificate{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
RevisionHistoryLimit: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should update an existing Certificate resource with different rsa private key size if it does not match specified on the IngressLike",
|
||||
Issuer: acmeIssuer,
|
||||
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
|
||||
IngressLike: &networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "RSA",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "4096",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
TLS: []networkingv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultIssuerKind: "Issuer",
|
||||
CertificateLister: []runtime.Object{
|
||||
&cmapi.Certificate{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.RSAKeyAlgorithm,
|
||||
Size: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedEvents: []string{`Normal UpdateCertificate Successfully updated Certificate "cert-secret-name"`},
|
||||
ExpectedUpdate: []*cmapi.Certificate{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.RSAKeyAlgorithm,
|
||||
Size: 4096,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should update an existing Certificate resource with different ecdsa private key size if it does not match specified on the IngressLike",
|
||||
Issuer: acmeIssuer,
|
||||
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
|
||||
IngressLike: &networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "ECDSA",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "384",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
TLS: []networkingv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultIssuerKind: "Issuer",
|
||||
CertificateLister: []runtime.Object{
|
||||
&cmapi.Certificate{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Size: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedEvents: []string{`Normal UpdateCertificate Successfully updated Certificate "cert-secret-name"`},
|
||||
ExpectedUpdate: []*cmapi.Certificate{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Size: 384,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should update an existing Certificate resource with different private key encoding if it does not match specified on the IngressLike",
|
||||
Issuer: acmeIssuer,
|
||||
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
|
||||
IngressLike: &networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "ECDSA",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "PKCS8",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "384",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
TLS: []networkingv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultIssuerKind: "Issuer",
|
||||
CertificateLister: []runtime.Object{
|
||||
&cmapi.Certificate{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Size: 384,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedEvents: []string{`Normal UpdateCertificate Successfully updated Certificate "cert-secret-name"`},
|
||||
ExpectedUpdate: []*cmapi.Certificate{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Encoding: cmapi.PKCS8,
|
||||
Size: 384,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should update an existing Certificate resource with different private key rotation policy if it does not match specified on the IngressLike",
|
||||
Issuer: acmeIssuer,
|
||||
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
|
||||
IngressLike: &networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "ECDSA",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "PKCS1",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "384",
|
||||
cmapi.PrivateKeyRotationPolicyAnnotationKey: "Always",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
TLS: []networkingv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultIssuerKind: "Issuer",
|
||||
CertificateLister: []runtime.Object{
|
||||
&cmapi.Certificate{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Size: 384,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedEvents: []string{`Normal UpdateCertificate Successfully updated Certificate "cert-secret-name"`},
|
||||
ExpectedUpdate: []*cmapi.Certificate{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cert-secret-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
|
||||
},
|
||||
Spec: cmapi.CertificateSpec{
|
||||
DNSNames: []string{"example.com"},
|
||||
SecretName: "cert-secret-name",
|
||||
IssuerRef: cmmeta.ObjectReference{
|
||||
Name: "issuer-name",
|
||||
Kind: "Issuer",
|
||||
},
|
||||
Usages: cmapi.DefaultKeyUsages(),
|
||||
PrivateKey: &cmapi.CertificatePrivateKey{
|
||||
Algorithm: cmapi.ECDSAKeyAlgorithm,
|
||||
Encoding: cmapi.PKCS1,
|
||||
Size: 384,
|
||||
RotationPolicy: cmapi.RotationPolicyAlways,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "should not update certificate if it does not belong to any ingress",
|
||||
Issuer: acmeIssuer,
|
||||
@ -1027,11 +1382,15 @@ func TestSync(t *testing.T) {
|
||||
Name: "ingress-name",
|
||||
Namespace: gen.DefaultTestNamespace,
|
||||
Annotations: map[string]string{
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.IssuerKindAnnotationKey: "Issuer",
|
||||
cmapi.IssuerGroupAnnotationKey: "cert-manager.io",
|
||||
cmapi.RenewBeforeAnnotationKey: "invalid renew before value",
|
||||
cmapi.RevisionHistoryLimitAnnotationKey: "invalid revision history limit value",
|
||||
cmapi.IngressIssuerNameAnnotationKey: "issuer-name",
|
||||
cmapi.IssuerKindAnnotationKey: "Issuer",
|
||||
cmapi.IssuerGroupAnnotationKey: "cert-manager.io",
|
||||
cmapi.RenewBeforeAnnotationKey: "invalid renew before value",
|
||||
cmapi.RevisionHistoryLimitAnnotationKey: "invalid revision history limit value",
|
||||
cmapi.PrivateKeyAlgorithmAnnotationKey: "invalid private key algorithm value",
|
||||
cmapi.PrivateKeyEncodingAnnotationKey: "invalid private key encoding value",
|
||||
cmapi.PrivateKeySizeAnnotationKey: "invalid private key size value",
|
||||
cmapi.PrivateKeyRotationPolicyAnnotationKey: "invalid private key rotation policy value",
|
||||
},
|
||||
UID: types.UID("ingress-name"),
|
||||
},
|
||||
|
||||
@ -786,7 +786,11 @@ func (s *Suite) Define() {
|
||||
domain := e2eutil.RandomSubdomain(s.DomainSuffix)
|
||||
duration := time.Hour * 999
|
||||
renewBefore := time.Hour * 111
|
||||
revisitionHistoryLimit := pointer.Int32(7)
|
||||
revisionHistoryLimit := pointer.Int32(7)
|
||||
privateKeyAlgorithm := cmapi.RSAKeyAlgorithm
|
||||
privateKeyEncoding := cmapi.PKCS1
|
||||
privateKeySize := 4096
|
||||
privateKeyRotationPolicy := cmapi.RotationPolicyAlways
|
||||
|
||||
switch {
|
||||
case e2eutil.HasIngresses(f.KubeClientSet.Discovery(), networkingv1.SchemeGroupVersion.String()):
|
||||
@ -797,13 +801,17 @@ func (s *Suite) Define() {
|
||||
|
||||
By("Creating an Ingress with annotations for issuerRef and other Certificate fields")
|
||||
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewIngress(name, secretName, map[string]string{
|
||||
"cert-manager.io/issuer": issuerRef.Name,
|
||||
"cert-manager.io/issuer-kind": issuerRef.Kind,
|
||||
"cert-manager.io/issuer-group": issuerRef.Group,
|
||||
"cert-manager.io/common-name": domain,
|
||||
"cert-manager.io/duration": duration.String(),
|
||||
"cert-manager.io/renew-before": renewBefore.String(),
|
||||
"cert-manager.io/revision-history-limit": strconv.FormatInt(int64(*revisitionHistoryLimit), 10),
|
||||
"cert-manager.io/issuer": issuerRef.Name,
|
||||
"cert-manager.io/issuer-kind": issuerRef.Kind,
|
||||
"cert-manager.io/issuer-group": issuerRef.Group,
|
||||
"cert-manager.io/common-name": domain,
|
||||
"cert-manager.io/duration": duration.String(),
|
||||
"cert-manager.io/renew-before": renewBefore.String(),
|
||||
"cert-manager.io/revision-history-limit": strconv.FormatInt(int64(*revisionHistoryLimit), 10),
|
||||
"cert-manager.io/private-key-algorithm": string(privateKeyAlgorithm),
|
||||
"cert-manager.io/private-key-encoding": string(privateKeyEncoding),
|
||||
"cert-manager.io/private-key-size": strconv.Itoa(privateKeySize),
|
||||
"cert-manager.io/private-key-rotation-policy": string(privateKeyRotationPolicy),
|
||||
}, domain), metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@ -816,13 +824,17 @@ func (s *Suite) Define() {
|
||||
|
||||
By("Creating an Ingress with annotations for issuerRef and other Certificate fields")
|
||||
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewV1Beta1Ingress(name, secretName, map[string]string{
|
||||
"cert-manager.io/issuer": issuerRef.Name,
|
||||
"cert-manager.io/issuer-kind": issuerRef.Kind,
|
||||
"cert-manager.io/issuer-group": issuerRef.Group,
|
||||
"cert-manager.io/common-name": domain,
|
||||
"cert-manager.io/duration": duration.String(),
|
||||
"cert-manager.io/renew-before": renewBefore.String(),
|
||||
"cert-manager.io/revision-history-limit": strconv.FormatInt(int64(*revisitionHistoryLimit), 10),
|
||||
"cert-manager.io/issuer": issuerRef.Name,
|
||||
"cert-manager.io/issuer-kind": issuerRef.Kind,
|
||||
"cert-manager.io/issuer-group": issuerRef.Group,
|
||||
"cert-manager.io/common-name": domain,
|
||||
"cert-manager.io/duration": duration.String(),
|
||||
"cert-manager.io/renew-before": renewBefore.String(),
|
||||
"cert-manager.io/revision-history-limit": strconv.FormatInt(int64(*revisionHistoryLimit), 10),
|
||||
"cert-manager.io/private-key-algorithm": string(privateKeyAlgorithm),
|
||||
"cert-manager.io/private-key-encoding": string(privateKeyEncoding),
|
||||
"cert-manager.io/private-key-size": strconv.Itoa(privateKeySize),
|
||||
"cert-manager.io/private-key-rotation-policy": string(privateKeyRotationPolicy),
|
||||
}, domain), metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@ -849,7 +861,11 @@ func (s *Suite) Define() {
|
||||
Expect(certificate.Spec.CommonName).To(Equal(domain))
|
||||
Expect(certificate.Spec.Duration.Duration).To(Equal(duration))
|
||||
Expect(certificate.Spec.RenewBefore.Duration).To(Equal(renewBefore))
|
||||
Expect(certificate.Spec.RevisionHistoryLimit).To(Equal(revisitionHistoryLimit))
|
||||
Expect(certificate.Spec.RevisionHistoryLimit).To(Equal(revisionHistoryLimit))
|
||||
Expect(certificate.Spec.PrivateKey.Algorithm).To(Equal(privateKeyAlgorithm))
|
||||
Expect(certificate.Spec.PrivateKey.Encoding).To(Equal(privateKeyEncoding))
|
||||
Expect(certificate.Spec.PrivateKey.Size).To(Equal(privateKeySize))
|
||||
Expect(certificate.Spec.PrivateKey.RotationPolicy).To(Equal(privateKeyRotationPolicy))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user