Skip to content

Commit

Permalink
Merge pull request #6839 from mangeshhambarde/ingress-annotations-for…
Browse files Browse the repository at this point in the history
…-secret-template

Add secretTemplate to Certificate resources created by ingress-shim
  • Loading branch information
jetstack-bot committed Mar 14, 2024
2 parents 3a26313 + f3bfc93 commit 5213a53
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pkg/apis/certmanager/v1/types.go
Expand Up @@ -145,6 +145,10 @@ const (
// controller only processes Ingresses with this annotation either unset, or
// set to either the configured value or the empty string.
IngressClassAnnotationKey = "kubernetes.io/ingress.class"

// IngressSecretTemplate can be used to set the secretTemplate field in the generated Certificate.
// The value is a JSON representation of secretTemplate and must not have any unknown fields.
IngressSecretTemplate = "cert-manager.io/secret-template"
)

// Annotation names for CertificateRequests
Expand Down
19 changes: 19 additions & 0 deletions pkg/controller/certificate-shim/helper.go
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package shimhelper

import (
"encoding/json"
"errors"
"fmt"
"reflect"
Expand Down Expand Up @@ -268,5 +269,23 @@ func translateAnnotations(crt *cmapi.Certificate, ingLikeAnnotations map[string]
}
}

if secretTemplateJson, found := ingLikeAnnotations[cmapi.IngressSecretTemplate]; found {
decoder := json.NewDecoder(strings.NewReader(secretTemplateJson))
decoder.DisallowUnknownFields()

var secretTemplate = new(cmapi.CertificateSecretTemplate)
if err := decoder.Decode(secretTemplate); err != nil {
return fmt.Errorf("%w %q: error parsing secret template JSON: %v", errInvalidIngressAnnotation, cmapi.IngressSecretTemplate, err)
}
for annotationKey := range secretTemplate.Annotations {
if strings.HasPrefix(annotationKey, "cert-manager.io/") {
return fmt.Errorf("%w %q: secretTemplate must not have cert-manager.io/ annotations: %q", errInvalidIngressAnnotation, cmapi.IngressSecretTemplate, annotationKey)
}
}
if len(secretTemplate.Annotations) > 0 || len(secretTemplate.Labels) > 0 {
crt.Spec.SecretTemplate = secretTemplate
}
}

return nil
}
99 changes: 99 additions & 0 deletions pkg/controller/certificate-shim/sync_test.go
Expand Up @@ -536,6 +536,105 @@ func TestSync(t *testing.T) {
},
},
},
{
Name: "return a single HTTP01 Certificate for an ingress with a single valid TLS entry and valid secret template annotation",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
Annotations: map[string]string{
cmapi.IngressClusterIssuerNameAnnotationKey: "issuer-name",
cmapi.IngressSecretTemplate: `{ "annotations": { "example-annotation" : "dummy-value" }, "labels": { "example-label" : "dummy-value" } }`,
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
},
},
},
},
ClusterIssuerLister: []runtime.Object{acmeClusterIssuer},
ExpectedEvents: []string{`Normal CreateCertificate Successfully created Certificate "example-com-tls"`},
ExpectedCreate: []*cmapi.Certificate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-com-tls",
Namespace: gen.DefaultTestNamespace,
OwnerReferences: buildIngressOwnerReferences("ingress-name", gen.DefaultTestNamespace),
},
Spec: cmapi.CertificateSpec{
DNSNames: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
SecretTemplate: &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{
"example-annotation": "dummy-value",
},
Labels: map[string]string{
"example-label": "dummy-value",
},
},
IssuerRef: cmmeta.ObjectReference{
Name: "issuer-name",
Kind: "ClusterIssuer",
},
Usages: cmapi.DefaultKeyUsages(),
},
},
},
},
{
Name: "secret template annotation should not allow cert-manager.io/ annotations",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
Annotations: map[string]string{
cmapi.IngressClusterIssuerNameAnnotationKey: "issuer-name",
cmapi.IngressSecretTemplate: `{ "annotations": { "cert-manager.io/disallowed-annotation" : "dummy-value" } }`,
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
},
},
},
},
Err: true,
},
{
Name: "secret template annotation should not allow unknown fields",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
Annotations: map[string]string{
cmapi.IngressClusterIssuerNameAnnotationKey: "issuer-name",
cmapi.IngressSecretTemplate: `{ "unknown-field": "true" }`,
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
},
},
},
},
Err: true,
},
{
Name: "edit-in-place set to false should not trigger editing the ingress in-place",
Issuer: acmeClusterIssuer,
Expand Down

0 comments on commit 5213a53

Please sign in to comment.