2020-09-15 02:13:40 +00:00
|
|
|
package cloudcas
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/x509"
|
|
|
|
"encoding/asn1"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
gax "github.com/googleapis/gax-go/v2"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/smallstep/certificates/cas/apiv1"
|
|
|
|
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
errTest = errors.New("test error")
|
|
|
|
testAuthorityName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca"
|
|
|
|
testCertificateName = "projects/test-project/locations/us-west1/certificateAuthorities/test-ca/certificates/test-certificate"
|
|
|
|
testRootCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIBhjCCAS2gAwIBAgIQLbKTuXau4+t3KFbGpJJAADAKBggqhkjOPQQDAjAiMSAw
|
|
|
|
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
|
|
|
Fw0zMDA5MTIyMjQ4NDlaMCIxIDAeBgNVBAMTF0dvb2dsZSBDQVMgVGVzdCBSb290
|
|
|
|
IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYKGgQ3/0D7+oBTc0CXoYfSC6
|
|
|
|
M8hOqLsmzBapPZSYpfwjgEsjdNU84jdrYmW1zF1+p+MrL4c7qJv9NLo/picCuqNF
|
|
|
|
MEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
|
|
|
|
FFVn9V7Qymd7cUJh9KAhnUDAQL5YMAoGCCqGSM49BAMCA0cAMEQCIA4LzttYoT3u
|
|
|
|
8TYgSrvFT+Z+cklfi4UrPBU6aSbcUaW2AiAPfaqbyccQT3CxMVyHg+xZZjAirZp8
|
|
|
|
lAeA/T4FxAonHA==
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testIntermediateCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIBsDCCAVagAwIBAgIQOb91kHxWKVzSJ9ESW1ViVzAKBggqhkjOPQQDAjAiMSAw
|
|
|
|
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
|
|
|
Fw0zMDA5MTIyMjQ4NDlaMCoxKDAmBgNVBAMTH0dvb2dsZSBDQVMgVGVzdCBJbnRl
|
|
|
|
cm1lZGlhdGUgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASUHN1cNyId4Ei/
|
|
|
|
4MxD5VrZFc51P50caMUdDZVrPveidChBYCU/9IM6vnRlZHx2HLjQ0qAvqHwY3rT0
|
|
|
|
xc7n+PfCo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAd
|
|
|
|
BgNVHQ4EFgQUSDlasiw0pRKyS7llhL0ZuVFNa9UwHwYDVR0jBBgwFoAUVWf1XtDK
|
|
|
|
Z3txQmH0oCGdQMBAvlgwCgYIKoZIzj0EAwIDSAAwRQIgMmsLcoC4KriXw+s+cZx2
|
|
|
|
bJMf6Mx/WESj31buJJhpzY0CIQCBUa/JtvS3nyce/4DF5tK2v49/NWHREgqAaZ57
|
|
|
|
DcYyHQ==
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testLeafCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIB1jCCAX2gAwIBAgIQQfOn+COMeuD8VYF1TiDkEzAKBggqhkjOPQQDAjAqMSgw
|
|
|
|
JgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDkx
|
|
|
|
NDIyNTE1NVoXDTMwMDkxMjIyNTE1MlowHTEbMBkGA1UEAxMSdGVzdC5zbWFsbHN0
|
|
|
|
ZXAuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAdUSRBrpgHFilN4eaGlN
|
|
|
|
nX2+xfjXa1Iwk2/+AensjFTXJi1UAIB0e+4pqi7Sen5E2QVBhntEHCrA3xOf7czg
|
|
|
|
P6OBkTCBjjAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
|
|
|
|
AQUFBwMCMB0GA1UdDgQWBBSYPbu4Tmm7Zze/hCePeZH1Avoj+jAfBgNVHSMEGDAW
|
|
|
|
gBRIOVqyLDSlErJLuWWEvRm5UU1r1TAdBgNVHREEFjAUghJ0ZXN0LnNtYWxsc3Rl
|
|
|
|
cC5jb20wCgYIKoZIzj0EAwIDRwAwRAIgY+nTc+RHn31/BOhht4JpxCmJPHxqFT3S
|
|
|
|
ojnictBudV0CIB87ipY5HV3c8FLVEzTA0wFwdDZvQraQYsthwbg2kQFb
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testSignedCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIB/DCCAaKgAwIBAgIQHHFuGMz0cClfde5kqP5prTAKBggqhkjOPQQDAjAqMSgw
|
|
|
|
JgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDkx
|
|
|
|
NTAwMDQ0M1oXDTMwMDkxMzAwMDQ0MFowHTEbMBkGA1UEAxMSdGVzdC5zbWFsbHN0
|
|
|
|
ZXAuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMqNCiXMvbn74LsHzRv+8
|
|
|
|
17m9vEzH6RHrg3m82e0uEc36+fZWV/zJ9SKuONmnl5VP79LsjL5SVH0RDj73U2XO
|
|
|
|
DKOBtjCBszAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
|
|
|
|
AQUFBwMCMB0GA1UdDgQWBBRTA2cTs7PCNjnps/+T0dS8diqv0DAfBgNVHSMEGDAW
|
|
|
|
gBRIOVqyLDSlErJLuWWEvRm5UU1r1TBCBgwrBgEEAYKkZMYoQAIEMjAwEwhjbG91
|
|
|
|
ZGNhcxMkZDhkMThhNjgtNTI5Ni00YWYzLWFlNGItMmY4NzdkYTNmYmQ5MAoGCCqG
|
|
|
|
SM49BAMCA0gAMEUCIGxl+pqJ50WYWUqK2l4V1FHoXSi0Nht5kwTxFxnWZu1xAiEA
|
|
|
|
zemu3bhWLFaGg3s8i+HTEhw4RqkHP74vF7AVYp88bAw=
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
)
|
|
|
|
|
|
|
|
type testClient struct {
|
|
|
|
credentialsFile string
|
|
|
|
certificate *pb.Certificate
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func newTestClient(credentialsFile string) (CertificateAuthorityClient, error) {
|
|
|
|
if credentialsFile == "testdata/error.json" {
|
|
|
|
return nil, errTest
|
|
|
|
}
|
|
|
|
return &testClient{
|
|
|
|
credentialsFile: credentialsFile,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func okTestClient() *testClient {
|
|
|
|
return &testClient{
|
|
|
|
credentialsFile: "testdata/credentials.json",
|
|
|
|
certificate: &pb.Certificate{
|
|
|
|
Name: testCertificateName,
|
|
|
|
PemCertificate: testSignedCertificate,
|
|
|
|
PemCertificateChain: []string{testIntermediateCertificate, testRootCertificate},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func failTestClient() *testClient {
|
|
|
|
return &testClient{
|
|
|
|
credentialsFile: "testdata/credentials.json",
|
|
|
|
err: errTest,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func badTestClient() *testClient {
|
|
|
|
return &testClient{
|
|
|
|
credentialsFile: "testdata/credentials.json",
|
|
|
|
certificate: &pb.Certificate{
|
|
|
|
Name: testCertificateName,
|
|
|
|
PemCertificate: "not a pem cert",
|
|
|
|
PemCertificateChain: []string{testIntermediateCertificate, testRootCertificate},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func setTeeReader(t *testing.T, w *bytes.Buffer) {
|
|
|
|
t.Helper()
|
|
|
|
reader := rand.Reader
|
|
|
|
t.Cleanup(func() {
|
|
|
|
rand.Reader = reader
|
|
|
|
})
|
|
|
|
rand.Reader = io.TeeReader(reader, w)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *testClient) CreateCertificate(ctx context.Context, req *pb.CreateCertificateRequest, opts ...gax.CallOption) (*pb.Certificate, error) {
|
|
|
|
return c.certificate, c.err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *testClient) RevokeCertificate(ctx context.Context, req *pb.RevokeCertificateRequest, opts ...gax.CallOption) (*pb.Certificate, error) {
|
|
|
|
return c.certificate, c.err
|
|
|
|
}
|
|
|
|
|
|
|
|
func mustParseCertificate(t *testing.T, pemCert string) *x509.Certificate {
|
|
|
|
t.Helper()
|
|
|
|
crt, err := parseCertificate(pemCert)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return crt
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNew(t *testing.T) {
|
|
|
|
tmp := newCertificateAuthorityClient
|
|
|
|
newCertificateAuthorityClient = func(ctx context.Context, credentialsFile string) (CertificateAuthorityClient, error) {
|
|
|
|
return newTestClient(credentialsFile)
|
|
|
|
}
|
|
|
|
t.Cleanup(func() {
|
|
|
|
newCertificateAuthorityClient = tmp
|
|
|
|
})
|
|
|
|
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
opts apiv1.Options
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want *CloudCAS
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", args{context.Background(), apiv1.Options{
|
|
|
|
Certificateauthority: testAuthorityName,
|
|
|
|
}}, &CloudCAS{
|
|
|
|
client: &testClient{},
|
|
|
|
certificateAuthority: testAuthorityName,
|
|
|
|
}, false},
|
|
|
|
{"ok with credentials", args{context.Background(), apiv1.Options{
|
|
|
|
Certificateauthority: testAuthorityName, CredentialsFile: "testdata/credentials.json",
|
|
|
|
}}, &CloudCAS{
|
|
|
|
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
|
|
|
certificateAuthority: testAuthorityName,
|
|
|
|
}, false},
|
|
|
|
{"fail certificate authority", args{context.Background(), apiv1.Options{}}, nil, true},
|
|
|
|
{"fail with credentials", args{context.Background(), apiv1.Options{
|
|
|
|
Certificateauthority: testAuthorityName, CredentialsFile: "testdata/error.json",
|
|
|
|
}}, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got, err := New(tt.args.ctx, tt.args.opts)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("New() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-16 00:23:11 +00:00
|
|
|
func TestNew_register(t *testing.T) {
|
|
|
|
tmp := newCertificateAuthorityClient
|
|
|
|
newCertificateAuthorityClient = func(ctx context.Context, credentialsFile string) (CertificateAuthorityClient, error) {
|
|
|
|
return newTestClient(credentialsFile)
|
|
|
|
}
|
|
|
|
t.Cleanup(func() {
|
|
|
|
newCertificateAuthorityClient = tmp
|
|
|
|
})
|
|
|
|
|
|
|
|
want := &CloudCAS{
|
|
|
|
client: &testClient{credentialsFile: "testdata/credentials.json"},
|
|
|
|
certificateAuthority: testAuthorityName,
|
|
|
|
}
|
|
|
|
|
|
|
|
newFn, ok := apiv1.LoadCertificateAuthorityServiceNewFunc(apiv1.CloudCAS)
|
|
|
|
if !ok {
|
|
|
|
t.Error("apiv1.LoadCertificateAuthorityServiceNewFunc(apiv1.CloudCAS) was not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
got, err := newFn(context.Background(), apiv1.Options{
|
|
|
|
Certificateauthority: testAuthorityName, CredentialsFile: "testdata/credentials.json",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("New() error = %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("New() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-09-15 02:13:40 +00:00
|
|
|
func TestNew_real(t *testing.T) {
|
|
|
|
if v, ok := os.LookupEnv("GOOGLE_APPLICATION_CREDENTIALS"); ok {
|
|
|
|
os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS")
|
|
|
|
t.Cleanup(func() {
|
|
|
|
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", v)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
opts apiv1.Options
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"fail default credentials", args{context.Background(), apiv1.Options{Certificateauthority: testAuthorityName}}, true},
|
|
|
|
{"fail certificate authority", args{context.Background(), apiv1.Options{}}, true},
|
|
|
|
{"fail with credentials", args{context.Background(), apiv1.Options{
|
|
|
|
Certificateauthority: testAuthorityName, CredentialsFile: "testdata/missing.json",
|
|
|
|
}}, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
_, err := New(tt.args.ctx, tt.args.opts)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloudCAS_CreateCertificate(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
client CertificateAuthorityClient
|
|
|
|
certificateAuthority string
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
req *apiv1.CreateCertificateRequest
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
want *apiv1.CreateCertificateResponse
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", fields{okTestClient(), testCertificateName}, args{&apiv1.CreateCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, &apiv1.CreateCertificateResponse{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
CertificateChain: []*x509.Certificate{mustParseCertificate(t, testIntermediateCertificate)},
|
|
|
|
}, false},
|
|
|
|
{"fail Template", fields{okTestClient(), testCertificateName}, args{&apiv1.CreateCertificateRequest{
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Lifetime", fields{okTestClient(), testCertificateName}, args{&apiv1.CreateCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail CreateCertificate", fields{failTestClient(), testCertificateName}, args{&apiv1.CreateCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Certificate", fields{badTestClient(), testCertificateName}, args{&apiv1.CreateCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &CloudCAS{
|
|
|
|
client: tt.fields.client,
|
|
|
|
certificateAuthority: tt.fields.certificateAuthority,
|
|
|
|
}
|
|
|
|
got, err := c.CreateCertificate(tt.args.req)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CloudCAS.CreateCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("CloudCAS.CreateCertificate() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloudCAS_createCertificate(t *testing.T) {
|
|
|
|
leaf := mustParseCertificate(t, testLeafCertificate)
|
|
|
|
signed := mustParseCertificate(t, testSignedCertificate)
|
|
|
|
chain := []*x509.Certificate{mustParseCertificate(t, testIntermediateCertificate)}
|
|
|
|
|
|
|
|
type fields struct {
|
|
|
|
client CertificateAuthorityClient
|
|
|
|
certificateAuthority string
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
tpl *x509.Certificate
|
|
|
|
lifetime time.Duration
|
|
|
|
requestID string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
want *x509.Certificate
|
|
|
|
want1 []*x509.Certificate
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", fields{okTestClient(), testAuthorityName}, args{leaf, 24 * time.Hour, "request-id"}, signed, chain, false},
|
|
|
|
{"fail CertificateConfig", fields{okTestClient(), testAuthorityName}, args{&x509.Certificate{}, 24 * time.Hour, "request-id"}, nil, nil, true},
|
|
|
|
{"fail CreateCertificate", fields{failTestClient(), testAuthorityName}, args{leaf, 24 * time.Hour, "request-id"}, nil, nil, true},
|
|
|
|
{"fail ParseCertificates", fields{badTestClient(), testAuthorityName}, args{leaf, 24 * time.Hour, "request-id"}, nil, nil, true},
|
|
|
|
{"fail create id", fields{okTestClient(), testAuthorityName}, args{leaf, 24 * time.Hour, "request-id"}, nil, nil, true},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pre-calulate rand.Random
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
setTeeReader(t, buf)
|
|
|
|
for i := 0; i < len(tests)-1; i++ {
|
|
|
|
_, err := uuid.NewRandomFromReader(rand.Reader)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rand.Reader = buf
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &CloudCAS{
|
|
|
|
client: tt.fields.client,
|
|
|
|
certificateAuthority: tt.fields.certificateAuthority,
|
|
|
|
}
|
|
|
|
got, got1, err := c.createCertificate(tt.args.tpl, tt.args.lifetime, tt.args.requestID)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CloudCAS.createCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("CloudCAS.createCertificate() got = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got1, tt.want1) {
|
|
|
|
t.Errorf("CloudCAS.createCertificate() got1 = %v, want %v", got1, tt.want1)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloudCAS_RenewCertificate(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
client CertificateAuthorityClient
|
|
|
|
certificateAuthority string
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
req *apiv1.RenewCertificateRequest
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
want *apiv1.RenewCertificateResponse
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", fields{okTestClient(), testCertificateName}, args{&apiv1.RenewCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, &apiv1.RenewCertificateResponse{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
CertificateChain: []*x509.Certificate{mustParseCertificate(t, testIntermediateCertificate)},
|
|
|
|
}, false},
|
|
|
|
{"fail Template", fields{okTestClient(), testCertificateName}, args{&apiv1.RenewCertificateRequest{
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Lifetime", fields{okTestClient(), testCertificateName}, args{&apiv1.RenewCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail CreateCertificate", fields{failTestClient(), testCertificateName}, args{&apiv1.RenewCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Certificate", fields{badTestClient(), testCertificateName}, args{&apiv1.RenewCertificateRequest{
|
|
|
|
Template: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
Lifetime: 24 * time.Hour,
|
|
|
|
}}, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &CloudCAS{
|
|
|
|
client: tt.fields.client,
|
|
|
|
certificateAuthority: tt.fields.certificateAuthority,
|
|
|
|
}
|
|
|
|
got, err := c.RenewCertificate(tt.args.req)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CloudCAS.RenewCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("CloudCAS.RenewCertificate() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloudCAS_RevokeCertificate(t *testing.T) {
|
|
|
|
badExtensionCert := mustParseCertificate(t, testSignedCertificate)
|
|
|
|
for i, ext := range badExtensionCert.Extensions {
|
|
|
|
if ext.Id.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64, 2}) {
|
|
|
|
badExtensionCert.Extensions[i].Value = []byte("bad-data")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type fields struct {
|
|
|
|
client CertificateAuthorityClient
|
|
|
|
certificateAuthority string
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
req *apiv1.RevokeCertificateRequest
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
want *apiv1.RevokeCertificateResponse
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 1,
|
|
|
|
}}, &apiv1.RevokeCertificateResponse{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
CertificateChain: []*x509.Certificate{mustParseCertificate(t, testIntermediateCertificate)},
|
|
|
|
}, false},
|
|
|
|
{"fail Extension", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testLeafCertificate),
|
|
|
|
ReasonCode: 1,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Extension Value", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: badExtensionCert,
|
|
|
|
ReasonCode: 1,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail Certificate", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
ReasonCode: 2,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail ReasonCode", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 100,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail ReasonCode 7", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 7,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail ReasonCode 8", fields{okTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 8,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail RevokeCertificate", fields{failTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 1,
|
|
|
|
}}, nil, true},
|
|
|
|
{"fail ParseCertificate", fields{badTestClient(), testCertificateName}, args{&apiv1.RevokeCertificateRequest{
|
|
|
|
Certificate: mustParseCertificate(t, testSignedCertificate),
|
|
|
|
ReasonCode: 1,
|
|
|
|
}}, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &CloudCAS{
|
|
|
|
client: tt.fields.client,
|
|
|
|
certificateAuthority: tt.fields.certificateAuthority,
|
|
|
|
}
|
|
|
|
got, err := c.RevokeCertificate(tt.args.req)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CloudCAS.RevokeCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("CloudCAS.RevokeCertificate() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_createCertificateID(t *testing.T) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
setTeeReader(t, buf)
|
|
|
|
uuid, err := uuid.NewRandomFromReader(rand.Reader)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
rand.Reader = buf
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
want string
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", uuid.String(), false},
|
|
|
|
{"fail", "", true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got, err := createCertificateID()
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("createCertificateID() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if got != tt.want {
|
|
|
|
t.Errorf("createCertificateID() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_parseCertificate(t *testing.T) {
|
|
|
|
type args struct {
|
|
|
|
pemCert string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want *x509.Certificate
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", args{testLeafCertificate}, mustParseCertificate(t, testLeafCertificate), false},
|
|
|
|
{"ok intermediate", args{testIntermediateCertificate}, mustParseCertificate(t, testIntermediateCertificate), false},
|
|
|
|
{"fail pem", args{"not pem"}, nil, true},
|
|
|
|
{"fail parseCertificate", args{"-----BEGIN CERTIFICATE-----\nZm9vYmFyCg==\n-----END CERTIFICATE-----\n"}, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got, err := parseCertificate(tt.args.pemCert)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("parseCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("parseCertificate() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_getCertificateAndChain(t *testing.T) {
|
|
|
|
type args struct {
|
|
|
|
certpb *pb.Certificate
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want *x509.Certificate
|
|
|
|
want1 []*x509.Certificate
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"ok", args{&pb.Certificate{
|
|
|
|
Name: testCertificateName,
|
|
|
|
PemCertificate: testSignedCertificate,
|
|
|
|
PemCertificateChain: []string{testIntermediateCertificate, testRootCertificate},
|
|
|
|
}}, mustParseCertificate(t, testSignedCertificate), []*x509.Certificate{mustParseCertificate(t, testIntermediateCertificate)}, false},
|
|
|
|
{"fail PemCertificate", args{&pb.Certificate{
|
|
|
|
Name: testCertificateName,
|
|
|
|
PemCertificate: "foobar",
|
|
|
|
PemCertificateChain: []string{testIntermediateCertificate, testRootCertificate},
|
|
|
|
}}, nil, nil, true},
|
|
|
|
{"fail PemCertificateChain", args{&pb.Certificate{
|
|
|
|
Name: testCertificateName,
|
|
|
|
PemCertificate: testSignedCertificate,
|
|
|
|
PemCertificateChain: []string{"foobar", testRootCertificate},
|
|
|
|
}}, nil, nil, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got, got1, err := getCertificateAndChain(tt.args.certpb)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("getCertificateAndChain() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("getCertificateAndChain() got = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got1, tt.want1) {
|
|
|
|
t.Errorf("getCertificateAndChain() got1 = %v, want %v", got1, tt.want1)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|