mirror of
https://github.com/wahyd4/cert-manager.git
synced 2026-08-09 05:06:38 +10:00
Merge pull request #4108 from JoshVanL/certificate-signing-request=venafi
CertificateSigningRequest Venafi controller
This commit is contained in:
@@ -27,6 +27,7 @@ go_library(
|
||||
"//pkg/controller/certificatesigningrequests/ca:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests/selfsigned:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests/vault:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests/venafi:go_default_library",
|
||||
"//pkg/controller/clusterissuers:go_default_library",
|
||||
"//pkg/controller/issuers:go_default_library",
|
||||
"//pkg/feature:go_default_library",
|
||||
|
||||
@@ -46,6 +46,7 @@ import (
|
||||
csrcacontroller "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/ca"
|
||||
csrselfsignedcontroller "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/selfsigned"
|
||||
csrvaultcontroller "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/vault"
|
||||
csrvenaficontroller "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/venafi"
|
||||
clusterissuerscontroller "github.com/jetstack/cert-manager/pkg/controller/clusterissuers"
|
||||
issuerscontroller "github.com/jetstack/cert-manager/pkg/controller/issuers"
|
||||
"github.com/jetstack/cert-manager/pkg/feature"
|
||||
@@ -195,6 +196,7 @@ var (
|
||||
experimentalCertificateSigningRequestControllers = []string{
|
||||
csrcacontroller.CSRControllerName,
|
||||
csrselfsignedcontroller.CSRControllerName,
|
||||
csrvenaficontroller.CSRControllerName,
|
||||
csrvaultcontroller.CSRControllerName,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -26,7 +26,10 @@ const (
|
||||
// CertificateSigningRequestIsCAAnnotationKey is the annotation key used to
|
||||
// request whether the certificate should be marked as CA.
|
||||
CertificateSigningRequestIsCAAnnotationKey = "experimental.cert-manager.io/request-is-ca"
|
||||
)
|
||||
|
||||
// SelfSigned Issuer specific Annotations
|
||||
const (
|
||||
// CertificateSigningRequestPrivateKeyAnnotationKey is the annotation key
|
||||
// used to reference a Secret resource containing the private key used to
|
||||
// sign the request.
|
||||
@@ -34,3 +37,18 @@ const (
|
||||
// issuer type to self-sign certificates.
|
||||
CertificateSigningRequestPrivateKeyAnnotationKey = "experimental.cert-manager.io/private-key-secret-name"
|
||||
)
|
||||
|
||||
// Venafi Issuer specific Annotations
|
||||
const (
|
||||
// CertificateSigningRequestVenafiCustomFieldsAnnotationKey is the annotation
|
||||
// that passes on JSON encoded custom fields to the Venafi issuer.
|
||||
// This will only work with Venafi TPP v19.3 and higher.
|
||||
// The value is an array with objects containing the name and value keys for
|
||||
// example: `[{"name": "custom-field", "value": "custom-value"}]`
|
||||
CertificateSigningRequestVenafiCustomFieldsAnnotationKey = "venafi.experimental.cert-manager.io/custom-fields"
|
||||
|
||||
// CertificateSigningRequestVenafiPickupIDAnnotationKey is the annotation key
|
||||
// used to record the Venafi Pickup ID of a certificate signing request that
|
||||
// has been submitted to the Venafi API for collection later.
|
||||
CertificateSigningRequestVenafiPickupIDAnnotationKey = "venafi.experimental.cert-manager.io/pickup-id"
|
||||
)
|
||||
|
||||
@@ -74,6 +74,7 @@ filegroup(
|
||||
"//pkg/controller/certificatesigningrequests/selfsigned:all-srcs",
|
||||
"//pkg/controller/certificatesigningrequests/util:all-srcs",
|
||||
"//pkg/controller/certificatesigningrequests/vault:all-srcs",
|
||||
"//pkg/controller/certificatesigningrequests/venafi:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
@@ -38,6 +38,11 @@ func (c *Controller) Sync(ctx context.Context, csr *certificatesv1.CertificateSi
|
||||
log := logf.WithResource(logf.FromContext(ctx), csr).WithValues("signerName", csr.Spec.SignerName)
|
||||
dbg := log.V(logf.DebugLevel)
|
||||
|
||||
// Deep copy CertificateSigningRequest to prevent writing to the shared local
|
||||
// cache making it invalid. Done early in the sync to avoid accidental
|
||||
// invalidation by future contributions.
|
||||
csr = csr.DeepCopy()
|
||||
|
||||
ref, ok := util.SignerIssuerRefFromSignerName(csr.Spec.SignerName)
|
||||
if !ok {
|
||||
dbg.Info("certificate signing request has malformed signer name,", "signerName", csr.Spec.SignerName)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["venafi.go"],
|
||||
importpath = "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/venafi",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/apis/certmanager/v1:go_default_library",
|
||||
"//pkg/apis/experimental/v1alpha1:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests/util:go_default_library",
|
||||
"//pkg/issuer/venafi/client:go_default_library",
|
||||
"//pkg/issuer/venafi/client/api:go_default_library",
|
||||
"//pkg/logs:go_default_library",
|
||||
"//pkg/util/pki:go_default_library",
|
||||
"@com_github_venafi_vcert_v4//pkg/endpoint:go_default_library",
|
||||
"@io_k8s_api//certificates/v1:go_default_library",
|
||||
"@io_k8s_api//core/v1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/api/errors:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
"@io_k8s_client_go//kubernetes/typed/certificates/v1:go_default_library",
|
||||
"@io_k8s_client_go//listers/core/v1:go_default_library",
|
||||
"@io_k8s_client_go//tools/record:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["venafi_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/apis/certmanager:go_default_library",
|
||||
"//pkg/apis/certmanager/v1:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests:go_default_library",
|
||||
"//pkg/controller/certificatesigningrequests/util:go_default_library",
|
||||
"//pkg/controller/test:go_default_library",
|
||||
"//pkg/issuer/venafi/client:go_default_library",
|
||||
"//pkg/issuer/venafi/client/api:go_default_library",
|
||||
"//pkg/issuer/venafi/client/fake:go_default_library",
|
||||
"//pkg/util/pki:go_default_library",
|
||||
"//test/unit/gen:go_default_library",
|
||||
"@com_github_venafi_vcert_v4//pkg/endpoint:go_default_library",
|
||||
"@io_k8s_api//authorization/v1:go_default_library",
|
||||
"@io_k8s_api//certificates/v1:go_default_library",
|
||||
"@io_k8s_api//core/v1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/api/errors:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/runtime/schema:go_default_library",
|
||||
"@io_k8s_client_go//listers/core/v1:go_default_library",
|
||||
"@io_k8s_client_go//testing:go_default_library",
|
||||
"@io_k8s_utils//clock/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
Copyright 2020 The cert-manager Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Venafi/vcert/v4/pkg/endpoint"
|
||||
certificatesv1 "k8s.io/api/certificates/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1"
|
||||
corelisters "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/record"
|
||||
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
|
||||
experimentalapi "github.com/jetstack/cert-manager/pkg/apis/experimental/v1alpha1"
|
||||
controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests"
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/util"
|
||||
venaficlient "github.com/jetstack/cert-manager/pkg/issuer/venafi/client"
|
||||
venafiapi "github.com/jetstack/cert-manager/pkg/issuer/venafi/client/api"
|
||||
logf "github.com/jetstack/cert-manager/pkg/logs"
|
||||
"github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
utilpki "github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
)
|
||||
|
||||
const (
|
||||
CSRControllerName = "certificatesigningrequests-issuer-venafi"
|
||||
)
|
||||
|
||||
// Venafi is a Kubernetes CertificateSigningRequest controller, responsible for
|
||||
// signing CertificateSigningRequests that reference a cert-manager Venafi
|
||||
// Issuer or ClusterIssuer
|
||||
type Venafi struct {
|
||||
issuerOptions controllerpkg.IssuerOptions
|
||||
secretsLister corelisters.SecretLister
|
||||
certClient certificatesclient.CertificateSigningRequestInterface
|
||||
recorder record.EventRecorder
|
||||
|
||||
clientBuilder venaficlient.VenafiClientBuilder
|
||||
}
|
||||
|
||||
func init() {
|
||||
controllerpkg.Register(CSRControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) {
|
||||
return controllerpkg.NewBuilder(ctx, CSRControllerName).
|
||||
For(certificatesigningrequests.New(apiutil.IssuerVenafi, NewVenafi(ctx))).
|
||||
Complete()
|
||||
})
|
||||
}
|
||||
|
||||
func NewVenafi(ctx *controllerpkg.Context) *Venafi {
|
||||
return &Venafi{
|
||||
issuerOptions: ctx.IssuerOptions,
|
||||
secretsLister: ctx.KubeSharedInformerFactory.Core().V1().Secrets().Lister(),
|
||||
certClient: ctx.Client.CertificatesV1().CertificateSigningRequests(),
|
||||
recorder: ctx.Recorder,
|
||||
clientBuilder: venaficlient.New,
|
||||
}
|
||||
}
|
||||
|
||||
// Sign attempts to sign the given CertificateSigningRequest based on the
|
||||
// provided Venafi Issuer or ClusterIssuer. This function will update the resource
|
||||
// if signing was successful. Returns an error which, if not nil, should
|
||||
// trigger a retry.
|
||||
// Since this signer takes some time to sign the request, this controller will
|
||||
// set a "pick ID" annotation value that is used to fetch the latest state of
|
||||
// the request in subsequent re-syncs. The re-syncs are triggered by using the
|
||||
// workqueue's back-off mechanism.
|
||||
func (v *Venafi) Sign(ctx context.Context, csr *certificatesv1.CertificateSigningRequest, issuerObj cmapi.GenericIssuer) error {
|
||||
log := logf.FromContext(ctx, "sign")
|
||||
log = logf.WithRelatedResource(log, issuerObj)
|
||||
|
||||
resourceNamespace := v.issuerOptions.ResourceNamespace(issuerObj)
|
||||
|
||||
client, err := v.clientBuilder(resourceNamespace, v.secretsLister, issuerObj)
|
||||
if apierrors.IsNotFound(err) {
|
||||
message := "Required secret resource not found"
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "SecretNotFound", message)
|
||||
log.Error(err, message)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("Failed to initialise venafi client for signing: %s", err)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorVenafiInit", message)
|
||||
log.Error(err, message)
|
||||
return err
|
||||
}
|
||||
|
||||
var customFields []venafiapi.CustomField
|
||||
if annotation, exists := csr.GetAnnotations()[experimentalapi.CertificateSigningRequestVenafiCustomFieldsAnnotationKey]; exists && annotation != "" {
|
||||
err := json.Unmarshal([]byte(annotation), &customFields)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("Failed to parse %q annotation: %s", experimentalapi.CertificateSigningRequestVenafiCustomFieldsAnnotationKey, err)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorCustomFields", message)
|
||||
util.CertificateSigningRequestSetFailed(csr, "ErrorCustomFields", message)
|
||||
_, userr := v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
return userr
|
||||
}
|
||||
}
|
||||
|
||||
duration, err := pki.DurationFromCertificateSigningRequest(csr)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("Failed to parse requested duration: %s", err)
|
||||
log.Error(err, message)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorParseDuration", message)
|
||||
util.CertificateSigningRequestSetFailed(csr, "ErrorParseDuration", message)
|
||||
_, userr := v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
return userr
|
||||
}
|
||||
|
||||
// The signing process with Venafi is slow. The "pickupID" allows us to track
|
||||
// the progress of the certificate signing. It is set as an annotation the
|
||||
// first time the Certificate is reconciled.
|
||||
pickupID := csr.GetAnnotations()[experimentalapi.CertificateSigningRequestVenafiPickupIDAnnotationKey]
|
||||
|
||||
// check if the pickup ID annotation is there, if not set it up.
|
||||
if len(pickupID) == 0 {
|
||||
pickupID, err := client.RequestCertificate(csr.Spec.Request, duration, customFields)
|
||||
// Check some known error types
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
|
||||
case venaficlient.ErrCustomFieldsType:
|
||||
log.Error(err, "")
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorCustomFields", err.Error())
|
||||
util.CertificateSigningRequestSetFailed(csr, "ErrorCustomFields", err.Error())
|
||||
_, userr := v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
return userr
|
||||
|
||||
default:
|
||||
message := fmt.Sprintf("Failed to request venafi certificate: %s", err)
|
||||
log.Error(err, message)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorRequest", message)
|
||||
util.CertificateSigningRequestSetFailed(csr, "ErrorRequest", message)
|
||||
_, userr := v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
return userr
|
||||
}
|
||||
}
|
||||
|
||||
if csr.Annotations == nil {
|
||||
csr.Annotations = make(map[string]string)
|
||||
}
|
||||
csr.Annotations[experimentalapi.CertificateSigningRequestVenafiPickupIDAnnotationKey] = pickupID
|
||||
_, uerr := v.certClient.Update(ctx, csr, metav1.UpdateOptions{})
|
||||
return uerr
|
||||
}
|
||||
|
||||
certPem, err := client.RetrieveCertificate(pickupID, csr.Spec.Request, duration, customFields)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case endpoint.ErrCertificatePending:
|
||||
message := "Venafi certificate still in a pending state, waiting"
|
||||
log.V(2).Info(message, "error", err.Error())
|
||||
v.recorder.Event(csr, corev1.EventTypeNormal, "IssuancePending", message)
|
||||
return err
|
||||
|
||||
case endpoint.ErrRetrieveCertificateTimeout:
|
||||
message := "Venafi retrieve certificate timeout, retrying"
|
||||
log.Error(err, message)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "RetrieveCertificateTimeout", message)
|
||||
return err
|
||||
|
||||
default:
|
||||
message := fmt.Sprintf("Failed to obtain venafi certificate: %s", err)
|
||||
log.Error(err, message)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorRetrieve", message)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
bundle, err := utilpki.ParseSingleCertificateChainPEM(certPem)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("Failed to parse returned certificate bundle: %s", err)
|
||||
log.Error(err, message)
|
||||
v.recorder.Event(csr, corev1.EventTypeWarning, "ErrorParse", message)
|
||||
util.CertificateSigningRequestSetFailed(csr, "ErrorParse", message)
|
||||
_, userr := v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
return userr
|
||||
}
|
||||
|
||||
csr.Status.Certificate = bundle.ChainPEM
|
||||
csr, err = v.certClient.UpdateStatus(ctx, csr, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
message := "Error updating certificate"
|
||||
v.recorder.Eventf(csr, corev1.EventTypeWarning, "SigningError", "%s: %s", message, err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.V(logf.DebugLevel).Info("certificate issued")
|
||||
v.recorder.Event(csr, corev1.EventTypeNormal, "CertificateIssued", "Certificate fetched from venafi issuer successfully")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,905 @@
|
||||
/*
|
||||
Copyright 2021 The cert-manager Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Venafi/vcert/v4/pkg/endpoint"
|
||||
authzv1 "k8s.io/api/authorization/v1"
|
||||
certificatesv1 "k8s.io/api/certificates/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
corelisters "k8s.io/client-go/listers/core/v1"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
fakeclock "k8s.io/utils/clock/testing"
|
||||
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
"github.com/jetstack/cert-manager/pkg/apis/certmanager"
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests"
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/util"
|
||||
testpkg "github.com/jetstack/cert-manager/pkg/controller/test"
|
||||
venaficlient "github.com/jetstack/cert-manager/pkg/issuer/venafi/client"
|
||||
venafiapi "github.com/jetstack/cert-manager/pkg/issuer/venafi/client/api"
|
||||
fakevenaficlient "github.com/jetstack/cert-manager/pkg/issuer/venafi/client/fake"
|
||||
"github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
"github.com/jetstack/cert-manager/test/unit/gen"
|
||||
)
|
||||
|
||||
var (
|
||||
fixedClockStart = time.Now()
|
||||
fixedClock = fakeclock.NewFakeClock(fixedClockStart)
|
||||
)
|
||||
|
||||
func TestProcessItem(t *testing.T) {
|
||||
metaFixedClockStart := metav1.NewTime(fixedClockStart)
|
||||
util.Clock = fixedClock
|
||||
|
||||
rootCSRPEM, rootPK, err := gen.CSR(x509.RSA,
|
||||
gen.SetCSRCommonName("root"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rootTmpl, err := pki.GenerateTemplateFromCSRPEM(rootCSRPEM, time.Hour, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, rootCert, err := pki.SignCertificate(rootTmpl, rootTmpl, rootPK.Public(), rootPK)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
leafCSRPEM, leafPK, err := gen.CSR(x509.RSA,
|
||||
gen.SetCSRCommonName("leaf"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
leafTmpl, err := pki.GenerateTemplateFromCSRPEM(leafCSRPEM, time.Hour, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, leafCert, err := pki.SignCertificate(leafTmpl, rootCert, leafPK.Public(), rootPK)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
certBundle, err := pki.ParseSingleCertificateChain([]*x509.Certificate{leafCert, rootCert})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
baseIssuer := gen.Issuer("test-issuer",
|
||||
gen.SetIssuerVenafi(cmapi.VenafiIssuer{
|
||||
Cloud: &cmapi.VenafiCloud{},
|
||||
}),
|
||||
gen.AddIssuerCondition(cmapi.IssuerCondition{
|
||||
Type: cmapi.IssuerConditionReady,
|
||||
Status: cmmeta.ConditionTrue,
|
||||
}),
|
||||
)
|
||||
|
||||
baseCSR := gen.CertificateSigningRequest("test-cr",
|
||||
gen.SetCertificateSigningRequestRequest(leafCSRPEM),
|
||||
gen.SetCertificateSigningRequestSignerName("issuers.cert-manager.io/default-unit-test-ns.test-issuer"),
|
||||
gen.SetCertificateSigningRequestDuration("1440h"),
|
||||
gen.SetCertificateSigningRequestUsername("user-1"),
|
||||
gen.SetCertificateSigningRequestGroups([]string{"group-1", "group-2"}),
|
||||
gen.SetCertificateSigningRequestUID("uid-1"),
|
||||
gen.SetCertificateSigningRequestExtra(map[string]certificatesv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
}),
|
||||
)
|
||||
|
||||
tests := map[string]struct {
|
||||
builder *testpkg.Builder
|
||||
csr *certificatesv1.CertificateSigningRequest
|
||||
clientBuilder venaficlient.VenafiClientBuilder
|
||||
expectedErr bool
|
||||
}{
|
||||
"a CertificateSigningRequest without an approved condition should do nothing": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR),
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
},
|
||||
},
|
||||
"a CertificateSigningRequest with a denied condition should do nothing": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateDenied,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{},
|
||||
ExpectedActions: nil,
|
||||
},
|
||||
},
|
||||
"an approved CSR where the venafi client builder returns a not found error should fire event and do nothing": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return nil, apierrors.NewNotFound(schema.GroupResource{}, "test-secret")
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning SecretNotFound Required secret resource not found",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR where the venafi client builder returns a generic error should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return nil, errors.New("generic error")
|
||||
},
|
||||
expectedErr: true,
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning ErrorVenafiInit Failed to initialise venafi client for signing: generic error",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR where the custom fields annotations contain garbage data should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": "garbage-data",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
`Warning ErrorCustomFields Failed to parse "venafi.experimental.cert-manager.io/custom-fields" annotation: invalid character 'g' looking for beginning of value`,
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": "garbage-data",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateFailed,
|
||||
Status: corev1.ConditionTrue,
|
||||
Reason: "ErrorCustomFields",
|
||||
Message: `Failed to parse "venafi.experimental.cert-manager.io/custom-fields" annotation: invalid character 'g' looking for beginning of value`,
|
||||
LastTransitionTime: metaFixedClockStart,
|
||||
LastUpdateTime: metaFixedClockStart,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR where the requested duration annotations contains garbage data should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestDuration("garbage-duration"),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
`Warning ErrorParseDuration Failed to parse requested duration: failed to parse requested duration on annotation "experimental.cert-manager.io/request-duration": time: invalid duration "garbage-duration"`,
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.SetCertificateSigningRequestDuration("garbage-duration"),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateFailed,
|
||||
Status: corev1.ConditionTrue,
|
||||
Reason: "ErrorParseDuration",
|
||||
Message: `Failed to parse requested duration: failed to parse requested duration on annotation "experimental.cert-manager.io/request-duration": time: invalid duration "garbage-duration"`,
|
||||
LastTransitionTime: metaFixedClockStart,
|
||||
LastUpdateTime: metaFixedClockStart,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which does not yet have a pickup ID, but the client responds with fields type error, should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RequestCertificateFn: func(_ []byte, _ time.Duration, _ []venafiapi.CustomField) (string, error) {
|
||||
return "", venaficlient.ErrCustomFieldsType{Type: "test-type"}
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
`Warning ErrorCustomFields certificate request contains an invalid Venafi custom fields type: "test-type"`,
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateFailed,
|
||||
Status: corev1.ConditionTrue,
|
||||
Reason: "ErrorCustomFields",
|
||||
Message: `certificate request contains an invalid Venafi custom fields type: "test-type"`,
|
||||
LastTransitionTime: metaFixedClockStart,
|
||||
LastUpdateTime: metaFixedClockStart,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which does not yet have a pickup ID, but the client responds a generic error, should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RequestCertificateFn: func(_ []byte, _ time.Duration, _ []venafiapi.CustomField) (string, error) {
|
||||
return "", errors.New("generic error")
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning ErrorRequest Failed to request venafi certificate: generic error",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateFailed,
|
||||
Status: corev1.ConditionTrue,
|
||||
Reason: "ErrorRequest",
|
||||
Message: "Failed to request venafi certificate: generic error",
|
||||
LastTransitionTime: metaFixedClockStart,
|
||||
LastUpdateTime: metaFixedClockStart,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which does not yet have a pickup ID, should update the annotation with one and return": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RequestCertificateFn: func(_ []byte, _ time.Duration, _ []venafiapi.CustomField) (string, error) {
|
||||
return "test-pickup-id", nil
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which has a pickup ID, retrieve certificate returns a pending error, fire event and return error": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RetrieveCertificateFn: func(_ string, _ []byte, _ time.Duration, _ []venafiapi.CustomField) ([]byte, error) {
|
||||
return nil, endpoint.ErrCertificatePending{}
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
expectedErr: true,
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Normal IssuancePending Venafi certificate still in a pending state, waiting",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which has a pickup ID, retrieve certificate returns a timeout error, fire event and return error": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RetrieveCertificateFn: func(_ string, _ []byte, _ time.Duration, _ []venafiapi.CustomField) ([]byte, error) {
|
||||
return nil, endpoint.ErrRetrieveCertificateTimeout{}
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
expectedErr: true,
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning RetrieveCertificateTimeout Venafi retrieve certificate timeout, retrying",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which has a pickup ID, retrieve certificate returns a generic error, fire event and return error": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RetrieveCertificateFn: func(_ string, _ []byte, _ time.Duration, _ []venafiapi.CustomField) ([]byte, error) {
|
||||
return nil, errors.New("generic error")
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
expectedErr: true,
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning ErrorRetrieve Failed to obtain venafi certificate: generic error",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which has a pickup ID, retrieve certificate returns garbage certificates, should mark as Failed": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RetrieveCertificateFn: func(_ string, _ []byte, _ time.Duration, _ []venafiapi.CustomField) ([]byte, error) {
|
||||
return []byte("garbage"), nil
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Warning ErrorParse Failed to parse returned certificate bundle: error decoding certificate PEM block",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateFailed,
|
||||
Status: corev1.ConditionTrue,
|
||||
Reason: "ErrorParse",
|
||||
Message: "Failed to parse returned certificate bundle: error decoding certificate PEM block",
|
||||
LastTransitionTime: metaFixedClockStart,
|
||||
LastUpdateTime: metaFixedClockStart,
|
||||
}),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
"an approved CSR which has a pickup ID, retrieve certificate returns a CA and certificate should update with certificate": {
|
||||
csr: gen.CertificateSigningRequestFrom(baseCSR,
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
),
|
||||
clientBuilder: func(_ string, _ corelisters.SecretLister, _ cmapi.GenericIssuer) (venaficlient.Interface, error) {
|
||||
return &fakevenaficlient.Venafi{
|
||||
RetrieveCertificateFn: func(_ string, _ []byte, _ time.Duration, _ []venafiapi.CustomField) ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("%s%s", certBundle.ChainPEM, certBundle.CAPEM)), nil
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
builder: &testpkg.Builder{
|
||||
CertManagerObjects: []runtime.Object{baseIssuer.DeepCopy()},
|
||||
ExpectedEvents: []string{
|
||||
"Normal CertificateIssued Certificate fetched from venafi issuer successfully",
|
||||
},
|
||||
ExpectedActions: []testpkg.Action{
|
||||
testpkg.NewAction(coretesting.NewCreateAction(
|
||||
authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews"),
|
||||
"",
|
||||
&authzv1.SubjectAccessReview{
|
||||
Spec: authzv1.SubjectAccessReviewSpec{
|
||||
User: "user-1",
|
||||
Groups: []string{"group-1", "group-2"},
|
||||
Extra: map[string]authzv1.ExtraValue{
|
||||
"extra": []string{"1", "2"},
|
||||
},
|
||||
UID: "uid-1",
|
||||
|
||||
ResourceAttributes: &authzv1.ResourceAttributes{
|
||||
Group: certmanager.GroupName,
|
||||
Resource: "signers",
|
||||
Verb: "reference",
|
||||
Namespace: baseIssuer.Namespace,
|
||||
Name: baseIssuer.Name,
|
||||
Version: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
)),
|
||||
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
|
||||
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
|
||||
"status",
|
||||
"",
|
||||
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
|
||||
gen.AddCertificateSigningRequestAnnotations(map[string]string{
|
||||
"venafi.experimental.cert-manager.io/custom-fields": `[ {"name": "field-name", "value": "vield value"}]`,
|
||||
"venafi.experimental.cert-manager.io/pickup-id": "test-pickup-id",
|
||||
}),
|
||||
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Status: corev1.ConditionTrue,
|
||||
}),
|
||||
gen.SetCertificateSigningRequestCertificate(certBundle.ChainPEM),
|
||||
),
|
||||
)),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if test.csr != nil {
|
||||
test.builder.KubeObjects = append(test.builder.KubeObjects, test.csr)
|
||||
}
|
||||
|
||||
fixedClock.SetTime(fixedClockStart)
|
||||
test.builder.Clock = fixedClock
|
||||
test.builder.T = t
|
||||
test.builder.Init()
|
||||
|
||||
// Always return true for SubjectAccessReviews in tests
|
||||
test.builder.FakeKubeClient().PrependReactor("create", "*", func(action coretesting.Action) (bool, runtime.Object, error) {
|
||||
if action.GetResource() != authzv1.SchemeGroupVersion.WithResource("subjectaccessreviews") {
|
||||
return false, nil, nil
|
||||
}
|
||||
return true, &authzv1.SubjectAccessReview{
|
||||
Status: authzv1.SubjectAccessReviewStatus{
|
||||
Allowed: true,
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
|
||||
defer test.builder.Stop()
|
||||
|
||||
venafi := NewVenafi(test.builder.Context)
|
||||
venafi.clientBuilder = test.clientBuilder
|
||||
|
||||
controller := certificatesigningrequests.New(apiutil.IssuerVenafi, venafi)
|
||||
controller.Register(test.builder.Context)
|
||||
test.builder.Start()
|
||||
|
||||
err := controller.ProcessItem(context.Background(), test.csr.Name)
|
||||
if err != nil && !test.expectedErr {
|
||||
t.Errorf("expected to not get an error, but got: %v", err)
|
||||
}
|
||||
if err == nil && test.expectedErr {
|
||||
t.Errorf("expected to get an error but did not get one")
|
||||
}
|
||||
|
||||
test.builder.CheckAndFinish(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,8 @@ type connector interface {
|
||||
RenewCertificate(req *certificate.RenewalRequest) (requestID string, err error)
|
||||
}
|
||||
|
||||
// New constructs a Venafi client Interface. Errors may be network errors and
|
||||
// should be considered for retrying.
|
||||
func New(namespace string, secretsLister corelisters.SecretLister, issuer cmapi.GenericIssuer) (Interface, error) {
|
||||
cfg, err := configForIssuer(issuer, secretsLister, namespace)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,6 +28,7 @@ filegroup(
|
||||
"//test/e2e/framework/addon/base:all-srcs",
|
||||
"//test/e2e/framework/addon/chart:all-srcs",
|
||||
"//test/e2e/framework/addon/vault:all-srcs",
|
||||
"//test/e2e/framework/addon/venafi:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ go_library(
|
||||
"doc.go",
|
||||
"tpp.go",
|
||||
],
|
||||
importpath = "github.com/jetstack/cert-manager/test/e2e/suite/issuers/venafi/addon",
|
||||
importpath = "github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi",
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
+1
-1
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package addon
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -14,6 +14,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package addon implements an addon for the Venafi platform.
|
||||
// Package venafi implements an addon for the Venafi platform.
|
||||
// It provides a means for e2e tests to consume credentials for Venafi TPP.
|
||||
package addon
|
||||
package venafi
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package addon
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -49,7 +49,6 @@ func DefaultCertificateSigningRequestSet() []certificatesigningrequests.Validati
|
||||
certificatesigningrequests.ExpectCertificateURIsToMatch,
|
||||
certificatesigningrequests.ExpectCertificateIPsToMatch,
|
||||
certificatesigningrequests.ExpectValidCommonName,
|
||||
certificatesigningrequests.ExpectValidDuration,
|
||||
certificatesigningrequests.ExpectKeyUsageUsageDigitalSignature,
|
||||
certificatesigningrequests.ExpectEmailsToMatch,
|
||||
certificatesigningrequests.ExpectIsCA,
|
||||
@@ -92,5 +91,11 @@ func CertificateSetForUnsupportedFeatureSet(fs featureset.FeatureSet) []certific
|
||||
}
|
||||
|
||||
func CertificateSigningRequestSetForUnsupportedFeatureSet(fs featureset.FeatureSet) []certificatesigningrequests.ValidationFunc {
|
||||
return DefaultCertificateSigningRequestSet()
|
||||
validations := DefaultCertificateSigningRequestSet()
|
||||
|
||||
if !fs.Contains(featureset.DurationFeature) {
|
||||
validations = append(validations, certificatesigningrequests.ExpectValidDuration)
|
||||
}
|
||||
|
||||
return validations
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ go_library(
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/ca:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/selfsigned:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/vault:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/venafi:go_default_library",
|
||||
"//test/e2e/suite/conformance/rbac:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -9,10 +9,10 @@ go_library(
|
||||
"//pkg/apis/certmanager/v1:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//test/e2e/framework:go_default_library",
|
||||
"//test/e2e/framework/addon/venafi:go_default_library",
|
||||
"//test/e2e/framework/helper/featureset:go_default_library",
|
||||
"//test/e2e/framework/util/errors:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificates:go_default_library",
|
||||
"//test/e2e/suite/issuers/venafi/addon:go_default_library",
|
||||
"@com_github_onsi_ginkgo//:go_default_library",
|
||||
"@com_github_onsi_gomega//:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
|
||||
@@ -26,10 +26,10 @@ import (
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/helper/featureset"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/util/errors"
|
||||
"github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificates"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/suite/issuers/venafi/addon"
|
||||
)
|
||||
|
||||
var _ = framework.ConformanceDescribe("Certificates", func() {
|
||||
|
||||
@@ -9,10 +9,10 @@ go_library(
|
||||
"//pkg/apis/certmanager/v1:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//test/e2e/framework:go_default_library",
|
||||
"//test/e2e/framework/addon/venafi:go_default_library",
|
||||
"//test/e2e/framework/helper/featureset:go_default_library",
|
||||
"//test/e2e/framework/util/errors:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificates:go_default_library",
|
||||
"//test/e2e/suite/issuers/venafi/addon:go_default_library",
|
||||
"@com_github_onsi_ginkgo//:go_default_library",
|
||||
"@com_github_onsi_gomega//:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
|
||||
@@ -26,10 +26,10 @@ import (
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/helper/featureset"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/util/errors"
|
||||
"github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificates"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/suite/issuers/venafi/addon"
|
||||
)
|
||||
|
||||
var _ = framework.ConformanceDescribe("[Feature:Issuers:Venafi:Cloud] Certificates", func() {
|
||||
|
||||
@@ -40,6 +40,7 @@ filegroup(
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/ca:all-srcs",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/selfsigned:all-srcs",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/vault:all-srcs",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests/venafi:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
@@ -72,8 +72,11 @@ func (s *Suite) Define() {
|
||||
})
|
||||
|
||||
type testCase struct {
|
||||
keyAlgo x509.PublicKeyAlgorithm
|
||||
csrModifiers []gen.CSRModifier
|
||||
keyAlgo x509.PublicKeyAlgorithm
|
||||
// csrModifers define the shape of the X.509 CSR which is used in the
|
||||
// test case. We use a function to allow access to variables that are
|
||||
// initialized at test runtime by complete().
|
||||
csrModifiers func() []gen.CSRModifier
|
||||
kubeCSRUsages []certificatesv1.KeyUsage
|
||||
kubeCSRAnnotations map[string]string
|
||||
// The list of features that are required by the Issuer for the test to
|
||||
@@ -86,8 +89,10 @@ func (s *Suite) Define() {
|
||||
|
||||
tests := map[string]testCase{
|
||||
"should issue an RSA certificate for a single distinct DNS Name": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))},
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -96,8 +101,10 @@ func (s *Suite) Define() {
|
||||
},
|
||||
|
||||
"should issue an ECDSA certificate for a single distinct DNS Name": {
|
||||
keyAlgo: x509.ECDSA,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))},
|
||||
keyAlgo: x509.ECDSA,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -106,8 +113,10 @@ func (s *Suite) Define() {
|
||||
},
|
||||
|
||||
"should issue an Ed25519 certificate for a single distinct DNS Name": {
|
||||
keyAlgo: x509.Ed25519,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))},
|
||||
keyAlgo: x509.Ed25519,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -116,8 +125,10 @@ func (s *Suite) Define() {
|
||||
},
|
||||
|
||||
"should issue an RSA certificate for a single Common Name": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))},
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -126,8 +137,10 @@ func (s *Suite) Define() {
|
||||
},
|
||||
|
||||
"should issue an ECDSA certificate for a single Common Name": {
|
||||
keyAlgo: x509.ECDSA,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))},
|
||||
keyAlgo: x509.ECDSA,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -136,8 +149,10 @@ func (s *Suite) Define() {
|
||||
},
|
||||
|
||||
"should issue an Ed25519 certificate for a single Common Name": {
|
||||
keyAlgo: x509.Ed25519,
|
||||
csrModifiers: []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))},
|
||||
keyAlgo: x509.Ed25519,
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10))}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
certificatesv1.UsageKeyEncipherment,
|
||||
@@ -147,9 +162,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a Common Name and IP Address": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10)),
|
||||
gen.SetCSRIPAddresses(net.IPv4(127, 0, 0, 1), net.IPv4(8, 8, 8, 8)),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10)),
|
||||
gen.SetCSRIPAddresses(net.IPv4(127, 0, 0, 1), net.IPv4(8, 8, 8, 8)),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -160,8 +177,10 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines an Email Address": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSREmails([]string{"alice@example.com", "bob@cert-manager.io"}),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSREmails([]string{"alice@example.com", "bob@cert-manager.io"}),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -172,9 +191,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a Common Name and URI SAN": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10)),
|
||||
gen.SetCSRURIs(sharedURI),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("test-common-name-" + util.RandStringRunes(10)),
|
||||
gen.SetCSRURIs(sharedURI),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -185,9 +206,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a 2 distinct DNS Name with one copied to the Common Name": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName, e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName, e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -198,9 +221,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a distinct DNS Name and another distinct Common Name": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -211,9 +236,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a Common Name, DNS Name, and sets a duration": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -227,8 +254,10 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that defines a DNS Name and sets a duration": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames(e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -242,8 +271,10 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate which has a wildcard DNS Name defined": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames("*." + e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRDNSNames("*." + e2eutil.RandomSubdomain(s.DomainSuffix)),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -254,8 +285,10 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that includes only a URISANs name": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRURIs(sharedURI),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRURIs(sharedURI),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -266,9 +299,11 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a certificate that includes arbitrary key usages": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName(sharedCommonName),
|
||||
gen.SetCSRDNSNames(sharedCommonName),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageServerAuth,
|
||||
@@ -287,8 +322,10 @@ func (s *Suite) Define() {
|
||||
|
||||
"should issue a signing CA certificate that has a large duration": {
|
||||
keyAlgo: x509.RSA,
|
||||
csrModifiers: []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("cert-manager-ca"),
|
||||
csrModifiers: func() []gen.CSRModifier {
|
||||
return []gen.CSRModifier{
|
||||
gen.SetCSRCommonName("cert-manager-ca"),
|
||||
}
|
||||
},
|
||||
kubeCSRUsages: []certificatesv1.KeyUsage{
|
||||
certificatesv1.UsageDigitalSignature,
|
||||
@@ -306,7 +343,7 @@ func (s *Suite) Define() {
|
||||
defineTest := func(name string, test testCase) {
|
||||
s.it(f, name, func(signerName string) {
|
||||
// Generate request CSR
|
||||
csr, key, err := gen.CSR(test.keyAlgo, test.csrModifiers...)
|
||||
csr, key, err := gen.CSR(test.keyAlgo, test.csrModifiers()...)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Create CertificateSigningRequest
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cloud.go",
|
||||
"tpp.go",
|
||||
],
|
||||
importpath = "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/venafi",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/controller/certificatesigningrequests/util:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//test/e2e/framework:go_default_library",
|
||||
"//test/e2e/framework/addon/venafi:go_default_library",
|
||||
"//test/e2e/framework/helper/featureset:go_default_library",
|
||||
"//test/e2e/framework/util/errors:go_default_library",
|
||||
"//test/e2e/suite/conformance/certificatesigningrequests:go_default_library",
|
||||
"@com_github_onsi_ginkgo//:go_default_library",
|
||||
"@com_github_onsi_gomega//:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2021 The cert-manager Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/util"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/helper/featureset"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/util/errors"
|
||||
"github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests"
|
||||
)
|
||||
|
||||
var _ = framework.ConformanceDescribe("CertificateSigningRequests", func() {
|
||||
// unsupportedFeatures is a list of features that are not supported by the
|
||||
// Venafi TPP issuer.
|
||||
var unsupportedFeatures = featureset.NewFeatureSet(
|
||||
// Venafi TPP doesn't allow setting a duration
|
||||
featureset.DurationFeature,
|
||||
// Due to the current configuration of the test environment, it does not
|
||||
// support signing certificates that pair with an elliptic curve or
|
||||
// Ed255119 private keys
|
||||
featureset.ECDSAFeature,
|
||||
featureset.Ed25519FeatureSet,
|
||||
// Our Venafi TPP doesn't allow setting non DNS SANs
|
||||
// TODO: investigate options to enable these
|
||||
featureset.EmailSANsFeature,
|
||||
featureset.URISANsFeature,
|
||||
featureset.IPAddressFeature,
|
||||
// Venafi doesn't allow certs with empty CN & DN
|
||||
featureset.OnlySAN,
|
||||
// Venafi doesn't setting key usages.
|
||||
featureset.KeyUsagesFeature,
|
||||
)
|
||||
|
||||
venafiIssuer := new(cloud)
|
||||
(&certificatesigningrequests.Suite{
|
||||
Name: "Venafi Cloud Issuer",
|
||||
CreateIssuerFunc: venafiIssuer.createIssuer,
|
||||
DeleteIssuerFunc: venafiIssuer.delete,
|
||||
UnsupportedFeatures: unsupportedFeatures,
|
||||
}).Define()
|
||||
|
||||
venafiClusterIssuer := new(cloud)
|
||||
(&certificatesigningrequests.Suite{
|
||||
Name: "Venafi Cloud Cluster Issuer",
|
||||
CreateIssuerFunc: venafiClusterIssuer.createClusterIssuer,
|
||||
DeleteIssuerFunc: venafiClusterIssuer.delete,
|
||||
UnsupportedFeatures: unsupportedFeatures,
|
||||
}).Define()
|
||||
})
|
||||
|
||||
type cloud struct {
|
||||
*venafi.VenafiCloud
|
||||
}
|
||||
|
||||
func (c *cloud) delete(f *framework.Framework, signerName string) {
|
||||
Expect(c.Deprovision()).NotTo(HaveOccurred(), "failed to deprovision cloud venafi")
|
||||
|
||||
ref, _ := util.SignerIssuerRefFromSignerName(signerName)
|
||||
if ref.Type == "clusterissuers" {
|
||||
err := f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Delete(context.TODO(), ref.Name, metav1.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cloud) createIssuer(f *framework.Framework) string {
|
||||
By("Creating a Venafi Cloud Issuer")
|
||||
|
||||
c.VenafiCloud = &venafi.VenafiCloud{
|
||||
Namespace: f.Namespace.Name,
|
||||
}
|
||||
|
||||
err := c.Setup(f.Config)
|
||||
if errors.IsSkip(err) {
|
||||
framework.Skipf("Skipping test as addon could not be setup: %v", err)
|
||||
}
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to provision venafi cloud issuer")
|
||||
|
||||
Expect(c.Provision()).NotTo(HaveOccurred(), "failed to provision tpp venafi")
|
||||
|
||||
issuer := c.Details().BuildIssuer()
|
||||
issuer, err = f.CertManagerClientSet.CertmanagerV1().Issuers(f.Namespace.Name).Create(context.TODO(), issuer, metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to create issuer for venafi")
|
||||
|
||||
return fmt.Sprintf("issuers.cert-manager.io/%s.%s", issuer.Namespace, issuer.Name)
|
||||
}
|
||||
|
||||
// createClusterIssuer creates and returns name of a Venafi Cloud
|
||||
// ClusterIssuer. The name is of the form
|
||||
// "clusterissuers.cert-manager.io/issuer-ab3de1".
|
||||
func (c *cloud) createClusterIssuer(f *framework.Framework) string {
|
||||
By("Creating a Venafi Cloud ClusterIssuer")
|
||||
|
||||
c.VenafiCloud = &venafi.VenafiCloud{
|
||||
Namespace: f.Config.Addons.CertManager.ClusterResourceNamespace,
|
||||
}
|
||||
|
||||
err := c.Setup(f.Config)
|
||||
if errors.IsSkip(err) {
|
||||
framework.Skipf("Skipping test as addon could not be setup: %v", err)
|
||||
}
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to setup tpp venafi")
|
||||
|
||||
Expect(c.Provision()).NotTo(HaveOccurred(), "failed to provision tpp venafi")
|
||||
|
||||
issuer := c.Details().BuildClusterIssuer()
|
||||
issuer, err = f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Create(context.TODO(), issuer, metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to create issuer for venafi")
|
||||
|
||||
return fmt.Sprintf("clusterissuers.cert-manager.io/%s", issuer.Name)
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2021 The cert-manager Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package venafi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/util"
|
||||
cmutil "github.com/jetstack/cert-manager/pkg/util"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/helper/featureset"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework/util/errors"
|
||||
"github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests"
|
||||
)
|
||||
|
||||
var _ = framework.ConformanceDescribe("CertificateSigningRequests", func() {
|
||||
// unsupportedFeatures is a list of features that are not supported by the
|
||||
// Venafi TPP issuer.
|
||||
var unsupportedFeatures = featureset.NewFeatureSet(
|
||||
// Venafi TPP doesn't allow setting a duration
|
||||
featureset.DurationFeature,
|
||||
// Due to the current configuration of the test environment, it does not
|
||||
// support signing certificates that pair with an elliptic curve or
|
||||
// Ed255119 private keys
|
||||
featureset.ECDSAFeature,
|
||||
featureset.Ed25519FeatureSet,
|
||||
// Our Venafi TPP doesn't allow setting non DNS SANs
|
||||
// TODO: investigate options to enable these
|
||||
featureset.EmailSANsFeature,
|
||||
featureset.URISANsFeature,
|
||||
featureset.IPAddressFeature,
|
||||
// Venafi doesn't allow certs with empty CN & DN
|
||||
featureset.OnlySAN,
|
||||
// Venafi doesn't setting key usages.
|
||||
featureset.KeyUsagesFeature,
|
||||
)
|
||||
|
||||
venafiIssuer := new(tpp)
|
||||
(&certificatesigningrequests.Suite{
|
||||
Name: "Venafi TPP Issuer",
|
||||
CreateIssuerFunc: venafiIssuer.createIssuer,
|
||||
DeleteIssuerFunc: venafiIssuer.delete,
|
||||
UnsupportedFeatures: unsupportedFeatures,
|
||||
DomainSuffix: fmt.Sprintf("%s-venafi-e2e", cmutil.RandStringRunes(5)),
|
||||
}).Define()
|
||||
|
||||
venafiClusterIssuer := new(tpp)
|
||||
(&certificatesigningrequests.Suite{
|
||||
Name: "Venafi TPP Cluster Issuer",
|
||||
CreateIssuerFunc: venafiClusterIssuer.createClusterIssuer,
|
||||
DeleteIssuerFunc: venafiClusterIssuer.delete,
|
||||
UnsupportedFeatures: unsupportedFeatures,
|
||||
DomainSuffix: fmt.Sprintf("%s-venafi-e2e", cmutil.RandStringRunes(5)),
|
||||
}).Define()
|
||||
})
|
||||
|
||||
type tpp struct {
|
||||
*venafi.VenafiTPP
|
||||
}
|
||||
|
||||
func (t *tpp) delete(f *framework.Framework, signerName string) {
|
||||
Expect(t.Deprovision()).NotTo(HaveOccurred(), "failed to deprovision tpp venafi")
|
||||
ref, _ := util.SignerIssuerRefFromSignerName(signerName)
|
||||
|
||||
if ref.Type == "clusterissuers" {
|
||||
err := f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Delete(context.TODO(), ref.Name, metav1.DeleteOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tpp) createIssuer(f *framework.Framework) string {
|
||||
By("Creating a Venafi Issuer")
|
||||
|
||||
t.VenafiTPP = &venafi.VenafiTPP{
|
||||
Namespace: f.Namespace.Name,
|
||||
}
|
||||
|
||||
err := t.Setup(f.Config)
|
||||
if errors.IsSkip(err) {
|
||||
framework.Skipf("Skipping test as addon could not be setup: %v", err)
|
||||
}
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to setup tpp venafi")
|
||||
|
||||
Expect(t.Provision()).NotTo(HaveOccurred(), "failed to provision tpp venafi")
|
||||
|
||||
issuer := t.Details().BuildIssuer()
|
||||
issuer, err = f.CertManagerClientSet.CertmanagerV1().Issuers(f.Namespace.Name).Create(context.TODO(), issuer, metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to create issuer for venafi")
|
||||
|
||||
return fmt.Sprintf("issuers.cert-manager.io/%s.%s", issuer.Namespace, issuer.Name)
|
||||
}
|
||||
|
||||
func (t *tpp) createClusterIssuer(f *framework.Framework) string {
|
||||
By("Creating a Venafi ClusterIssuer")
|
||||
|
||||
t.VenafiTPP = &venafi.VenafiTPP{
|
||||
Namespace: f.Config.Addons.CertManager.ClusterResourceNamespace,
|
||||
}
|
||||
|
||||
err := t.Setup(f.Config)
|
||||
if errors.IsSkip(err) {
|
||||
framework.Skipf("Skipping test as addon could not be setup: %v", err)
|
||||
}
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to setup tpp venafi")
|
||||
|
||||
Expect(t.Provision()).NotTo(HaveOccurred(), "failed to provision tpp venafi")
|
||||
|
||||
issuer := t.Details().BuildClusterIssuer()
|
||||
issuer, err = f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Create(context.TODO(), issuer, metav1.CreateOptions{})
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to create issuer for venafi")
|
||||
|
||||
return fmt.Sprintf("clusterissuers.cert-manager.io/%s", issuer.Name)
|
||||
}
|
||||
@@ -27,5 +27,6 @@ import (
|
||||
_ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/ca"
|
||||
_ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/selfsigned"
|
||||
_ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/vault"
|
||||
_ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/venafi"
|
||||
_ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/rbac"
|
||||
)
|
||||
|
||||
@@ -19,7 +19,6 @@ filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//test/e2e/suite/issuers/venafi/addon:all-srcs",
|
||||
"//test/e2e/suite/issuers/venafi/tpp:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
||||
@@ -15,7 +15,7 @@ go_library(
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//test/e2e/framework:go_default_library",
|
||||
"//test/e2e/suite/issuers/venafi/addon:go_default_library",
|
||||
"//test/e2e/framework/addon/venafi:go_default_library",
|
||||
"//test/e2e/util:go_default_library",
|
||||
"@com_github_onsi_ginkgo//:go_default_library",
|
||||
"@com_github_onsi_gomega//:go_default_library",
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
cmutil "github.com/jetstack/cert-manager/pkg/util"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/suite/issuers/venafi/addon"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/util"
|
||||
)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
cmutil "github.com/jetstack/cert-manager/pkg/util"
|
||||
"github.com/jetstack/cert-manager/test/e2e/framework"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/suite/issuers/venafi/addon"
|
||||
vaddon "github.com/jetstack/cert-manager/test/e2e/framework/addon/venafi"
|
||||
"github.com/jetstack/cert-manager/test/e2e/util"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user