Beginning porting and building new venafi tests
Signed-off-by: JoshVanL <vleeuwenjoshua@gmail.com>
This commit is contained in:
parent
d96c7d2e1c
commit
28f2d071ec
75
pkg/internal/venafi/connector_test.go
Normal file
75
pkg/internal/venafi/connector_test.go
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2018 The Jetstack cert-manager contributors.
|
||||
|
||||
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 (
|
||||
"github.com/Venafi/vcert/pkg/certificate"
|
||||
"github.com/Venafi/vcert/pkg/endpoint"
|
||||
"github.com/Venafi/vcert/pkg/venafi/fake"
|
||||
)
|
||||
|
||||
type fakeConnector struct {
|
||||
*fake.Connector
|
||||
|
||||
PingFunc func() error
|
||||
ReadZoneConfigurationFunc func() (*endpoint.ZoneConfiguration, error)
|
||||
RetrieveCertificateFunc func(*certificate.Request) (*certificate.PEMCollection, error)
|
||||
RequestCertificateFunc func(*certificate.Request) (string, error)
|
||||
RenewCertificateFunc func(*certificate.RenewalRequest) (string, error)
|
||||
}
|
||||
|
||||
func (f fakeConnector) Default() *fakeConnector {
|
||||
if f.Connector == nil {
|
||||
f.Connector = fake.NewConnector(true, nil)
|
||||
}
|
||||
return &f
|
||||
}
|
||||
|
||||
func (f *fakeConnector) Ping() (err error) {
|
||||
if f.PingFunc != nil {
|
||||
return f.PingFunc()
|
||||
}
|
||||
return f.Connector.Ping()
|
||||
}
|
||||
|
||||
func (f *fakeConnector) ReadZoneConfiguration() (config *endpoint.ZoneConfiguration, err error) {
|
||||
if f.ReadZoneConfigurationFunc != nil {
|
||||
return f.ReadZoneConfigurationFunc()
|
||||
}
|
||||
return f.Connector.ReadZoneConfiguration()
|
||||
}
|
||||
|
||||
func (f *fakeConnector) RetrieveCertificate(req *certificate.Request) (certificates *certificate.PEMCollection, err error) {
|
||||
if f.RetrieveCertificateFunc != nil {
|
||||
return f.RetrieveCertificateFunc(req)
|
||||
}
|
||||
return f.Connector.RetrieveCertificate(req)
|
||||
}
|
||||
|
||||
func (f *fakeConnector) RequestCertificate(req *certificate.Request) (requestID string, err error) {
|
||||
if f.RequestCertificateFunc != nil {
|
||||
return f.RequestCertificateFunc(req)
|
||||
}
|
||||
return f.Connector.RequestCertificate(req)
|
||||
}
|
||||
|
||||
func (f *fakeConnector) RenewCertificate(req *certificate.RenewalRequest) (requestID string, err error) {
|
||||
if f.RenewCertificateFunc != nil {
|
||||
return f.RenewCertificateFunc(req)
|
||||
}
|
||||
return f.Connector.RenewCertificate(req)
|
||||
}
|
||||
156
pkg/internal/venafi/sign_test.go
Normal file
156
pkg/internal/venafi/sign_test.go
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2018 The Jetstack cert-manager contributors.
|
||||
|
||||
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 (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"testing"
|
||||
|
||||
"github.com/Venafi/vcert/pkg/venafi/fake"
|
||||
|
||||
//"github.com/jetstack/cert-manager/pkg/issuer"
|
||||
"github.com/jetstack/cert-manager/pkg/util"
|
||||
"github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
//"github.com/jetstack/cert-manager/test/unit/gen"
|
||||
)
|
||||
|
||||
func checkCertificateIssued(t *testing.T, csrPEM []byte, resp []byte, err error) {
|
||||
if len(resp) == 0 {
|
||||
t.Errorf("expected IssueResponse to be non-nil")
|
||||
t.FailNow()
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("expected no error to be returned, but got: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
csr, err := pki.DecodeX509CertificateRequestBytes(csrPEM)
|
||||
if err != nil {
|
||||
t.Errorf("failed to decode CSR PEM: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
crt, err := pki.DecodeX509CertificateBytes(resp)
|
||||
if err != nil {
|
||||
t.Errorf("unable to decode x509 certificate: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
ok, err := pki.PublicKeyMatchesCSR(crt.PublicKey, csr)
|
||||
if err != nil {
|
||||
t.Errorf("error checking private key: %v", err)
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
t.Errorf("private key does not match certificate")
|
||||
}
|
||||
|
||||
// validate the common name is correct
|
||||
expectedCN := csr.Subject.CommonName
|
||||
if expectedCN != crt.Subject.CommonName {
|
||||
t.Errorf("expected common name to be %q but it was %q", expectedCN, crt.Subject.CommonName)
|
||||
}
|
||||
|
||||
// validate the dns names are correct
|
||||
expectedDNSNames := csr.DNSNames
|
||||
if !util.EqualUnsorted(crt.DNSNames, expectedDNSNames) {
|
||||
t.Errorf("expected dns names to be %q but it was %q", expectedDNSNames, crt.DNSNames)
|
||||
}
|
||||
}
|
||||
|
||||
func generateCSR(t *testing.T, sk crypto.Signer, commonName string, dnsNames []string) []byte {
|
||||
asn1Subj, _ := asn1.Marshal(pkix.Name{
|
||||
CommonName: commonName,
|
||||
}.ToRDNSequence())
|
||||
template := x509.CertificateRequest{
|
||||
RawSubject: asn1Subj,
|
||||
SignatureAlgorithm: x509.SHA256WithRSA,
|
||||
DNSNames: dnsNames,
|
||||
}
|
||||
|
||||
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, sk)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
csr := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes})
|
||||
return csr
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
sk, err := pki.GenerateRSAPrivateKey(2048)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
csrPEM := generateCSR(t, sk, "common-name", []string{
|
||||
"foo.example.com", "bar.example.com"})
|
||||
|
||||
tests := map[string]testT{
|
||||
"obtain a certificate with a single dnsname specified": {
|
||||
csrPEM: csrPEM,
|
||||
CheckFn: checkCertificateIssued,
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
runTest(t, test)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testT struct {
|
||||
csrPEM []byte
|
||||
client connector
|
||||
|
||||
expectedErr bool
|
||||
|
||||
CheckFn func(*testing.T, []byte, []byte, error)
|
||||
}
|
||||
|
||||
func runTest(t *testing.T, test testT) {
|
||||
if test.client == nil {
|
||||
test.client = fake.NewConnector(true, nil)
|
||||
}
|
||||
|
||||
v := &Venafi{
|
||||
client: test.client,
|
||||
}
|
||||
|
||||
resp, err := v.Sign(test.csrPEM)
|
||||
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")
|
||||
}
|
||||
|
||||
if test.CheckFn != nil {
|
||||
test.CheckFn(t, test.csrPEM, resp, err)
|
||||
}
|
||||
}
|
||||
@ -25,10 +25,7 @@ import (
|
||||
"github.com/Venafi/vcert/pkg/endpoint"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
//"k8s.io/klog"
|
||||
|
||||
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
|
||||
"github.com/jetstack/cert-manager/pkg/internal/venafi"
|
||||
"github.com/jetstack/cert-manager/pkg/issuer"
|
||||
logf "github.com/jetstack/cert-manager/pkg/logs"
|
||||
"github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
@ -71,30 +68,33 @@ func (v *Venafi) Issue(ctx context.Context, crt *v1alpha1.Certificate) (*issuer.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
dbg.Info("generated new private key")
|
||||
v.Recorder.Event(crt, corev1.EventTypeNormal, "GenerateKey", "Generated new private key")
|
||||
|
||||
pk, err := pki.EncodePKCS8PrivateKey(signeeKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbg.Info("generated new private key")
|
||||
v.Recorder.Event(crt, corev1.EventTypeNormal, "GenerateKey", "Generated new private key")
|
||||
|
||||
// We build a x509.Certificate as the vcert library has support for converting
|
||||
// this into its own internal Certificate Request type.
|
||||
dbg.Info("constructing certificate request template to submit to venafi")
|
||||
csr, err := pki.GenerateCSR(crt)
|
||||
if err != nil {
|
||||
v.Recorder.Eventf(crt, corev1.EventTypeWarning, "GenerateCSR", "Failed to generate a CSR for the certificate: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
csrPEM, err := pki.EncodeCSR(csr, signeeKey)
|
||||
if err != nil {
|
||||
v.Recorder.Eventf(crt, corev1.EventTypeWarning, "EncodeCSR", "Failed to PEM encode CSR for the certificate: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := venafi.New(v.resourceNamespace, v.secretsLister, v.issuer)
|
||||
client, err := v.clientBuilder(v.resourceNamespace, v.secretsLister, v.issuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
v.Recorder.Eventf(v.issuer, corev1.EventTypeWarning, "FailedInit", "Failed to create Venafi client: %v", err)
|
||||
return nil, fmt.Errorf("error creating Venafi client: %s", err.Error())
|
||||
}
|
||||
|
||||
cert, err := client.Sign(csrPEM)
|
||||
|
||||
@ -25,12 +25,11 @@ import (
|
||||
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
|
||||
"github.com/jetstack/cert-manager/pkg/internal/venafi"
|
||||
)
|
||||
|
||||
func (v *Venafi) Setup(ctx context.Context) error {
|
||||
|
||||
client, err := venafi.New(v.resourceNamespace, v.secretsLister, v.issuer)
|
||||
client, err := v.clientBuilder(v.resourceNamespace, v.secretsLister, v.issuer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import (
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
|
||||
"github.com/jetstack/cert-manager/pkg/controller"
|
||||
"github.com/jetstack/cert-manager/pkg/internal/venafi"
|
||||
"github.com/jetstack/cert-manager/pkg/issuer"
|
||||
)
|
||||
|
||||
@ -43,6 +44,8 @@ type Venafi struct {
|
||||
// For Issuers, this will be the namespace of the Issuer.
|
||||
// For ClusterIssuers, this will be the cluster resource namespace.
|
||||
resourceNamespace string
|
||||
|
||||
clientBuilder venafi.VenafiClientBuilder
|
||||
}
|
||||
|
||||
func NewVenafi(ctx *controller.Context, issuer cmapi.GenericIssuer) (issuer.Interface, error) {
|
||||
@ -50,6 +53,7 @@ func NewVenafi(ctx *controller.Context, issuer cmapi.GenericIssuer) (issuer.Inte
|
||||
issuer: issuer,
|
||||
secretsLister: ctx.KubeSharedInformerFactory.Core().V1().Secrets().Lister(),
|
||||
resourceNamespace: ctx.IssuerOptions.ResourceNamespace(issuer),
|
||||
clientBuilder: venafi.New,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user