Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-0.16] Adds Issuer Group to Secret annotation #3153

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -205,6 +205,7 @@ func (s *SecretsManager) setValues(crt *cmapi.Certificate, secret *corev1.Secret
secret.Annotations[cmapi.CertificateNameKey] = crt.Name
secret.Annotations[cmapi.IssuerNameAnnotationKey] = crt.Spec.IssuerRef.Name
secret.Annotations[cmapi.IssuerKindAnnotationKey] = apiutil.IssuerKind(crt.Spec.IssuerRef)
secret.Annotations[cmapi.IssuerGroupAnnotationKey] = crt.Spec.IssuerRef.Group

// If deprecated annotations exist with any value, then they too shall be
// updated
Expand Down
30 changes: 17 additions & 13 deletions pkg/controller/certificates/internal/secretsmanager/secret_test.go
Expand Up @@ -54,7 +54,7 @@ func TestSecretsManager(t *testing.T) {
}

baseCert := gen.Certificate("test",
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "ca-issuer", Kind: "Issuer", Group: "not-empty"}),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "ca-issuer", Kind: "Issuer", Group: "foo.io"}),
gen.SetCertificateSecretName("output"),
gen.SetCertificateRenewBefore(time.Hour*36),
gen.SetCertificateDNSNames("example.com"),
Expand Down Expand Up @@ -91,9 +91,10 @@ func TestSecretsManager(t *testing.T) {
Namespace: gen.DefaultTestNamespace,
Name: "output",
Annotations: map[string]string{
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",

cmapi.CommonNameAnnotationKey: exampleBundle.Cert.Subject.CommonName,
cmapi.AltNamesAnnotationKey: strings.Join(exampleBundle.Cert.DNSNames, ","),
Expand Down Expand Up @@ -150,9 +151,10 @@ func TestSecretsManager(t *testing.T) {
Annotations: map[string]string{
"my-custom": "annotation",

cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",

cmapi.CommonNameAnnotationKey: exampleBundle.Cert.Subject.CommonName,
cmapi.AltNamesAnnotationKey: strings.Join(exampleBundle.Cert.DNSNames, ","),
Expand Down Expand Up @@ -191,9 +193,10 @@ func TestSecretsManager(t *testing.T) {
Namespace: gen.DefaultTestNamespace,
Name: "output",
Annotations: map[string]string{
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",

cmapi.CommonNameAnnotationKey: exampleBundle.Cert.Subject.CommonName,
cmapi.AltNamesAnnotationKey: strings.Join(exampleBundle.Cert.DNSNames, ","),
Expand Down Expand Up @@ -249,9 +252,10 @@ func TestSecretsManager(t *testing.T) {
Annotations: map[string]string{
"my-custom": "annotation",

cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",

cmapi.CommonNameAnnotationKey: exampleBundle.Cert.Subject.CommonName,
cmapi.AltNamesAnnotationKey: strings.Join(exampleBundle.Cert.DNSNames, ","),
Expand Down
98 changes: 52 additions & 46 deletions pkg/controller/certificates/issuing/issuing_controller_test.go
Expand Up @@ -59,7 +59,7 @@ func TestIssuingController(t *testing.T) {
nextPrivateKeySecretName := "next-private-key"

baseCert := gen.Certificate("test",
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "ca-issuer", Kind: "Issuer", Group: "not-empty"}),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "ca-issuer", Kind: "Issuer", Group: "foo.io"}),
gen.SetCertificateSecretName("output"),
gen.SetCertificateRenewBefore(time.Hour*36),
gen.SetCertificateDNSNames("example.com"),
Expand Down Expand Up @@ -380,13 +380,14 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down Expand Up @@ -452,14 +453,15 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down Expand Up @@ -511,13 +513,14 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down Expand Up @@ -580,14 +583,15 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down Expand Up @@ -697,14 +701,15 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
"my-custom": "annotation",
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down Expand Up @@ -811,13 +816,14 @@ func TestIssuingController(t *testing.T) {
Namespace: exampleBundle.Certificate.Namespace,
Name: "output",
Annotations: map[string]string{
cmapi.CertificateNameKey: "test",
cmapi.IssuerKindAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Kind,
cmapi.IssuerNameAnnotationKey: exampleBundle.Certificate.Spec.IssuerRef.Name,
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
cmapi.CertificateNameKey: "test",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerNameAnnotationKey: "ca-issuer",
cmapi.CommonNameAnnotationKey: "",
cmapi.AltNamesAnnotationKey: "example.com",
cmapi.IPSANAnnotationKey: "",
cmapi.URISANAnnotationKey: "",
},
},
Data: map[string][]byte{
Expand Down
7 changes: 6 additions & 1 deletion pkg/util/pki/csr.go
Expand Up @@ -227,12 +227,16 @@ func GenerateTemplate(crt *v1alpha2.Certificate) (*x509.Certificate, error) {
ipAddresses := IPAddressesForCertificate(crt)
organization := OrganizationForCertificate(crt)
subject := SubjectForCertificate(crt)
uris, err := URLsFromStrings(crt.Spec.URISANs)
if err != nil {
return nil, err
}
keyUsages, extKeyUsages, err := BuildKeyUsages(crt.Spec.Usages, crt.Spec.IsCA)
if err != nil {
return nil, err
}

if len(commonName) == 0 && len(dnsNames) == 0 && len(ipAddresses) == 0 && len(crt.Spec.URISANs) == 0 && len(crt.Spec.EmailSANs) == 0 {
if len(commonName) == 0 && len(dnsNames) == 0 && len(ipAddresses) == 0 && len(uris) == 0 && len(crt.Spec.EmailSANs) == 0 {
return nil, fmt.Errorf("no common name or subject alt names requested on certificate")
}

Expand Down Expand Up @@ -272,6 +276,7 @@ func GenerateTemplate(crt *v1alpha2.Certificate) (*x509.Certificate, error) {
ExtKeyUsage: extKeyUsages,
DNSNames: dnsNames,
IPAddresses: ipAddresses,
URIs: uris,
EmailAddresses: crt.Spec.EmailSANs,
}, nil
}
Expand Down
73 changes: 56 additions & 17 deletions test/integration/certificates/issuing_controller_test.go
Expand Up @@ -106,11 +106,14 @@ func TestIssuingController(t *testing.T) {
// Create Certificate
crt := gen.Certificate(crtName,
gen.SetCertificateNamespace(namespace),
gen.SetCertificateDNSNames("example.com"),
gen.SetCertificateCommonName("my-common-name"),
gen.SetCertificateDNSNames("example.com", "foo.example.com"),
gen.SetCertificateIPs("1.2.3.4", "5.6.7.8"),
gen.SetCertificateURIs("spiffe://hello.world"),
gen.SetCertificateKeyAlgorithm(cmapi.RSAKeyAlgorithm),
gen.SetCertificateKeySize(2048),
gen.SetCertificateSecretName(secretName),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "testissuer"}),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "testissuer", Group: "foo.io", Kind: "Issuer"}),
)

crt, err = cmCl.CertmanagerV1alpha2().Certificates(namespace).Create(ctx, crt, metav1.CreateOptions{})
Expand Down Expand Up @@ -196,23 +199,40 @@ func TestIssuingController(t *testing.T) {
return false, nil
}

// If the condition is set, but the rest of the values are not there,
// error. This is to assert that all Secret data and metadata is pushed in
// a single resource update.

if crt.Status.Revision == nil ||
*crt.Status.Revision != 2 {
t.Logf("Certificate does not have a revision of 2: %v", crt.Status.Revision)
return false, nil
return false, fmt.Errorf("Certificate does not have a revision of 2: %v", crt.Status.Revision)
}

secret, err := kubeClient.CoreV1().Secrets(namespace).Get(ctx, crt.Spec.SecretName, metav1.GetOptions{})
if err != nil {
t.Logf("Failed to fetch Secret %s/%s: %s", namespace, crt.Spec.SecretName, err)
return false, nil
return false, fmt.Errorf("Failed to fetch Secret %s/%s: %s", namespace, crt.Spec.SecretName, err)
}

if !bytes.Equal(secret.Data[corev1.TLSPrivateKeyKey], skBytes) ||
!bytes.Equal(secret.Data[corev1.TLSCertKey], certPem) ||
!bytes.Equal(secret.Data[cmmeta.TLSCAKey], certPem) {
t.Logf("Contents of secret did not match expected: %+v", secret.Data)
return false, nil
return false, fmt.Errorf("Contents of secret did not match expected: %+v", secret.Data)
}

for expKey, expV := range map[string]string{
cmapi.AltNamesAnnotationKey: "example.com,foo.example.com",
cmapi.IPSANAnnotationKey: "1.2.3.4,5.6.7.8",
cmapi.URISANAnnotationKey: "spiffe://hello.world",
cmapi.CommonNameAnnotationKey: "my-common-name",
cmapi.IssuerNameAnnotationKey: "testissuer",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.CertificateNameKey: "testcrt",
} {
if v, ok := secret.Annotations[expKey]; !ok || expV != v {
return false, fmt.Errorf("expected Secret to have the annotation %s:%s, got %s:%s",
expKey, expV, expKey, v)
}
}

return true, nil
Expand Down Expand Up @@ -289,12 +309,15 @@ func TestIssuingController_PKCS8_PrivateKey(t *testing.T) {
// Create Certificate
crt := gen.Certificate(crtName,
gen.SetCertificateNamespace(namespace),
gen.SetCertificateDNSNames("example.com"),
gen.SetCertificateCommonName("my-common-name"),
gen.SetCertificateDNSNames("example.com", "foo.example.com"),
gen.SetCertificateIPs("1.2.3.4", "5.6.7.8"),
gen.SetCertificateURIs("spiffe://hello.world"),
gen.SetCertificateKeyAlgorithm(cmapi.RSAKeyAlgorithm),
gen.SetCertificateKeyEncoding(cmapi.PKCS8),
gen.SetCertificateKeySize(2048),
gen.SetCertificateSecretName(secretName),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "testissuer"}),
gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "testissuer", Group: "foo.io", Kind: "Issuer"}),
)

crt, err = cmCl.CertmanagerV1alpha2().Certificates(namespace).Create(ctx, crt, metav1.CreateOptions{})
Expand Down Expand Up @@ -380,28 +403,44 @@ func TestIssuingController_PKCS8_PrivateKey(t *testing.T) {
return false, nil
}

// If the condition is set, but the rest of the values are not there,
// error. This is to assert that all Secret data and metadata is pushed in
// a single resource update.

if crt.Status.Revision == nil ||
*crt.Status.Revision != 2 {
t.Logf("Certificate does not have a revision of 2: %v", crt.Status.Revision)
return false, nil
return false, fmt.Errorf("Certificate does not have a revision of 2: %v", crt.Status.Revision)
}

secret, err := kubeClient.CoreV1().Secrets(namespace).Get(ctx, crt.Spec.SecretName, metav1.GetOptions{})
if err != nil {
t.Logf("Failed to fetch Secret %s/%s: %s", namespace, crt.Spec.SecretName, err)
return false, nil
return false, fmt.Errorf("Failed to fetch Secret %s/%s: %s", namespace, crt.Spec.SecretName, err)
}

if !bytes.Equal(secret.Data[corev1.TLSPrivateKeyKey], skBytesPKCS8) ||
!bytes.Equal(secret.Data[corev1.TLSCertKey], certPem) ||
!bytes.Equal(secret.Data[cmmeta.TLSCAKey], certPem) {
t.Logf("Contents of secret did not match expected: %+v", secret.Data)
return false, nil
return false, fmt.Errorf("Contents of secret did not match expected: %+v", secret.Data)
}

for expKey, expV := range map[string]string{
cmapi.AltNamesAnnotationKey: "example.com,foo.example.com",
cmapi.IPSANAnnotationKey: "1.2.3.4,5.6.7.8",
cmapi.URISANAnnotationKey: "spiffe://hello.world",
cmapi.CommonNameAnnotationKey: "my-common-name",
cmapi.IssuerNameAnnotationKey: "testissuer",
cmapi.IssuerKindAnnotationKey: "Issuer",
cmapi.IssuerGroupAnnotationKey: "foo.io",
cmapi.CertificateNameKey: "testcrt",
} {
if v, ok := secret.Annotations[expKey]; !ok || expV != v {
return false, fmt.Errorf("expected Secret to have the annotation %s:%s, got %s:%s",
expKey, expV, expKey, v)
}
}

return true, nil
})

if err != nil {
t.Fatalf("Failed to wait for final state: %+v", crt)
}
Expand Down