|
|
@ -3,9 +3,14 @@ package cloudcas
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"crypto"
|
|
|
|
|
|
|
|
"crypto/ecdsa"
|
|
|
|
|
|
|
|
"crypto/ed25519"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/x509"
|
|
|
|
"crypto/x509"
|
|
|
|
"encoding/asn1"
|
|
|
|
"encoding/asn1"
|
|
|
|
|
|
|
|
"encoding/pem"
|
|
|
|
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
@ -20,6 +25,7 @@ import (
|
|
|
|
gax "github.com/googleapis/gax-go/v2"
|
|
|
|
gax "github.com/googleapis/gax-go/v2"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/smallstep/certificates/cas/apiv1"
|
|
|
|
"github.com/smallstep/certificates/cas/apiv1"
|
|
|
|
|
|
|
|
kmsapi "github.com/smallstep/certificates/kms/apiv1"
|
|
|
|
"google.golang.org/api/option"
|
|
|
|
"google.golang.org/api/option"
|
|
|
|
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
|
|
|
|
pb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1beta1"
|
|
|
|
longrunningpb "google.golang.org/genproto/googleapis/longrunning"
|
|
|
|
longrunningpb "google.golang.org/genproto/googleapis/longrunning"
|
|
|
@ -34,27 +40,25 @@ var (
|
|
|
|
testProject = "test-project"
|
|
|
|
testProject = "test-project"
|
|
|
|
testLocation = "us-west1"
|
|
|
|
testLocation = "us-west1"
|
|
|
|
testRootCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
testRootCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIBhjCCAS2gAwIBAgIQLbKTuXau4+t3KFbGpJJAADAKBggqhkjOPQQDAjAiMSAw
|
|
|
|
MIIBeDCCAR+gAwIBAgIQcXWWjtSZ/PAyH8D1Ou4L9jAKBggqhkjOPQQDAjAbMRkw
|
|
|
|
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
|
|
|
FwYDVQQDExBDbG91ZENBUyBSb290IENBMB4XDTIwMTAyNzIyNTM1NFoXDTMwMTAy
|
|
|
|
Fw0zMDA5MTIyMjQ4NDlaMCIxIDAeBgNVBAMTF0dvb2dsZSBDQVMgVGVzdCBSb290
|
|
|
|
NzIyNTM1NFowGzEZMBcGA1UEAxMQQ2xvdWRDQVMgUm9vdCBDQTBZMBMGByqGSM49
|
|
|
|
IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYKGgQ3/0D7+oBTc0CXoYfSC6
|
|
|
|
AgEGCCqGSM49AwEHA0IABIySHA4b78Yu4LuGhZIlv/PhNwXz4ZoV1OUZQ0LrK3vj
|
|
|
|
M8hOqLsmzBapPZSYpfwjgEsjdNU84jdrYmW1zF1+p+MrL4c7qJv9NLo/picCuqNF
|
|
|
|
B13O12DLZC5uj1z3kxdQzXUttSbtRv49clMpBiTpsZKjRTBDMA4GA1UdDwEB/wQE
|
|
|
|
MEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
|
|
|
|
AwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBSZ+t9RMHbFTl5BatM3
|
|
|
|
FFVn9V7Qymd7cUJh9KAhnUDAQL5YMAoGCCqGSM49BAMCA0cAMEQCIA4LzttYoT3u
|
|
|
|
5bJlHPOu3DAKBggqhkjOPQQDAgNHADBEAiASah6gg0tVM3WI0meCQ4SEKk7Mjhbv
|
|
|
|
8TYgSrvFT+Z+cklfi4UrPBU6aSbcUaW2AiAPfaqbyccQT3CxMVyHg+xZZjAirZp8
|
|
|
|
+SmhuZHWV1QlXQIgRXNyWcpVUrAoG6Uy1KQg07LDpF5dFeK9InrDxSJAkVo=
|
|
|
|
lAeA/T4FxAonHA==
|
|
|
|
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testIntermediateCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
testIntermediateCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIBsDCCAVagAwIBAgIQOb91kHxWKVzSJ9ESW1ViVzAKBggqhkjOPQQDAjAiMSAw
|
|
|
|
MIIBpDCCAUmgAwIBAgIRALLKxnxyl0GBeKevIcbx02wwCgYIKoZIzj0EAwIwGzEZ
|
|
|
|
HgYDVQQDExdHb29nbGUgQ0FTIFRlc3QgUm9vdCBDQTAeFw0yMDA5MTQyMjQ4NDla
|
|
|
|
MBcGA1UEAxMQQ2xvdWRDQVMgUm9vdCBDQTAeFw0yMDEwMjcyMjUzNTRaFw0zMDEw
|
|
|
|
Fw0zMDA5MTIyMjQ4NDlaMCoxKDAmBgNVBAMTH0dvb2dsZSBDQVMgVGVzdCBJbnRl
|
|
|
|
MjcyMjUzNTRaMCMxITAfBgNVBAMTGENsb3VkQ0FTIEludGVybWVkaWF0ZSBDQTBZ
|
|
|
|
cm1lZGlhdGUgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASUHN1cNyId4Ei/
|
|
|
|
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABPLuqxgBY+QmaXc8zKIC8FMgjJ6dF/cL
|
|
|
|
4MxD5VrZFc51P50caMUdDZVrPveidChBYCU/9IM6vnRlZHx2HLjQ0qAvqHwY3rT0
|
|
|
|
b+Dig0XKc5GH/T1ORrhgOkRayrQcjPMu+jkjg25qn6vvp43LRtUKPXOjZjBkMA4G
|
|
|
|
xc7n+PfCo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAd
|
|
|
|
A1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQ8RVQI
|
|
|
|
BgNVHQ4EFgQUSDlasiw0pRKyS7llhL0ZuVFNa9UwHwYDVR0jBBgwFoAUVWf1XtDK
|
|
|
|
VgXAmRNDX8qItalVpSBEGjAfBgNVHSMEGDAWgBSZ+t9RMHbFTl5BatM35bJlHPOu
|
|
|
|
Z3txQmH0oCGdQMBAvlgwCgYIKoZIzj0EAwIDSAAwRQIgMmsLcoC4KriXw+s+cZx2
|
|
|
|
3DAKBggqhkjOPQQDAgNJADBGAiEA70MVYVqjm8SBHJf5cOlWfiXXOfHUsctTJ+/F
|
|
|
|
bJMf6Mx/WESj31buJJhpzY0CIQCBUa/JtvS3nyce/4DF5tK2v49/NWHREgqAaZ57
|
|
|
|
pLsKBogCIQDJJkoQqYl9B59Dq3zydl8bpJevQxsoaa4Wqg+ZBMkvbQ==
|
|
|
|
DcYyHQ==
|
|
|
|
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testLeafCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
testLeafCertificate = `-----BEGIN CERTIFICATE-----
|
|
|
|
MIIB1jCCAX2gAwIBAgIQQfOn+COMeuD8VYF1TiDkEzAKBggqhkjOPQQDAjAqMSgw
|
|
|
|
MIIB1jCCAX2gAwIBAgIQQfOn+COMeuD8VYF1TiDkEzAKBggqhkjOPQQDAjAqMSgw
|
|
|
@ -82,20 +86,22 @@ SM49BAMCA0gAMEUCIGxl+pqJ50WYWUqK2l4V1FHoXSi0Nht5kwTxFxnWZu1xAiEA
|
|
|
|
zemu3bhWLFaGg3s8i+HTEhw4RqkHP74vF7AVYp88bAw=
|
|
|
|
zemu3bhWLFaGg3s8i+HTEhw4RqkHP74vF7AVYp88bAw=
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
-----END CERTIFICATE-----`
|
|
|
|
testIntermediateCsr = `-----BEGIN CERTIFICATE REQUEST-----
|
|
|
|
testIntermediateCsr = `-----BEGIN CERTIFICATE REQUEST-----
|
|
|
|
MIIBIjCByQIBADAqMSgwJgYDVQQDEx9Hb29nbGUgQ0FTIFRlc3QgSW50ZXJtZWRp
|
|
|
|
MIHeMIGFAgEAMCMxITAfBgNVBAMTGENsb3VkQ0FTIEludGVybWVkaWF0ZSBDQTBZ
|
|
|
|
YXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqoztio0c4XuaaGxHFiU7
|
|
|
|
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABPLuqxgBY+QmaXc8zKIC8FMgjJ6dF/cL
|
|
|
|
UBk3YRGTae9GtlKwyZJDk740hg6ZIoKcaXrzJT5taUpPiQLi7rP1eRui0dhl/bHo
|
|
|
|
b+Dig0XKc5GH/T1ORrhgOkRayrQcjPMu+jkjg25qn6vvp43LRtUKPXOgADAKBggq
|
|
|
|
o6A9MDsGCSqGSIb3DQEJDjEuMCwwKgYDVR0RBCMwIYIfR29vZ2xlIENBUyBUZXN0
|
|
|
|
hkjOPQQDAgNIADBFAiEAn3pkYXb2OzoQZ+AExFqd7qZ7pg2nyP2kBZZ01Pl8KfcC
|
|
|
|
IEludGVybWVkaWF0ZSBDQTAKBggqhkjOPQQDAgNIADBFAiEAvRKBPE32scAvsMe8
|
|
|
|
IHKplBXDR79/i7kjOtv1iWfgf5S/XQHrz178gXA0YQe7
|
|
|
|
R7ecx91q58ZmeLaRdSzL7stsnJYCIEBu+vQUSTbUpKL2YQNclT9kbilips5pEMr3
|
|
|
|
|
|
|
|
ojxK6mk3
|
|
|
|
|
|
|
|
-----END CERTIFICATE REQUEST-----`
|
|
|
|
-----END CERTIFICATE REQUEST-----`
|
|
|
|
|
|
|
|
testRootKey = `-----BEGIN EC PRIVATE KEY-----
|
|
|
|
// testIntermediateKey = `-----BEGIN EC PRIVATE KEY-----
|
|
|
|
MHcCAQEEIN51Rgg6YcQVLeCRzumdw4pjM3VWqFIdCbnsV3Up1e/goAoGCCqGSM49
|
|
|
|
// MHcCAQEEIMM+DSPChJgcYyqDWs0eRA5BctIo+VSNqRzCTL2ARYAqoAoGCCqGSM49
|
|
|
|
AwEHoUQDQgAEjJIcDhvvxi7gu4aFkiW/8+E3BfPhmhXU5RlDQusre+MHXc7XYMtk
|
|
|
|
// AwEHoUQDQgAEqoztio0c4XuaaGxHFiU7UBk3YRGTae9GtlKwyZJDk740hg6ZIoKc
|
|
|
|
Lm6PXPeTF1DNdS21Ju1G/j1yUykGJOmxkg==
|
|
|
|
// aXrzJT5taUpPiQLi7rP1eRui0dhl/bHoow==
|
|
|
|
-----END EC PRIVATE KEY-----`
|
|
|
|
// -----END EC PRIVATE KEY-----`
|
|
|
|
testIntermediateKey = `-----BEGIN EC PRIVATE KEY-----
|
|
|
|
|
|
|
|
MHcCAQEEIMMX/XkXGnRDD4fYu7Z4rHACdJn/iyOy2UTwsv+oZ0C+oAoGCCqGSM49
|
|
|
|
|
|
|
|
AwEHoUQDQgAE8u6rGAFj5CZpdzzMogLwUyCMnp0X9wtv4OKDRcpzkYf9PU5GuGA6
|
|
|
|
|
|
|
|
RFrKtByM8y76OSODbmqfq++njctG1Qo9cw==
|
|
|
|
|
|
|
|
-----END EC PRIVATE KEY-----`
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type testClient struct {
|
|
|
|
type testClient struct {
|
|
|
@ -158,6 +164,29 @@ func setTeeReader(t *testing.T, w *bytes.Buffer) {
|
|
|
|
rand.Reader = io.TeeReader(reader, w)
|
|
|
|
rand.Reader = io.TeeReader(reader, w)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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("💥")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (c *testClient) CreateCertificate(ctx context.Context, req *pb.CreateCertificateRequest, opts ...gax.CallOption) (*pb.Certificate, error) {
|
|
|
|
func (c *testClient) CreateCertificate(ctx context.Context, req *pb.CreateCertificateRequest, opts ...gax.CallOption) (*pb.Certificate, error) {
|
|
|
|
return c.certificate, c.err
|
|
|
|
return c.certificate, c.err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -191,6 +220,19 @@ func mustParseCertificate(t *testing.T, pemCert string) *x509.Certificate {
|
|
|
|
return crt
|
|
|
|
return crt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestNew(t *testing.T) {
|
|
|
|
func TestNew(t *testing.T) {
|
|
|
|
tmp := newCertificateAuthorityClient
|
|
|
|
tmp := newCertificateAuthorityClient
|
|
|
|
newCertificateAuthorityClient = func(ctx context.Context, credentialsFile string) (CertificateAuthorityClient, error) {
|
|
|
|
newCertificateAuthorityClient = func(ctx context.Context, credentialsFile string) (CertificateAuthorityClient, error) {
|
|
|
@ -233,7 +275,10 @@ func TestNew(t *testing.T) {
|
|
|
|
project: testProject,
|
|
|
|
project: testProject,
|
|
|
|
location: testLocation,
|
|
|
|
location: testLocation,
|
|
|
|
}, false},
|
|
|
|
}, false},
|
|
|
|
{"fail certificate authority", args{context.Background(), apiv1.Options{}}, nil, true},
|
|
|
|
{"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},
|
|
|
|
{"fail with credentials", args{context.Background(), apiv1.Options{
|
|
|
|
{"fail with credentials", args{context.Background(), apiv1.Options{
|
|
|
|
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/error.json",
|
|
|
|
CertificateAuthority: testAuthorityName, CredentialsFile: "testdata/error.json",
|
|
|
|
}}, nil, true},
|
|
|
|
}}, nil, true},
|
|
|
@ -735,8 +780,6 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
|
|
|
return a
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// client, close := mockTestClient()
|
|
|
|
|
|
|
|
// defer close()
|
|
|
|
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
defer ctrl.Finish()
|
|
|
|
mosCtrl := gomock.NewController(t)
|
|
|
|
mosCtrl := gomock.NewController(t)
|
|
|
@ -801,6 +844,31 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
|
|
|
m.EXPECT().FetchCertificateAuthorityCsr(any, any).Return(&pb.FetchCertificateAuthorityCsrResponse{
|
|
|
|
m.EXPECT().FetchCertificateAuthorityCsr(any, any).Return(&pb.FetchCertificateAuthorityCsrResponse{
|
|
|
|
PemCsr: testIntermediateCsr,
|
|
|
|
PemCsr: testIntermediateCsr,
|
|
|
|
}, nil)
|
|
|
|
}, 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)
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
m.EXPECT().CreateCertificate(any, any).Return(&pb.Certificate{
|
|
|
|
m.EXPECT().CreateCertificate(any, any).Return(&pb.Certificate{
|
|
|
|
PemCertificate: testIntermediateCertificate,
|
|
|
|
PemCertificate: testIntermediateCertificate,
|
|
|
|
PemCertificateChain: []string{testRootCertificate},
|
|
|
|
PemCertificateChain: []string{testRootCertificate},
|
|
|
@ -817,6 +885,126 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil)
|
|
|
|
}, nil)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
|
|
|
|
rootCrt := mustParseCertificate(t, testRootCertificate)
|
|
|
|
rootCrt := mustParseCertificate(t, testRootCertificate)
|
|
|
|
intCrt := mustParseCertificate(t, testIntermediateCertificate)
|
|
|
|
intCrt := mustParseCertificate(t, testIntermediateCertificate)
|
|
|
|
|
|
|
|
|
|
|
@ -857,6 +1045,136 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
|
|
|
Certificate: intCrt,
|
|
|
|
Certificate: intCrt,
|
|
|
|
CertificateChain: []*x509.Certificate{rootCrt},
|
|
|
|
CertificateChain: []*x509.Certificate{rootCrt},
|
|
|
|
}, false},
|
|
|
|
}, false},
|
|
|
|
|
|
|
|
{"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},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
@ -877,3 +1195,24 @@ func TestCloudCAS_CreateCertificateAuthority(t *testing.T) {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|