2020-09-15 02:13:40 +00:00
package cloudcas
import (
"bytes"
"context"
2020-10-28 00:59:32 +00:00
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
2020-09-15 02:13:40 +00:00
"crypto/rand"
"crypto/x509"
"encoding/asn1"
2020-10-28 00:59:32 +00:00
"encoding/pem"
"fmt"
2020-09-15 02:13:40 +00:00
"io"
2020-11-03 19:26:24 +00:00
"log"
2020-10-27 02:52:08 +00:00
"net"
2020-09-15 02:13:40 +00:00
"os"
"reflect"
"testing"
"time"
2020-10-27 02:52:08 +00:00
lroauto "cloud.google.com/go/longrunning/autogen"
privateca "cloud.google.com/go/security/privateca/apiv1beta1"
gomock "github.com/golang/mock/gomock"
2020-09-15 02:13:40 +00:00
"github.com/google/uuid"
gax "github.com/googleapis/gax-go/v2"
"github.com/pkg/errors"
"github.com/smallstep/certificates/cas/apiv1"
2020-10-28 00:59:32 +00:00
kmsapi "github.com/smallstep/certificates/kms/apiv1"
2020-10-27 02:52:08 +00:00
"google.golang.org/api/option"
2020-09-15 02:13:40 +00:00
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
2020-10-27 02:52:08 +00:00
longrunningpb "google.golang.org/genproto/googleapis/longrunning"
"google.golang.org/grpc"
2020-11-03 19:26:24 +00:00
"google.golang.org/grpc/test/bufconn"
2020-10-27 02:52:08 +00:00
"google.golang.org/protobuf/types/known/anypb"
2020-09-15 02:13:40 +00:00
)
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"
2020-10-27 02:52:08 +00:00
testProject = "test-project"
testLocation = "us-west1"
2020-09-15 02:13:40 +00:00
testRootCertificate = ` -- -- - BEGIN CERTIFICATE -- -- -
2020-10-28 00:59:32 +00:00
MIIBeDCCAR + gAwIBAgIQcXWWjtSZ / PAyH8D1Ou4L9jAKBggqhkjOPQQDAjAbMRkw
FwYDVQQDExBDbG91ZENBUyBSb290IENBMB4XDTIwMTAyNzIyNTM1NFoXDTMwMTAy
NzIyNTM1NFowGzEZMBcGA1UEAxMQQ2xvdWRDQVMgUm9vdCBDQTBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABIySHA4b78Yu4LuGhZIlv / PhNwXz4ZoV1OUZQ0LrK3vj
B13O12DLZC5uj1z3kxdQzXUttSbtRv49clMpBiTpsZKjRTBDMA4GA1UdDwEB / wQE
AwIBBjASBgNVHRMBAf8ECDAGAQH / AgEBMB0GA1UdDgQWBBSZ + t9RMHbFTl5BatM3
5 bJlHPOu3DAKBggqhkjOPQQDAgNHADBEAiASah6gg0tVM3WI0meCQ4SEKk7Mjhbv
+ SmhuZHWV1QlXQIgRXNyWcpVUrAoG6Uy1KQg07LDpF5dFeK9InrDxSJAkVo =
2020-09-15 02:13:40 +00:00
-- -- - END CERTIFICATE -- -- - `
testIntermediateCertificate = ` -- -- - BEGIN CERTIFICATE -- -- -
2020-10-28 00:59:32 +00:00
MIIBpDCCAUmgAwIBAgIRALLKxnxyl0GBeKevIcbx02wwCgYIKoZIzj0EAwIwGzEZ
MBcGA1UEAxMQQ2xvdWRDQVMgUm9vdCBDQTAeFw0yMDEwMjcyMjUzNTRaFw0zMDEw
MjcyMjUzNTRaMCMxITAfBgNVBAMTGENsb3VkQ0FTIEludGVybWVkaWF0ZSBDQTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABPLuqxgBY + QmaXc8zKIC8FMgjJ6dF / cL
b + Dig0XKc5GH / T1ORrhgOkRayrQcjPMu + jkjg25qn6vvp43LRtUKPXOjZjBkMA4G
A1UdDwEB / wQEAwIBBjASBgNVHRMBAf8ECDAGAQH / AgEAMB0GA1UdDgQWBBQ8RVQI
VgXAmRNDX8qItalVpSBEGjAfBgNVHSMEGDAWgBSZ + t9RMHbFTl5BatM35bJlHPOu
3 DAKBggqhkjOPQQDAgNJADBGAiEA70MVYVqjm8SBHJf5cOlWfiXXOfHUsctTJ + / F
pLsKBogCIQDJJkoQqYl9B59Dq3zydl8bpJevQxsoaa4Wqg + ZBMkvbQ ==
2020-09-15 02:13:40 +00:00
-- -- - END CERTIFICATE -- -- - `
testLeafCertificate = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIB1jCCAX2gAwIBAgIQQfOn + COMeuD8VYF1TiDkEzAKBggqhkjOPQQDAjAqMSgw
JgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDkx
NDIyNTE1NVoXDTMwMDkxMjIyNTE1MlowHTEbMBkGA1UEAxMSdGVzdC5zbWFsbHN0
ZXAuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAdUSRBrpgHFilN4eaGlN
nX2 + xfjXa1Iwk2 / + AensjFTXJi1UAIB0e + 4 pqi7Sen5E2QVBhntEHCrA3xOf7czg
P6OBkTCBjjAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMB0GA1UdDgQWBBSYPbu4Tmm7Zze / hCePeZH1Avoj + jAfBgNVHSMEGDAW
gBRIOVqyLDSlErJLuWWEvRm5UU1r1TAdBgNVHREEFjAUghJ0ZXN0LnNtYWxsc3Rl
cC5jb20wCgYIKoZIzj0EAwIDRwAwRAIgY + nTc + RHn31 / BOhht4JpxCmJPHxqFT3S
ojnictBudV0CIB87ipY5HV3c8FLVEzTA0wFwdDZvQraQYsthwbg2kQFb
-- -- - END CERTIFICATE -- -- - `
testSignedCertificate = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIB / DCCAaKgAwIBAgIQHHFuGMz0cClfde5kqP5prTAKBggqhkjOPQQDAjAqMSgw
JgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDkx
NTAwMDQ0M1oXDTMwMDkxMzAwMDQ0MFowHTEbMBkGA1UEAxMSdGVzdC5zbWFsbHN0
ZXAuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMqNCiXMvbn74LsHzRv + 8
17 m9vEzH6RHrg3m82e0uEc36 + fZWV / zJ9SKuONmnl5VP79LsjL5SVH0RDj73U2XO
DKOBtjCBszAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMB0GA1UdDgQWBBRTA2cTs7PCNjnps / + T0dS8diqv0DAfBgNVHSMEGDAW
gBRIOVqyLDSlErJLuWWEvRm5UU1r1TBCBgwrBgEEAYKkZMYoQAIEMjAwEwhjbG91
ZGNhcxMkZDhkMThhNjgtNTI5Ni00YWYzLWFlNGItMmY4NzdkYTNmYmQ5MAoGCCqG
SM49BAMCA0gAMEUCIGxl + pqJ50WYWUqK2l4V1FHoXSi0Nht5kwTxFxnWZu1xAiEA
zemu3bhWLFaGg3s8i + HTEhw4RqkHP74vF7AVYp88bAw =
-- -- - END CERTIFICATE -- -- - `
2020-10-27 02:52:08 +00:00
testIntermediateCsr = ` -- -- - BEGIN CERTIFICATE REQUEST -- -- -
2020-10-28 00:59:32 +00:00
MIHeMIGFAgEAMCMxITAfBgNVBAMTGENsb3VkQ0FTIEludGVybWVkaWF0ZSBDQTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABPLuqxgBY + QmaXc8zKIC8FMgjJ6dF / cL
b + Dig0XKc5GH / T1ORrhgOkRayrQcjPMu + jkjg25qn6vvp43LRtUKPXOgADAKBggq
hkjOPQQDAgNIADBFAiEAn3pkYXb2OzoQZ + AExFqd7qZ7pg2nyP2kBZZ01Pl8KfcC
IHKplBXDR79 / i7kjOtv1iWfgf5S / XQHrz178gXA0YQe7
2020-10-27 02:52:08 +00:00
-- -- - END CERTIFICATE REQUEST -- -- - `
2020-10-28 00:59:32 +00:00
testRootKey = ` -- -- - BEGIN EC PRIVATE KEY -- -- -
MHcCAQEEIN51Rgg6YcQVLeCRzumdw4pjM3VWqFIdCbnsV3Up1e / goAoGCCqGSM49
AwEHoUQDQgAEjJIcDhvvxi7gu4aFkiW / 8 + E3BfPhmhXU5RlDQusre + MHXc7XYMtk
Lm6PXPeTF1DNdS21Ju1G / j1yUykGJOmxkg ==
-- -- - END EC PRIVATE KEY -- -- - `
2020-10-28 01:03:02 +00:00
// nolint:unused,deadcode
2020-10-28 00:59:32 +00:00
testIntermediateKey = ` -- -- - BEGIN EC PRIVATE KEY -- -- -
MHcCAQEEIMMX / XkXGnRDD4fYu7Z4rHACdJn / iyOy2UTwsv + oZ0C + oAoGCCqGSM49
AwEHoUQDQgAE8u6rGAFj5CZpdzzMogLwUyCMnp0X9wtv4OKDRcpzkYf9PU5GuGA6
RFrKtByM8y76OSODbmqfq ++ njctG1Qo9cw ==
-- -- - END EC PRIVATE KEY -- -- - `
2020-09-15 02:13:40 +00:00
)
type testClient struct {
2020-09-21 22:27:20 +00:00
credentialsFile string
certificate * pb . Certificate
certificateAuthority * pb . CertificateAuthority
err error
2020-09-15 02:13:40 +00:00
}
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 } ,
} ,
2020-09-21 22:27:20 +00:00
certificateAuthority : & pb . CertificateAuthority {
PemCaCertificates : [ ] string { testIntermediateCertificate , testRootCertificate } ,
} ,
2020-09-15 02:13:40 +00:00
}
}
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 } ,
} ,
2020-09-21 22:27:20 +00:00
certificateAuthority : & pb . CertificateAuthority {
PemCaCertificates : [ ] string { testIntermediateCertificate , "not a pem cert" } ,
} ,
2020-09-15 02:13:40 +00:00
}
}
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 )
}
2020-10-28 00:59:32 +00:00
type badSigner struct {
pub crypto . PublicKey
}
func createBadSigner ( t * testing . T ) * badSigner {
t . Helper ( )
pub , _ , err := ed25519 . GenerateKey ( rand . Reader )
if err != nil {
t . Fatal ( err )
}
return & badSigner {
pub : pub ,
}
}
func ( b * badSigner ) Public ( ) crypto . PublicKey {
return b . pub
}
func ( b * badSigner ) Sign ( rand io . Reader , digest [ ] byte , opts crypto . SignerOpts ) ( [ ] byte , error ) {
return nil , fmt . Errorf ( "💥" )
}
2020-09-15 02:13:40 +00:00
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
}
2020-09-21 22:27:20 +00:00
func ( c * testClient ) GetCertificateAuthority ( ctx context . Context , req * pb . GetCertificateAuthorityRequest , opts ... gax . CallOption ) ( * pb . CertificateAuthority , error ) {
return c . certificateAuthority , c . err
}
2020-10-27 02:52:08 +00:00
func ( c * testClient ) CreateCertificateAuthority ( ctx context . Context , req * pb . CreateCertificateAuthorityRequest , opts ... gax . CallOption ) ( * privateca . CreateCertificateAuthorityOperation , error ) {
return nil , errors . New ( "use NewMockCertificateAuthorityClient" )
}
func ( c * testClient ) FetchCertificateAuthorityCsr ( ctx context . Context , req * pb . FetchCertificateAuthorityCsrRequest , opts ... gax . CallOption ) ( * pb . FetchCertificateAuthorityCsrResponse , error ) {
return nil , errors . New ( "use NewMockCertificateAuthorityClient" )
}
func ( c * testClient ) ActivateCertificateAuthority ( ctx context . Context , req * pb . ActivateCertificateAuthorityRequest , opts ... gax . CallOption ) ( * privateca . ActivateCertificateAuthorityOperation , error ) {
return nil , errors . New ( "use NewMockCertificateAuthorityClient" )
}
2020-09-15 02:13:40 +00:00
func mustParseCertificate ( t * testing . T , pemCert string ) * x509 . Certificate {
t . Helper ( )
crt , err := parseCertificate ( pemCert )
if err != nil {
t . Fatal ( err )
}
return crt
}
2020-10-28 00:59:32 +00:00
func mustParseECKey ( t * testing . T , pemKey string ) * ecdsa . PrivateKey {
t . Helper ( )
block , _ := pem . Decode ( [ ] byte ( pemKey ) )
if block == nil {
t . Fatal ( "failed to parse key" )
}
key , err := x509 . ParseECPrivateKey ( block . Bytes )
if err != nil {
t . Fatal ( err )
}
return key
}
2020-09-15 02:13:40 +00:00
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 {
2020-10-20 01:47:36 +00:00
CertificateAuthority : testAuthorityName ,
2020-09-15 02:13:40 +00:00
} } , & CloudCAS {
client : & testClient { } ,
certificateAuthority : testAuthorityName ,
2020-10-27 02:52:08 +00:00
project : testProject ,
location : testLocation ,
2020-09-15 02:13:40 +00:00
} , false } ,
{ "ok with credentials" , args { context . Background ( ) , apiv1 . Options {
2020-10-20 01:47:36 +00:00
CertificateAuthority : testAuthorityName , CredentialsFile : "testdata/credentials.json" ,
2020-09-15 02:13:40 +00:00
} } , & CloudCAS {
client : & testClient { credentialsFile : "testdata/credentials.json" } ,
certificateAuthority : testAuthorityName ,
2020-10-27 02:52:08 +00:00
project : testProject ,
location : testLocation ,
} , false } ,
{ "ok creator" , args { context . Background ( ) , apiv1 . Options {
IsCreator : true , Project : testProject , Location : testLocation ,
} } , & CloudCAS {
client : & testClient { } ,
project : testProject ,
location : testLocation ,
2020-09-15 02:13:40 +00:00
} , false } ,
2020-10-28 00:59:32 +00:00
{ "fail certificate authority" , args { context . Background ( ) , apiv1 . Options {
CertificateAuthority : "projects/ok1234/locations/ok1234/certificateAuthorities/ok1234/bad" ,
} } , nil , true } ,
{ "fail certificate authority regex" , args { context . Background ( ) , apiv1 . Options { } } , nil , true } ,
2020-09-15 02:13:40 +00:00
{ "fail with credentials" , args { context . Background ( ) , apiv1 . Options {
2020-10-20 01:47:36 +00:00
CertificateAuthority : testAuthorityName , CredentialsFile : "testdata/error.json" ,
2020-09-15 02:13:40 +00:00
} } , nil , true } ,
2020-10-27 02:52:08 +00:00
{ "fail creator project" , args { context . Background ( ) , apiv1 . Options {
IsCreator : true , Project : "" , Location : testLocation ,
} } , nil , true } ,
{ "fail creator location" , args { context . Background ( ) , apiv1 . Options {
IsCreator : true , Project : testProject , Location : "" ,
} } , nil , true } ,
2020-09-15 02:13:40 +00:00
}
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 ,
2020-10-27 02:52:08 +00:00
project : testProject ,
location : testLocation ,
2020-09-16 00:23:11 +00:00
}
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 {
2020-10-20 01:47:36 +00:00
CertificateAuthority : testAuthorityName , CredentialsFile : "testdata/credentials.json" ,
2020-09-16 00:23:11 +00:00
} )
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 {
2020-09-16 21:03:26 +00:00
name string
skipOnCI bool
args args
wantErr bool
2020-09-15 02:13:40 +00:00
} {
2020-10-20 01:47:36 +00:00
{ "fail default credentials" , true , args { context . Background ( ) , apiv1 . Options { CertificateAuthority : testAuthorityName } } , true } ,
2020-09-16 21:03:26 +00:00
{ "fail certificate authority" , false , args { context . Background ( ) , apiv1 . Options { } } , true } ,
{ "fail with credentials" , false , args { context . Background ( ) , apiv1 . Options {
2020-10-20 01:47:36 +00:00
CertificateAuthority : testAuthorityName , CredentialsFile : "testdata/missing.json" ,
2020-09-15 02:13:40 +00:00
} } , true } ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2020-09-16 21:03:26 +00:00
if tt . skipOnCI && os . Getenv ( "CI" ) == "true" {
t . SkipNow ( )
}
2020-09-15 02:13:40 +00:00
_ , err := New ( tt . args . ctx , tt . args . opts )
if ( err != nil ) != tt . wantErr {
t . Errorf ( "New() error = %v, wantErr %v" , err , tt . wantErr )
}
} )
}
}
2020-09-21 22:27:20 +00:00
func TestCloudCAS_GetCertificateAuthority ( t * testing . T ) {
root := mustParseCertificate ( t , testRootCertificate )
type fields struct {
client CertificateAuthorityClient
certificateAuthority string
}
type args struct {
req * apiv1 . GetCertificateAuthorityRequest
}
tests := [ ] struct {
name string
fields fields
args args
want * apiv1 . GetCertificateAuthorityResponse
wantErr bool
} {
{ "ok" , fields { okTestClient ( ) , testCertificateName } , args { & apiv1 . GetCertificateAuthorityRequest { } } , & apiv1 . GetCertificateAuthorityResponse {
RootCertificate : root ,
} , false } ,
{ "ok with name" , fields { okTestClient ( ) , testCertificateName } , args { & apiv1 . GetCertificateAuthorityRequest {
Name : testCertificateName ,
} } , & apiv1 . GetCertificateAuthorityResponse {
RootCertificate : root ,
} , false } ,
{ "fail GetCertificateAuthority" , fields { failTestClient ( ) , testCertificateName } , args { & apiv1 . GetCertificateAuthorityRequest { } } , nil , true } ,
{ "fail bad root" , fields { badTestClient ( ) , testCertificateName } , args { & apiv1 . GetCertificateAuthorityRequest { } } , nil , true } ,
{ "fail no pems" , fields { & testClient { certificateAuthority : & pb . CertificateAuthority { } } , testCertificateName } , args { & apiv1 . GetCertificateAuthorityRequest { } } , 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 . GetCertificateAuthority ( tt . args . req )
if ( err != nil ) != tt . wantErr {
t . Errorf ( "CloudCAS.GetCertificateAuthority() error = %v, wantErr %v" , err , tt . wantErr )
return
}
if ! reflect . DeepEqual ( got , tt . want ) {
t . Errorf ( "CloudCAS.GetCertificateAuthority() = %v, want %v" , got , tt . want )
}
} )
}
}
2020-09-15 02:13:40 +00:00
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 } ,
}
2020-09-16 19:41:43 +00:00
// Pre-calculate rand.Random
2020-09-15 02:13:40 +00:00
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 )
}
} )
}
}
2020-10-23 22:04:09 +00:00
2020-10-27 02:52:08 +00:00
func TestCloudCAS_CreateCertificateAuthority ( t * testing . T ) {
must := func ( a , b interface { } ) interface { } {
return a
}
ctrl := gomock . NewController ( t )
defer ctrl . Finish ( )
mosCtrl := gomock . NewController ( t )
defer mosCtrl . Finish ( )
m := NewMockCertificateAuthorityClient ( ctrl )
mos := NewMockOperationsServer ( mosCtrl )
// Create operation server
srv := grpc . NewServer ( )
longrunningpb . RegisterOperationsServer ( srv , mos )
2020-11-03 19:26:24 +00:00
lis := bufconn . Listen ( 2 )
2020-10-27 02:52:08 +00:00
go srv . Serve ( lis )
defer srv . Stop ( )
// Create fake privateca client
2020-11-03 19:26:24 +00:00
conn , err := grpc . DialContext ( context . Background ( ) , "" , grpc . WithInsecure ( ) ,
grpc . WithContextDialer ( func ( context . Context , string ) ( net . Conn , error ) {
return lis . Dial ( )
} ) )
2020-10-27 02:52:08 +00:00
if err != nil {
2020-11-03 19:26:24 +00:00
log . Fatal ( err )
2020-10-27 02:52:08 +00:00
}
client , err := lroauto . NewOperationsClient ( context . Background ( ) , option . WithGRPCConn ( conn ) )
2020-10-23 22:04:09 +00:00
if err != nil {
t . Fatal ( err )
}
2020-10-27 02:52:08 +00:00
fake := & privateca . CertificateAuthorityClient {
LROClient : client ,
}
// Configure mocks
any := gomock . Any ( )
// ok root
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
PemCaCertificates : [ ] string { testRootCertificate } ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
// ok intermediate
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
2020-10-28 00:59:32 +00:00
m . EXPECT ( ) . ActivateCertificateAuthority ( any , any ) . Return ( fake . ActivateCertificateAuthorityOperation ( "ActivateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "ActivateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
PemCaCertificates : [ ] string { testIntermediateCertificate , testRootCertificate } ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
// ok intermediate local signer
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
2020-10-27 02:52:08 +00:00
m . EXPECT ( ) . CreateCertificate ( any , any ) . Return ( & pb . Certificate {
PemCertificate : testIntermediateCertificate ,
PemCertificateChain : [ ] string { testRootCertificate } ,
} , nil )
m . EXPECT ( ) . ActivateCertificateAuthority ( any , any ) . Return ( fake . ActivateCertificateAuthorityOperation ( "ActivateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "ActivateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
PemCaCertificates : [ ] string { testIntermediateCertificate , testRootCertificate } ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
2020-10-28 00:59:32 +00:00
// ok create key
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
PemCaCertificates : [ ] string { testRootCertificate } ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
// fail CreateCertificateAuthority
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( nil , errTest )
// fail CreateCertificateAuthority.Wait
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( nil , errTest )
// fail FetchCertificateAuthorityCsr
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( nil , errTest )
// fail CreateCertificate
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
m . EXPECT ( ) . CreateCertificate ( any , any ) . Return ( nil , errTest )
// fail ActivateCertificateAuthority
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
m . EXPECT ( ) . CreateCertificate ( any , any ) . Return ( & pb . Certificate {
PemCertificate : testIntermediateCertificate ,
PemCertificateChain : [ ] string { testRootCertificate } ,
} , nil )
m . EXPECT ( ) . ActivateCertificateAuthority ( any , any ) . Return ( nil , errTest )
// fail ActivateCertificateAuthority.Wait
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
m . EXPECT ( ) . CreateCertificate ( any , any ) . Return ( & pb . Certificate {
PemCertificate : testIntermediateCertificate ,
PemCertificateChain : [ ] string { testRootCertificate } ,
} , nil )
m . EXPECT ( ) . ActivateCertificateAuthority ( any , any ) . Return ( fake . ActivateCertificateAuthorityOperation ( "ActivateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( nil , errTest )
// fail x509util.CreateCertificate
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : testIntermediateCsr ,
} , nil )
// fail parseCertificateRequest
m . EXPECT ( ) . CreateCertificateAuthority ( any , any ) . Return ( fake . CreateCertificateAuthorityOperation ( "CreateCertificateAuthority" ) , nil )
mos . EXPECT ( ) . GetOperation ( any , any ) . Return ( & longrunningpb . Operation {
Name : "CreateCertificateAuthority" ,
Done : true ,
Result : & longrunningpb . Operation_Response {
Response : must ( anypb . New ( & pb . CertificateAuthority {
Name : testAuthorityName ,
} ) ) . ( * anypb . Any ) ,
} ,
} , nil )
m . EXPECT ( ) . FetchCertificateAuthorityCsr ( any , any ) . Return ( & pb . FetchCertificateAuthorityCsrResponse {
PemCsr : "Not a CSR" ,
} , nil )
2020-10-27 02:52:08 +00:00
rootCrt := mustParseCertificate ( t , testRootCertificate )
intCrt := mustParseCertificate ( t , testIntermediateCertificate )
type fields struct {
client CertificateAuthorityClient
certificateAuthority string
project string
location string
}
type args struct {
req * apiv1 . CreateCertificateAuthorityRequest
}
tests := [ ] struct {
name string
fields fields
args args
want * apiv1 . CreateCertificateAuthorityResponse
wantErr bool
} {
{ "ok root" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} , false } ,
{ "ok intermediate" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} ,
} } , & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : intCrt ,
CertificateChain : [ ] * x509 . Certificate { rootCrt } ,
} , false } ,
2020-10-28 00:59:32 +00:00
{ "ok intermediate local signer" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Certificate : rootCrt ,
Signer : mustParseECKey ( t , testRootKey ) ,
} ,
} } , & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : intCrt ,
CertificateChain : [ ] * x509 . Certificate { rootCrt } ,
} , false } ,
{ "ok create key" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
CreateKey : & kmsapi . CreateKeyRequest {
SignatureAlgorithm : kmsapi . ECDSAWithSHA256 ,
} ,
} } , & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} , false } ,
{ "fail project" , fields { m , "" , "" , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail location" , fields { m , "" , testProject , "" } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail template" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail lifetime" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
} } , nil , true } ,
{ "fail parent" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail parent name" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse { } ,
} } , nil , true } ,
{ "fail type" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : 0 ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail create key" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
CreateKey : & kmsapi . CreateKeyRequest {
SignatureAlgorithm : kmsapi . PureEd25519 ,
} ,
} } , nil , true } ,
{ "fail CreateCertificateAuthority" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail CreateCertificateAuthority.Wait" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . RootCA ,
Template : mustParseCertificate ( t , testRootCertificate ) ,
Lifetime : 24 * time . Hour ,
} } , nil , true } ,
{ "fail FetchCertificateAuthorityCsr" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} ,
} } , nil , true } ,
{ "fail CreateCertificate" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} ,
} } , nil , true } ,
{ "fail ActivateCertificateAuthority" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} ,
} } , nil , true } ,
{ "fail ActivateCertificateAuthority.Wait" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Name : testAuthorityName ,
Certificate : rootCrt ,
} ,
} } , nil , true } ,
{ "fail x509util.CreateCertificate" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Certificate : rootCrt ,
Signer : createBadSigner ( t ) ,
} ,
} } , nil , true } ,
{ "fail parseCertificateRequest" , fields { m , "" , testProject , testLocation } , args { & apiv1 . CreateCertificateAuthorityRequest {
Type : apiv1 . IntermediateCA ,
Template : mustParseCertificate ( t , testIntermediateCertificate ) ,
Lifetime : 24 * time . Hour ,
Parent : & apiv1 . CreateCertificateAuthorityResponse {
Certificate : rootCrt ,
Signer : createBadSigner ( t ) ,
} ,
} } , nil , true } ,
2020-10-27 02:52:08 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
c := & CloudCAS {
client : tt . fields . client ,
certificateAuthority : tt . fields . certificateAuthority ,
project : tt . fields . project ,
location : tt . fields . location ,
}
got , err := c . CreateCertificateAuthority ( tt . args . req )
if ( err != nil ) != tt . wantErr {
t . Errorf ( "CloudCAS.CreateCertificateAuthority() error = %+v, wantErr %v" , err , tt . wantErr )
return
}
if ! reflect . DeepEqual ( got , tt . want ) {
t . Errorf ( "CloudCAS.CreateCertificateAuthority() = %v, want %v" , got , tt . want )
}
} )
}
2020-10-23 22:04:09 +00:00
}
2020-10-28 00:59:32 +00:00
func Test_normalizeCertificateAuthorityName ( t * testing . T ) {
type args struct {
name string
}
tests := [ ] struct {
name string
args args
want string
} {
{ "ok" , args { "Test-CA-Name_1234" } , "Test-CA-Name_1234" } ,
{ "change" , args { "💥 CA" } , "--CA" } ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
if got := normalizeCertificateAuthorityName ( tt . args . name ) ; got != tt . want {
t . Errorf ( "normalizeCertificateAuthorityName() = %v, want %v" , got , tt . want )
}
} )
}
}