From 181ca4069ddaa5bccf7cf91376b77b14f9c965a7 Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Tue, 17 Oct 2023 16:11:07 -0700 Subject: [PATCH] v0.0.3-beta (#8) * v0.0.3-beta * v0.0.3-beta * v0.0.3-beta * v0.0.3-beta * v0.0.3-beta --- .dockerignore | 1 - .github/workflows/release_build.yml | 2 +- Dockerfile | 3 +- Makefile | 8 +- cmd/{server/main.go => baseca/server.go} | 8 +- cmd/server/baseca/server.go | 69 ---- .../rds.global.bundle.pem | 0 config/config.primary.development.aws.yml | 2 + config/config.primary.production.aws.yml | 1 + .../casbin => config/permissions}/model.conf | 0 .../casbin => config/permissions}/policy.csv | 0 db/mock/store.go | 89 ++-- db/query/accounts.sql | 5 + db/query/certificate.sql | 1 - db/query/provisioners.sql | 1 - db/sqlc/accounts.sql.go | 36 +- db/sqlc/aws_attestation.sql.go | 2 +- db/sqlc/certificate.sql.go | 3 +- db/sqlc/db.go | 2 +- db/sqlc/models.go | 2 +- db/sqlc/provisioners.sql.go | 3 +- db/sqlc/querier.go | 3 +- db/sqlc/tx_update_account.go | 2 +- db/sqlc/users.sql.go | 2 +- docs/ENDPOINTS.md | 3 +- docs/GETTING_STARTED.md | 31 +- docs/images/baseca_image.png | Bin 248104 -> 84626 bytes .../baseca.v1.Certificate/code_sign.go | 35 +- .../operations_sign_csr.go | 14 +- .../baseca.v1.Certificate/sign_csr.go | 14 +- .../config/config.primary.development.aws.yml | 2 + .../config/config.primary.local.sandbox.yml | 1 + .../config/config.primary.production.aws.yml | 1 + gen/go/baseca/v1/api.pb.go | 390 +++++++++--------- go.mod | 2 +- go.sum | 9 +- .../{attestor => attestation}/aws_iid/iid.go | 0 internal/attestation/aws_iid/iid_test.go | 33 ++ .../aws_iid/certificate/ec2.amazonaws.com.crt | 19 - internal/authentication/payload.go | 38 -- internal/authorization/permission.go | 16 - internal/client/acmpca/client.go | 2 +- internal/client/acmpca/issue.go | 2 +- internal/client/acmpca/query.go | 2 +- internal/client/acmpca/revoke.go | 2 +- internal/config/config.go | 5 +- .../{environment => config}/environment.go | 2 +- internal/config/fx.go | 6 +- internal/config/load.go | 10 +- internal/config/path.go | 8 +- internal/environment/fx.go | 11 - internal/gateway/{grpc => }/fx.go | 70 +++- .../authentication/credentials.go} | 2 +- internal/{ => lib}/authentication/issuer.go | 7 +- internal/lib/crypto/csr.go | 99 +++++ internal/lib/crypto/csr_test.go | 61 +++ internal/lib/crypto/generate.go | 95 +++++ internal/lib/crypto/generate_test.go | 71 ++++ internal/lib/crypto/pk.go | 80 +--- internal/lib/util/backoff.go | 2 +- internal/lib/util/errors.go | 11 - internal/lib/util/random.go | 4 +- internal/{ => lib/util}/validator/domain.go | 21 - internal/lib/util/validator/domain_test.go | 67 +++ .../{ => lib/util}/validator/environment.go | 0 .../lib/util/validator/environment_test.go | 45 ++ internal/{ => lib/util}/validator/fx.go | 0 internal/lib/util/validator/permission.go | 12 + internal/{ => lib/util}/validator/validate.go | 50 ++- .../{ => lib/util}/validator/validate_test.go | 24 ++ internal/logger/logger.go | 79 ++-- internal/types/account.go | 37 +- internal/types/certificate.go | 56 ++- internal/types/constants.go | 15 +- internal/v1/accounts/accounts.go | 2 +- internal/v1/accounts/accounts_test.go | 2 +- internal/v1/accounts/operation_test.go | 2 +- internal/v1/accounts/provision.go | 88 +++- internal/v1/accounts/provision_test.go | 294 ++++++++++++- internal/v1/accounts/query.go | 2 +- internal/v1/accounts/query_test.go | 2 +- internal/v1/accounts/service.go | 14 +- internal/v1/accounts/service_test.go | 24 +- internal/v1/accounts/validate.go | 2 +- internal/v1/certificate/certificate.go | 6 +- internal/v1/certificate/certificate_test.go | 15 +- internal/v1/certificate/operations.go | 18 +- internal/v1/certificate/operations_test.go | 9 +- internal/v1/certificate/pca.go | 9 +- internal/v1/certificate/query.go | 2 +- internal/v1/certificate/query_test.go | 2 +- internal/v1/certificate/sign.go | 19 +- internal/v1/certificate/sign_test.go | 11 +- internal/v1/certificate/validate.go | 13 +- internal/v1/middleware/authentication.go | 26 +- internal/v1/middleware/middleware.go | 10 +- internal/v1/users/operations.go | 19 +- internal/v1/users/operations_test.go | 8 +- internal/v1/users/users.go | 6 +- internal/v1/users/users_test.go | 6 +- pkg/attestor/aws_iid/iid.go | 4 +- pkg/client/certificate.go | 5 +- pkg/client/client.go | 4 +- pkg/client/csr.go | 19 +- pkg/client/provisioner.go | 3 +- pkg/client/sign.go | 60 ++- pkg/types/certificate.go | 71 ++++ pkg/types/sign.go | 16 + protos/baseca/v1/api.proto | 1 + test/config/config.test.local.sandbox.yml | 11 +- 110 files changed, 1773 insertions(+), 843 deletions(-) rename cmd/{server/main.go => baseca/server.go} (77%) delete mode 100644 cmd/server/baseca/server.go rename {internal/attestor/aws_iid/certificate => config/certificate_authority}/rds.global.bundle.pem (100%) rename {internal/authorization/casbin => config/permissions}/model.conf (100%) rename {internal/authorization/casbin => config/permissions}/policy.csv (100%) rename internal/{attestor => attestation}/aws_iid/iid.go (100%) create mode 100644 internal/attestation/aws_iid/iid_test.go delete mode 100644 internal/attestor/aws_iid/certificate/ec2.amazonaws.com.crt delete mode 100644 internal/authentication/payload.go delete mode 100644 internal/authorization/permission.go rename internal/{environment => config}/environment.go (97%) delete mode 100644 internal/environment/fx.go rename internal/gateway/{grpc => }/fx.go (67%) rename internal/{authentication/authentication.go => lib/authentication/credentials.go} (97%) rename internal/{ => lib}/authentication/issuer.go (98%) create mode 100644 internal/lib/crypto/csr.go create mode 100644 internal/lib/crypto/csr_test.go create mode 100644 internal/lib/crypto/generate.go create mode 100644 internal/lib/crypto/generate_test.go delete mode 100644 internal/lib/util/errors.go rename internal/{ => lib/util}/validator/domain.go (76%) create mode 100644 internal/lib/util/validator/domain_test.go rename internal/{ => lib/util}/validator/environment.go (100%) create mode 100644 internal/lib/util/validator/environment_test.go rename internal/{ => lib/util}/validator/fx.go (100%) create mode 100644 internal/lib/util/validator/permission.go rename internal/{ => lib/util}/validator/validate.go (69%) rename internal/{ => lib/util}/validator/validate_test.go (76%) create mode 100644 pkg/types/certificate.go create mode 100644 pkg/types/sign.go diff --git a/.dockerignore b/.dockerignore index cfc83e6..1021c82 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ .github/ -config/ docs/ examples/ pkg/ diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml index 37ddc81..50e06bd 100644 --- a/.github/workflows/release_build.yml +++ b/.github/workflows/release_build.yml @@ -43,7 +43,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=ref,event=branch + type=ref,event=tag type=sha # Build and push Docker image with Buildx (don't push on PR) diff --git a/Dockerfile b/Dockerfile index ae1e832..782d916 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,7 @@ RUN adduser --home /home/baseca baseca --gecos "baseca" --disabled-password && \ rm -rf /var/cache/apk/* COPY --from=builder /baseca/target/bin/linux/baseca /home/baseca/baseca -COPY --from=builder /baseca/internal/authorization/casbin /home/baseca/internal/authorization/casbin -COPY --from=builder /baseca/internal/attestor/aws_iid/certificate /home/baseca/internal/attestor/aws_iid/certificate +COPY --from=builder /baseca/config /home/baseca/config RUN chown -R baseca:baseca /home/baseca diff --git a/Makefile b/Makefile index cbd24dc..d6c7316 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,8 @@ test: info clean dependencies .PHONY: build build: info clean - @ GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BIN)/darwin/$(SERVICE) cmd/server/main.go - @ GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BIN)/linux/$(SERVICE) cmd/server/main.go + @ GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BIN)/darwin/$(SERVICE) cmd/baseca/server.go + @ GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BIN)/linux/$(SERVICE) cmd/baseca/server.go .PHONY: sqlc sqlc: @@ -47,7 +47,7 @@ gen: info clean .PHONY: server server: @ database_credentials=${DATABASE_CREDENTIALS} \ - go run cmd/server/main.go + go run cmd/baseca/server.go .PHONY: lint lint: @@ -55,7 +55,9 @@ lint: .PHONY: tools tools: + @ go install go.uber.org/mock/mockgen@latest @ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 @ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 @ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest @ which buf || (go install github.com/bufbuild/buf/cmd/buf@latest) + diff --git a/cmd/server/main.go b/cmd/baseca/server.go similarity index 77% rename from cmd/server/main.go rename to cmd/baseca/server.go index 3b93fdb..d876e9a 100644 --- a/cmd/server/main.go +++ b/cmd/baseca/server.go @@ -6,9 +6,8 @@ import ( "time" "github.com/coinbase/baseca/internal/config" - "github.com/coinbase/baseca/internal/environment" - "github.com/coinbase/baseca/internal/gateway/grpc" - "github.com/coinbase/baseca/internal/validator" + "github.com/coinbase/baseca/internal/gateway" + "github.com/coinbase/baseca/internal/lib/util/validator" _ "github.com/lib/pq" "go.uber.org/fx" "go.uber.org/fx/fxevent" @@ -19,8 +18,7 @@ func main() { app := fx.New( fx.Options( config.Module, - environment.Module, - grpc.Module, + gateway.Module, validator.Module, ), fx.WithLogger( diff --git a/cmd/server/baseca/server.go b/cmd/server/baseca/server.go deleted file mode 100644 index 2b732f6..0000000 --- a/cmd/server/baseca/server.go +++ /dev/null @@ -1,69 +0,0 @@ -package apiservice - -import ( - "context" - "fmt" - "time" - - "github.com/allegro/bigcache/v3" - "github.com/casbin/casbin/v2" - db "github.com/coinbase/baseca/db/sqlc" - apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" - "github.com/coinbase/baseca/internal/config" - "github.com/coinbase/baseca/internal/v1/accounts" - "github.com/coinbase/baseca/internal/v1/certificate" - "github.com/coinbase/baseca/internal/v1/middleware" - "github.com/coinbase/baseca/internal/v1/users" -) - -const ( - // Local Memory (Authentication) - _default_cleanup = 10 * time.Minute -) - -type Server struct { - apiv1.CertificateServer - Store db.DatabaseEndpoints - Auth authentication.Auth - Service *accounts.Service - Certificate *certificate.Certificate - User *users.User - Middleware *middleware.Middleware -} - -func BuildServer(store db.DatabaseEndpoints, cfg *config.Config, enforcer *casbin.Enforcer) (*Server, error) { - signer, err := authentication.BuildSigningClient(cfg) - if err != nil { - return nil, err - } - - auth, err := authentication.NewAuthSigningMetadata(signer) - if err != nil { - return nil, err - } - - cache, err := bigcache.New(context.Background(), bigcache.DefaultConfig(_default_cleanup)) - if err != nil { - return nil, fmt.Errorf("error instantiating memory cache") - } - - service := accounts.New(cfg, store) - user := users.New(cfg, store, auth) - middleware := middleware.New(auth, store, enforcer, cache) - certificate, err := certificate.New(cfg, store) - if err != nil { - return nil, fmt.Errorf("issue instantiating certificate client [%s]", err) - } - - server := &Server{ - Store: store, - Auth: auth, - Service: service, - Certificate: certificate, - User: user, - Middleware: middleware, - } - - return server, nil -} diff --git a/internal/attestor/aws_iid/certificate/rds.global.bundle.pem b/config/certificate_authority/rds.global.bundle.pem similarity index 100% rename from internal/attestor/aws_iid/certificate/rds.global.bundle.pem rename to config/certificate_authority/rds.global.bundle.pem diff --git a/config/config.primary.development.aws.yml b/config/config.primary.development.aws.yml index c3fdf9a..a8394ea 100644 --- a/config/config.primary.development.aws.yml +++ b/config/config.primary.development.aws.yml @@ -25,11 +25,13 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true development_usw1: region: us-west-1 ca_arn: arn:aws:acm-pca:us-west-1:123456789012:certificate-authority/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy ca_active_day: 90 assume_role: false + default: false firehose: stream: baseca-development diff --git a/config/config.primary.production.aws.yml b/config/config.primary.production.aws.yml index 5d4eab9..b2d2d3a 100644 --- a/config/config.primary.production.aws.yml +++ b/config/config.primary.production.aws.yml @@ -28,6 +28,7 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true # Configure Additional Certificate Authorities (development_use1, staging_use1, etc) diff --git a/internal/authorization/casbin/model.conf b/config/permissions/model.conf similarity index 100% rename from internal/authorization/casbin/model.conf rename to config/permissions/model.conf diff --git a/internal/authorization/casbin/policy.csv b/config/permissions/policy.csv similarity index 100% rename from internal/authorization/casbin/policy.csv rename to config/permissions/policy.csv diff --git a/db/mock/store.go b/db/mock/store.go index 4cba965..a633ee5 100644 --- a/db/mock/store.go +++ b/db/mock/store.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/coinbase/baseca/db/sqlc (interfaces: Store) - +// +// Generated by this command: +// +// mockgen --build_flags=--mod=mod -package mock -destination db/mock/store.go github.com/coinbase/baseca/db/sqlc Store +// // Package mock is a generated GoMock package. package mock @@ -10,8 +14,8 @@ import ( db "github.com/coinbase/baseca/db/sqlc" types "github.com/coinbase/baseca/internal/types" - gomock "github.com/golang/mock/gomock" uuid "github.com/google/uuid" + gomock "go.uber.org/mock/gomock" ) // MockStore is a mock of Store interface. @@ -47,7 +51,7 @@ func (m *MockStore) CreateProvisionerAccount(arg0 context.Context, arg1 db.Creat } // CreateProvisionerAccount indicates an expected call of CreateProvisionerAccount. -func (mr *MockStoreMockRecorder) CreateProvisionerAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) CreateProvisionerAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateProvisionerAccount", reflect.TypeOf((*MockStore)(nil).CreateProvisionerAccount), arg0, arg1) } @@ -62,7 +66,7 @@ func (m *MockStore) CreateServiceAccount(arg0 context.Context, arg1 db.CreateSer } // CreateServiceAccount indicates an expected call of CreateServiceAccount. -func (mr *MockStoreMockRecorder) CreateServiceAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) CreateServiceAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateServiceAccount", reflect.TypeOf((*MockStore)(nil).CreateServiceAccount), arg0, arg1) } @@ -77,7 +81,7 @@ func (m *MockStore) CreateUser(arg0 context.Context, arg1 db.CreateUserParams) ( } // CreateUser indicates an expected call of CreateUser. -func (mr *MockStoreMockRecorder) CreateUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) CreateUser(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0, arg1) } @@ -91,7 +95,7 @@ func (m *MockStore) DeleteInstanceIdentityDocument(arg0 context.Context, arg1 uu } // DeleteInstanceIdentityDocument indicates an expected call of DeleteInstanceIdentityDocument. -func (mr *MockStoreMockRecorder) DeleteInstanceIdentityDocument(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) DeleteInstanceIdentityDocument(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteInstanceIdentityDocument", reflect.TypeOf((*MockStore)(nil).DeleteInstanceIdentityDocument), arg0, arg1) } @@ -105,7 +109,7 @@ func (m *MockStore) DeleteProvisionerAccount(arg0 context.Context, arg1 uuid.UUI } // DeleteProvisionerAccount indicates an expected call of DeleteProvisionerAccount. -func (mr *MockStoreMockRecorder) DeleteProvisionerAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) DeleteProvisionerAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteProvisionerAccount", reflect.TypeOf((*MockStore)(nil).DeleteProvisionerAccount), arg0, arg1) } @@ -119,7 +123,7 @@ func (m *MockStore) DeleteServiceAccount(arg0 context.Context, arg1 uuid.UUID) e } // DeleteServiceAccount indicates an expected call of DeleteServiceAccount. -func (mr *MockStoreMockRecorder) DeleteServiceAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) DeleteServiceAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceAccount", reflect.TypeOf((*MockStore)(nil).DeleteServiceAccount), arg0, arg1) } @@ -133,7 +137,7 @@ func (m *MockStore) DeleteUser(arg0 context.Context, arg1 string) error { } // DeleteUser indicates an expected call of DeleteUser. -func (mr *MockStoreMockRecorder) DeleteUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) DeleteUser(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUser", reflect.TypeOf((*MockStore)(nil).DeleteUser), arg0, arg1) } @@ -148,7 +152,7 @@ func (m *MockStore) GetCertificate(arg0 context.Context, arg1 string) (*db.Certi } // GetCertificate indicates an expected call of GetCertificate. -func (mr *MockStoreMockRecorder) GetCertificate(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetCertificate(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCertificate", reflect.TypeOf((*MockStore)(nil).GetCertificate), arg0, arg1) } @@ -163,7 +167,7 @@ func (m *MockStore) GetInstanceIdentityDocument(arg0 context.Context, arg1 uuid. } // GetInstanceIdentityDocument indicates an expected call of GetInstanceIdentityDocument. -func (mr *MockStoreMockRecorder) GetInstanceIdentityDocument(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetInstanceIdentityDocument(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceIdentityDocument", reflect.TypeOf((*MockStore)(nil).GetInstanceIdentityDocument), arg0, arg1) } @@ -178,7 +182,7 @@ func (m *MockStore) GetProvisionerUUID(arg0 context.Context, arg1 uuid.UUID) (*d } // GetProvisionerUUID indicates an expected call of GetProvisionerUUID. -func (mr *MockStoreMockRecorder) GetProvisionerUUID(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetProvisionerUUID(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProvisionerUUID", reflect.TypeOf((*MockStore)(nil).GetProvisionerUUID), arg0, arg1) } @@ -193,7 +197,7 @@ func (m *MockStore) GetServiceAccountByMetadata(arg0 context.Context, arg1 db.Ge } // GetServiceAccountByMetadata indicates an expected call of GetServiceAccountByMetadata. -func (mr *MockStoreMockRecorder) GetServiceAccountByMetadata(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetServiceAccountByMetadata(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccountByMetadata", reflect.TypeOf((*MockStore)(nil).GetServiceAccountByMetadata), arg0, arg1) } @@ -208,7 +212,7 @@ func (m *MockStore) GetServiceAccountBySAN(arg0 context.Context, arg1 []string) } // GetServiceAccountBySAN indicates an expected call of GetServiceAccountBySAN. -func (mr *MockStoreMockRecorder) GetServiceAccountBySAN(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetServiceAccountBySAN(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccountBySAN", reflect.TypeOf((*MockStore)(nil).GetServiceAccountBySAN), arg0, arg1) } @@ -223,7 +227,7 @@ func (m *MockStore) GetServiceAccounts(arg0 context.Context, arg1 string) ([]*db } // GetServiceAccounts indicates an expected call of GetServiceAccounts. -func (mr *MockStoreMockRecorder) GetServiceAccounts(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetServiceAccounts(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccounts", reflect.TypeOf((*MockStore)(nil).GetServiceAccounts), arg0, arg1) } @@ -238,7 +242,7 @@ func (m *MockStore) GetServiceUUID(arg0 context.Context, arg1 uuid.UUID) (*db.Ac } // GetServiceUUID indicates an expected call of GetServiceUUID. -func (mr *MockStoreMockRecorder) GetServiceUUID(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetServiceUUID(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceUUID", reflect.TypeOf((*MockStore)(nil).GetServiceUUID), arg0, arg1) } @@ -253,7 +257,7 @@ func (m *MockStore) GetSignedCertificateByMetadata(arg0 context.Context, arg1 db } // GetSignedCertificateByMetadata indicates an expected call of GetSignedCertificateByMetadata. -func (mr *MockStoreMockRecorder) GetSignedCertificateByMetadata(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetSignedCertificateByMetadata(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSignedCertificateByMetadata", reflect.TypeOf((*MockStore)(nil).GetSignedCertificateByMetadata), arg0, arg1) } @@ -268,7 +272,7 @@ func (m *MockStore) GetUser(arg0 context.Context, arg1 string) (*db.User, error) } // GetUser indicates an expected call of GetUser. -func (mr *MockStoreMockRecorder) GetUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) GetUser(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUser", reflect.TypeOf((*MockStore)(nil).GetUser), arg0, arg1) } @@ -283,7 +287,7 @@ func (m *MockStore) ListCertificateSubjectAlternativeName(arg0 context.Context, } // ListCertificateSubjectAlternativeName indicates an expected call of ListCertificateSubjectAlternativeName. -func (mr *MockStoreMockRecorder) ListCertificateSubjectAlternativeName(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) ListCertificateSubjectAlternativeName(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListCertificateSubjectAlternativeName", reflect.TypeOf((*MockStore)(nil).ListCertificateSubjectAlternativeName), arg0, arg1) } @@ -298,7 +302,7 @@ func (m *MockStore) ListCertificates(arg0 context.Context, arg1 db.ListCertifica } // ListCertificates indicates an expected call of ListCertificates. -func (mr *MockStoreMockRecorder) ListCertificates(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) ListCertificates(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListCertificates", reflect.TypeOf((*MockStore)(nil).ListCertificates), arg0, arg1) } @@ -313,7 +317,7 @@ func (m *MockStore) ListProvisionerAccounts(arg0 context.Context, arg1 db.ListPr } // ListProvisionerAccounts indicates an expected call of ListProvisionerAccounts. -func (mr *MockStoreMockRecorder) ListProvisionerAccounts(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) ListProvisionerAccounts(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListProvisionerAccounts", reflect.TypeOf((*MockStore)(nil).ListProvisionerAccounts), arg0, arg1) } @@ -328,7 +332,7 @@ func (m *MockStore) ListServiceAccounts(arg0 context.Context, arg1 db.ListServic } // ListServiceAccounts indicates an expected call of ListServiceAccounts. -func (mr *MockStoreMockRecorder) ListServiceAccounts(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) ListServiceAccounts(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListServiceAccounts", reflect.TypeOf((*MockStore)(nil).ListServiceAccounts), arg0, arg1) } @@ -343,11 +347,26 @@ func (m *MockStore) ListUsers(arg0 context.Context, arg1 db.ListUsersParams) ([] } // ListUsers indicates an expected call of ListUsers. -func (mr *MockStoreMockRecorder) ListUsers(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) ListUsers(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUsers", reflect.TypeOf((*MockStore)(nil).ListUsers), arg0, arg1) } +// ListValidCertificateAuthorityFromSubordinateCA mocks base method. +func (m *MockStore) ListValidCertificateAuthorityFromSubordinateCA(arg0 context.Context, arg1 db.ListValidCertificateAuthorityFromSubordinateCAParams) ([]any, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListValidCertificateAuthorityFromSubordinateCA", arg0, arg1) + ret0, _ := ret[0].([]any) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListValidCertificateAuthorityFromSubordinateCA indicates an expected call of ListValidCertificateAuthorityFromSubordinateCA. +func (mr *MockStoreMockRecorder) ListValidCertificateAuthorityFromSubordinateCA(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListValidCertificateAuthorityFromSubordinateCA", reflect.TypeOf((*MockStore)(nil).ListValidCertificateAuthorityFromSubordinateCA), arg0, arg1) +} + // LogCertificate mocks base method. func (m *MockStore) LogCertificate(arg0 context.Context, arg1 db.LogCertificateParams) (*db.Certificate, error) { m.ctrl.T.Helper() @@ -358,7 +377,7 @@ func (m *MockStore) LogCertificate(arg0 context.Context, arg1 db.LogCertificateP } // LogCertificate indicates an expected call of LogCertificate. -func (mr *MockStoreMockRecorder) LogCertificate(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) LogCertificate(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogCertificate", reflect.TypeOf((*MockStore)(nil).LogCertificate), arg0, arg1) } @@ -372,7 +391,7 @@ func (m *MockStore) RevokeIssuedCertificateSerialNumber(arg0 context.Context, ar } // RevokeIssuedCertificateSerialNumber indicates an expected call of RevokeIssuedCertificateSerialNumber. -func (mr *MockStoreMockRecorder) RevokeIssuedCertificateSerialNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) RevokeIssuedCertificateSerialNumber(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RevokeIssuedCertificateSerialNumber", reflect.TypeOf((*MockStore)(nil).RevokeIssuedCertificateSerialNumber), arg0, arg1) } @@ -387,7 +406,7 @@ func (m *MockStore) StoreInstanceIdentityDocument(arg0 context.Context, arg1 db. } // StoreInstanceIdentityDocument indicates an expected call of StoreInstanceIdentityDocument. -func (mr *MockStoreMockRecorder) StoreInstanceIdentityDocument(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) StoreInstanceIdentityDocument(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreInstanceIdentityDocument", reflect.TypeOf((*MockStore)(nil).StoreInstanceIdentityDocument), arg0, arg1) } @@ -402,7 +421,7 @@ func (m *MockStore) TxCreateProvisionerAccount(arg0 context.Context, arg1 db.Cre } // TxCreateProvisionerAccount indicates an expected call of TxCreateProvisionerAccount. -func (mr *MockStoreMockRecorder) TxCreateProvisionerAccount(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) TxCreateProvisionerAccount(arg0, arg1, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxCreateProvisionerAccount", reflect.TypeOf((*MockStore)(nil).TxCreateProvisionerAccount), arg0, arg1, arg2) } @@ -417,7 +436,7 @@ func (m *MockStore) TxCreateServiceAccount(arg0 context.Context, arg1 db.CreateS } // TxCreateServiceAccount indicates an expected call of TxCreateServiceAccount. -func (mr *MockStoreMockRecorder) TxCreateServiceAccount(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) TxCreateServiceAccount(arg0, arg1, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxCreateServiceAccount", reflect.TypeOf((*MockStore)(nil).TxCreateServiceAccount), arg0, arg1, arg2) } @@ -431,7 +450,7 @@ func (m *MockStore) TxDeleteProvisionerAccount(arg0 context.Context, arg1 uuid.U } // TxDeleteProvisionerAccount indicates an expected call of TxDeleteProvisionerAccount. -func (mr *MockStoreMockRecorder) TxDeleteProvisionerAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) TxDeleteProvisionerAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxDeleteProvisionerAccount", reflect.TypeOf((*MockStore)(nil).TxDeleteProvisionerAccount), arg0, arg1) } @@ -445,7 +464,7 @@ func (m *MockStore) TxDeleteServiceAccount(arg0 context.Context, arg1 uuid.UUID) } // TxDeleteServiceAccount indicates an expected call of TxDeleteServiceAccount. -func (mr *MockStoreMockRecorder) TxDeleteServiceAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) TxDeleteServiceAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxDeleteServiceAccount", reflect.TypeOf((*MockStore)(nil).TxDeleteServiceAccount), arg0, arg1) } @@ -460,7 +479,7 @@ func (m *MockStore) TxUpdateServiceAccount(arg0 context.Context, arg1 db.Account } // TxUpdateServiceAccount indicates an expected call of TxUpdateServiceAccount. -func (mr *MockStoreMockRecorder) TxUpdateServiceAccount(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) TxUpdateServiceAccount(arg0, arg1, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxUpdateServiceAccount", reflect.TypeOf((*MockStore)(nil).TxUpdateServiceAccount), arg0, arg1, arg2) } @@ -475,7 +494,7 @@ func (m *MockStore) UpdateInstanceIdentityNodeAttestor(arg0 context.Context, arg } // UpdateInstanceIdentityNodeAttestor indicates an expected call of UpdateInstanceIdentityNodeAttestor. -func (mr *MockStoreMockRecorder) UpdateInstanceIdentityNodeAttestor(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) UpdateInstanceIdentityNodeAttestor(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateInstanceIdentityNodeAttestor", reflect.TypeOf((*MockStore)(nil).UpdateInstanceIdentityNodeAttestor), arg0, arg1) } @@ -490,7 +509,7 @@ func (m *MockStore) UpdateServiceAccount(arg0 context.Context, arg1 db.UpdateSer } // UpdateServiceAccount indicates an expected call of UpdateServiceAccount. -func (mr *MockStoreMockRecorder) UpdateServiceAccount(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) UpdateServiceAccount(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateServiceAccount", reflect.TypeOf((*MockStore)(nil).UpdateServiceAccount), arg0, arg1) } @@ -505,7 +524,7 @@ func (m *MockStore) UpdateUserAuthentication(arg0 context.Context, arg1 db.Updat } // UpdateUserAuthentication indicates an expected call of UpdateUserAuthentication. -func (mr *MockStoreMockRecorder) UpdateUserAuthentication(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) UpdateUserAuthentication(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserAuthentication", reflect.TypeOf((*MockStore)(nil).UpdateUserAuthentication), arg0, arg1) } @@ -520,7 +539,7 @@ func (m *MockStore) UpdateUserPermission(arg0 context.Context, arg1 db.UpdateUse } // UpdateUserPermission indicates an expected call of UpdateUserPermission. -func (mr *MockStoreMockRecorder) UpdateUserPermission(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) UpdateUserPermission(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPermission", reflect.TypeOf((*MockStore)(nil).UpdateUserPermission), arg0, arg1) } diff --git a/db/query/accounts.sql b/db/query/accounts.sql index aa27958..d4c8473 100644 --- a/db/query/accounts.sql +++ b/db/query/accounts.sql @@ -68,3 +68,8 @@ WHERE valid_subject_alternate_name = ANY($1::string[]); -- name: GetServiceAccountByMetadata :many SELECT * FROM accounts WHERE service_account LIKE $1 AND environment LIKE $2 AND extended_key LIKE $3; + +-- name: ListValidCertificateAuthorityFromSubordinateCA :many +SELECT DISTINCT unnest(valid_certificate_authorities) AS certificate_authorities +FROM accounts +WHERE subordinate_ca = $1 AND environment = $2; diff --git a/db/query/certificate.sql b/db/query/certificate.sql index 56d00a3..6987027 100644 --- a/db/query/certificate.sql +++ b/db/query/certificate.sql @@ -25,7 +25,6 @@ OFFSET $3; -- name: ListCertificates :many SELECT * FROM certificates -ORDER BY certificates LIMIT $1 OFFSET $2; diff --git a/db/query/provisioners.sql b/db/query/provisioners.sql index 1bbcd29..0b1a622 100644 --- a/db/query/provisioners.sql +++ b/db/query/provisioners.sql @@ -27,6 +27,5 @@ WHERE client_id = $1; -- name: ListProvisionerAccounts :many SELECT * FROM provisioners -ORDER BY provisioners LIMIT $1 OFFSET $2; \ No newline at end of file diff --git a/db/sqlc/accounts.sql.go b/db/sqlc/accounts.sql.go index a4bd797..bdca389 100644 --- a/db/sqlc/accounts.sql.go +++ b/db/sqlc/accounts.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 // source: accounts.sql package db @@ -329,6 +329,40 @@ func (q *Queries) ListServiceAccounts(ctx context.Context, arg ListServiceAccoun return items, nil } +const listValidCertificateAuthorityFromSubordinateCA = `-- name: ListValidCertificateAuthorityFromSubordinateCA :many +SELECT DISTINCT unnest(valid_certificate_authorities) AS certificate_authorities +FROM accounts +WHERE subordinate_ca = $1 AND environment = $2 +` + +type ListValidCertificateAuthorityFromSubordinateCAParams struct { + SubordinateCa string `json:"subordinate_ca"` + Environment string `json:"environment"` +} + +func (q *Queries) ListValidCertificateAuthorityFromSubordinateCA(ctx context.Context, arg ListValidCertificateAuthorityFromSubordinateCAParams) ([]interface{}, error) { + rows, err := q.db.QueryContext(ctx, listValidCertificateAuthorityFromSubordinateCA, arg.SubordinateCa, arg.Environment) + if err != nil { + return nil, err + } + defer rows.Close() + items := []interface{}{} + for rows.Next() { + var certificate_authorities interface{} + if err := rows.Scan(&certificate_authorities); err != nil { + return nil, err + } + items = append(items, certificate_authorities) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const updateInstanceIdentityNodeAttestor = `-- name: UpdateInstanceIdentityNodeAttestor :one UPDATE accounts SET diff --git a/db/sqlc/aws_attestation.sql.go b/db/sqlc/aws_attestation.sql.go index 36a0eba..c2eaa98 100644 --- a/db/sqlc/aws_attestation.sql.go +++ b/db/sqlc/aws_attestation.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 // source: aws_attestation.sql package db diff --git a/db/sqlc/certificate.sql.go b/db/sqlc/certificate.sql.go index 74191cf..e278aa9 100644 --- a/db/sqlc/certificate.sql.go +++ b/db/sqlc/certificate.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 // source: certificate.sql package db @@ -142,7 +142,6 @@ func (q *Queries) ListCertificateSubjectAlternativeName(ctx context.Context, arg const listCertificates = `-- name: ListCertificates :many SELECT serial_number, account, environment, extended_key, common_name, subject_alternative_name, expiration_date, issued_date, revoked, revoked_by, revoke_date, certificate_authority_arn FROM certificates -ORDER BY certificates LIMIT $1 OFFSET $2 ` diff --git a/db/sqlc/db.go b/db/sqlc/db.go index e0b5347..46fda54 100644 --- a/db/sqlc/db.go +++ b/db/sqlc/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 package db diff --git a/db/sqlc/models.go b/db/sqlc/models.go index 182682d..c71cd07 100644 --- a/db/sqlc/models.go +++ b/db/sqlc/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 package db diff --git a/db/sqlc/provisioners.sql.go b/db/sqlc/provisioners.sql.go index cb128f6..ea547ed 100644 --- a/db/sqlc/provisioners.sql.go +++ b/db/sqlc/provisioners.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 // source: provisioners.sql package db @@ -123,7 +123,6 @@ func (q *Queries) GetProvisionerUUID(ctx context.Context, clientID uuid.UUID) (* const listProvisionerAccounts = `-- name: ListProvisionerAccounts :many SELECT client_id, api_token, provisioner_account, environments, team, email, regular_expression, valid_subject_alternate_names, extended_keys, max_certificate_validity, node_attestation, created_at, created_by FROM provisioners -ORDER BY provisioners LIMIT $1 OFFSET $2 ` diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 89a4079..561f2bd 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 package db @@ -32,6 +32,7 @@ type Querier interface { ListProvisionerAccounts(ctx context.Context, arg ListProvisionerAccountsParams) ([]*Provisioner, error) ListServiceAccounts(ctx context.Context, arg ListServiceAccountsParams) ([]*Account, error) ListUsers(ctx context.Context, arg ListUsersParams) ([]*User, error) + ListValidCertificateAuthorityFromSubordinateCA(ctx context.Context, arg ListValidCertificateAuthorityFromSubordinateCAParams) ([]interface{}, error) LogCertificate(ctx context.Context, arg LogCertificateParams) (*Certificate, error) RevokeIssuedCertificateSerialNumber(ctx context.Context, arg RevokeIssuedCertificateSerialNumberParams) error StoreInstanceIdentityDocument(ctx context.Context, arg StoreInstanceIdentityDocumentParams) (*AwsAttestation, error) diff --git a/db/sqlc/tx_update_account.go b/db/sqlc/tx_update_account.go index 815eba7..63615fa 100644 --- a/db/sqlc/tx_update_account.go +++ b/db/sqlc/tx_update_account.go @@ -4,8 +4,8 @@ import ( "context" "database/sql" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" ) func (store *SQLStore) TxUpdateServiceAccount(ctx context.Context, arg Account, attestation types.NodeAttestation) (*Account, error) { diff --git a/db/sqlc/users.sql.go b/db/sqlc/users.sql.go index 10f8410..7ddcfb5 100644 --- a/db/sqlc/users.sql.go +++ b/db/sqlc/users.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.21.0 // source: users.sql package db diff --git a/docs/ENDPOINTS.md b/docs/ENDPOINTS.md index 356ac20..7fb008c 100644 --- a/docs/ENDPOINTS.md +++ b/docs/ENDPOINTS.md @@ -1115,6 +1115,7 @@ message CreateServiceAccountRequest { optional NodeAttestation node_attestation = 9; string team = 10; string email = 11; + optional string region = 12; } message NodeAttestation { AWSInstanceIdentityDocument aws_iid = 1; @@ -1163,7 +1164,7 @@ message CreateServiceAccountResponse { "serviceAccount": "example", "environment": "development", "subjectAlternativeNames": ["development.coinbase.com"], - "certificateAuthorities": ["cb_sandbox_use1_cbhq_net"], + "certificateAuthorities": ["sandbox_use1"], "extendedKey": "EndEntityServerAuthCertificate", "nodeAttestation": { "awsIid": { diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index 991f4e5..c996a68 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -192,11 +192,11 @@ Compile the Golang Binary `baseca` ```sh # Darwin AMD64 -GOOS=darwin GOARCH=amd64 go build -o target/bin/darwin/baseca cmd/server/main.go +GOOS=darwin GOARCH=amd64 go build -o target/bin/darwin/baseca cmd/baseca/server.go database_credentials=secret ./target/bin/darwin/baseca # Linux AMD64 -GOOS=linux GOARCH=amd64 go build -o target/bin/linux/baseca cmd/server/main.go +GOOS=linux GOARCH=amd64 go build -o target/bin/linux/baseca cmd/baseca/server.go database_credentials=secret ./target/bin/linux/baseca ``` @@ -216,12 +216,12 @@ ssl_mode: disable Start the Golang `baseca` gRPC Server ```sh -password=secret go run cmd/server/main.go +database_credentials=secret go run cmd/baseca/server.go ``` ## Signing x.509 Certificate -Start the `baseca` gRPC server via the preferred method within the [Local Deployment](#local-deployment) section and then run the [`baseca.v1.Account/LoginUser`](ENDPOINTS.md#basecav1accountloginuser) RPC method. +Start the `baseca` gRPC server via the preferred method within the [Local Deployment](#local-deployment) section and then run the [`baseca.v1.Account/LoginUser`](ENDPOINTS.md#basecav1accountloginuser) RPC method. ### 1. Generate Authentication Token @@ -314,15 +314,20 @@ import ( ) func main() { - client_id := [CLIENT_ID] - client_token := [CLIENT_TOKEN] - configuration := baseca.Configuration{ URL: "localhost:9090", Environment: baseca.Env.Local, } - client, err := baseca.LoadDefaultConfiguration(configuration, client_id, client_token, baseca.Attestation.Local) + authentication := baseca.Authentication{ + ClientId: "CLIENT_ID", + ClientToken: "CLIENT_TOKEN", + } + + client, err := baseca.LoadDefaultConfiguration(configuration, baseca.Attestation.Local, authentication) + if err != nil { + fmt.Println(err) + } if err != nil { // Handle Error @@ -336,10 +341,12 @@ func main() { PublicKeyAlgorithm: x509.RSA, KeySize: 4096, Output: baseca.Output{ - PrivateKey: "/tmp/private.key", // baseca Generate Private Key Output Location - Certificate: "/tmp/certificate.crt", // baseca Signed Leaf Certificate Output Location - CertificateChain: "/tmp/full_chain.crt", // baseca Signed Certificate Chain Output Location - CertificateSigningRequest: "/tmp/request.csr", // baseca CSR Output Location + PrivateKey: "/tmp/private.key", // baseca Generate Private Key Output Location + Certificate: "/tmp/certificate.crt", // baseca Signed Leaf Certificate Output Location + IntermediateCertificateChain: "/tmp/intermediate_chain.crt", // baseca Signed Certificate Chain Up to Intermediate CA Output Location + RootCertificateChain: "/tmp/root_chain.crt", // baseca Signed Full Certificate Chain Output Location + CertificateSigningRequest: "/tmp/certificate_request.csr", // baseca CSR Output Location + }, } } diff --git a/docs/images/baseca_image.png b/docs/images/baseca_image.png index 2a34f305d6e0bd382361e7cb4b625068642a1585..0c93a7bea343092fa05f3ef323fbadf0c04aa611 100644 GIT binary patch literal 84626 zcmaI71z1#T*fvTtlz=oyODNslB_%B_4oG){bayC?l+vJd$I#t5bcb|H!&$iZ{`UUQ z|DEG?%{Ak!S@o{>eV)4rQ+_Lhfl7=D0|SF0`$kd~1_q%X1_l-ngamwpzR2?k1A|&_ zE+L^TD|kqRZeJr{Lj*$|zGRLTzLSPzTQy9@J4P)Ps~Lii*ecL2e~f{~R?52DVUMGxzUvXs6oJRV zyUV*c4%iO`C%NMa>O>UsUl<}l=ir_$x-wZWQA8wVUqns_g-kyNCMKdn_xbYXqP1x7 z1;*a0*5kunOL(|)JT;7HJKJ0QEl>rkaNti^KlMa3-+8~;sI4uzkZZwi3-%wPk>u!( zyY!goj;EmY6KY`QB=*(cZ1a_~L|omD64MoDj{y6Q^6N_YzHIe<%%~zx&l1Oa|3kW)_P` zDZYo#MvMc|${TW@uN``lSx810Mnd1sOh^h!-Q86c%&-mP^eB+5r$zS0+LIdu>C?t2 zPqKVLxQX1xP)-wK*ls)vcMor_H&+o0uRQD7Bap3IXLDS`twxdZepnYCL-jE)iJ?m3 zqsQ;+zQ{qSXMb6 zN*qoKQ=4#@)%!6ZX_X=Qfg{Y?*7693b)hm_b4{`H4GR@OAyE%? zR6R5o!ehg+gxbmoV`hcdYwVs~v+4o|_uH}+fol{_h!xJU49UX|$@Lh?2NcX2>hG3} z2=^v{F}6)l3p9|06%Hn~3Y42cng{dj2f&Xa$gJX~1<2cB*tB{5@_+C44F338FctzO zC3;|x8RbnVieb)STG+#p=yK#6iQ7YGZt6!aBYsVgqBuPAqew8R9J8YDbyR z`S?TOUtr|>akOf$^YR+#5i-Lj`Nyr|uZP=g_gi_}`-+GRUVjP$r*b!J6 zs2ljcU4ZIyffy%s16DxjNvG2q+?vH2z9Ia{%kqF3i5D+FztMTg@CEr*WGCI`7gSli zoaP*yoV}d)Ps^Ir4U#|TQQTYD3#4l0Lm1GO5Bn#yVRdyQ2 z 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

PejZVBDpq{2f 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

W7kWM1Keyi+ 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

-Z3iISM84brl=R9-jqjt#<++WFw#` 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

3Hrf%72 z2(R>;F{p51ABVi^@$ql-HkQ

(1&JJVMvQw{AdZ)fC z#fD}(wU3m{^%i2T6*kE5jMqUdjqmwW&Jvw!o#8BbQ!P*L3-8_ZN^AHmJ!kmKNJfPa z8{565F67FF(V*zjG`)Nj(`XNk&)#drk21+>rO)hIz<)t*;>Dj4Zg zxw4*%Eb~2HpiAI|H2X|9dAZhHaK|!D$MH2tpsQ3`U6g15;3Rb)7(j-~Tlct21#HKo z1!nV@_-vcZ%e{RIa+4pI26qGK^qB$89B-X3x^U3STP8Gcz)2a&&(-qFDoO0(Kg5_; z9F)kwEF70mBU*m68+LBkY%`*}#UyTNEAB4-CFUHbZ zS*DQBO0OU)e^${S{tD6@Q8(t32tcgSJf+PUep(}^|AI3bJoDp;qdiEB^ZUE`&a2?V zHOKq$#qOoxJ)}U=CP<(v>Y1%yD|RXl|B|oP2=gRntxuV6Q*X`oiDwG{^;9Q|`^^f& zjokLn4!>0uG5}@~vvv~7@MF#d**H&-!zK*8FZnV%coU{$Ps8p z?m-V{SBa>X+2>d9$Hqw`iPVSTA zC|By`Ku436cll#v1C)C+M{^1TMm{L;^8j=#2J1-ScFD_gb>-xTp3I*kphX_sbw{%w zOGmlkGBt=7t9FMp_M} zoIGSkb1R_`Mkbrs0@^Gf4{U%AAJ zdij-)CrDj6V09#lnMOB}_Tz=xva==n+HqIVz(DXGuZ0{Z8HdrZc`~GI#&@+@4x6bJ zRg^aa%*SrcLi6qs>!*-sF*r*{#RU@p_$BVQgGb`6qjo9$>Dzn&3h6WRdPgNvy=C@} z!RK+Syo(DTm*>Z@)U{}LumbrHv+95+MLs{)sH={!uDf5~=o#2wSLS{SBttzdbybcj z!yjYePo0Q^=Qw8SgKr2Mmp%5hhUdh*c=bx}(m3v5op)k+WOpA3oMYZ6@xwjaV!0m4 zogMDPxot_FgHvnN%~b9tet1D&aE_9X`iym>S=^+Ege_*yG)lh)+_hHr%?x$QDY|Fs z+_r_xoXQCN1f&e^Tf=hpt)_rko8>&dt+i`95oK$WU6a}Ub`$EXZ!}s1UFHGcO>h4N zBx0N~%UL@t^xA0GNT$B_2@FqX8e&Mi!J@uu+ZOneXB?4FgOn;D$9*cAZ)&7nat^*h zlcGo{0HAF$FI9f1sNZ6$fEP?ex&VkQfS4<-5nEcIm-Rfbt>3z&6nBfhU3r=}+Nlj> zn()WnZBDn)*Tpq%9L#c*U(5nor=BZofoy?|2o9|GrwA8|sSf0`&&0aJsRdAF0SA6U zVVoawceMPIocIC+?|T$G$89g<^#!fjv@bF$T;bab-SKBsxymV#UzHMH>eJ}TxS&sK zG(D{nFZZeF7e{mUtxF>*i>o7;!K|%2LG4Uew4i}6E}D2VIfafEQnWH9!6$Bovehkq zG<`A`)y#u?7Q$jbeIsM^h-rC1rh>JyV&?YmnsG9q52lKk-QfSCFd?1wXe<6%^&I$1VP54-j$=;qn1(*)-ZZGR8vRNy*Q*Or%$+e3x4A6TV!JZa zJpim>UO0LIA4Bd{@|7C{Hca})+Y4xnz@|lg)9iGtwy+vJ52Q%)(QRYg7Re377&nr~5zx#4i7!9(nQ)t^LriA`i7o?;^b>877qzS_7&G za{#_%FF2H~hK!vsUulUHKuZ9*6mwLZ@k{u#qiw?l8DiJ{voYNdKzIqhnB{}aYVhcw zjcgzn@j2H9sD#~g{B}y#Dxpb≀hDXJ|B$B%b22c#La3)tH?^lZ0C{u2P%`=@foX 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

I`3J7 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

7cC#tjZzjaO$(AMdMJB|R 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 Hx1atWwqwC1 diff --git a/examples/certificate/baseca.v1.Certificate/code_sign.go b/examples/certificate/baseca.v1.Certificate/code_sign.go index a29b284..1b3956f 100644 --- a/examples/certificate/baseca.v1.Certificate/code_sign.go +++ b/examples/certificate/baseca.v1.Certificate/code_sign.go @@ -6,18 +6,21 @@ import ( "os" baseca "github.com/coinbase/baseca/pkg/client" + "github.com/coinbase/baseca/pkg/types" ) func CodeSign() { - client_id := "[CLIENT_ID]" - client_token := "[CLIENT_TOKEN]" - configuration := baseca.Configuration{ URL: "localhost:9090", Environment: baseca.Env.Local, } - client, err := baseca.LoadDefaultConfiguration(configuration, client_id, client_token, baseca.Attestation.Local) + authentication := baseca.Authentication{ + ClientId: "CLIENT_ID", + ClientToken: "CLIENT_TOKEN", + } + + client, err := baseca.LoadDefaultConfiguration(configuration, baseca.Attestation.Local, authentication) if err != nil { fmt.Println(err) } @@ -25,9 +28,13 @@ func CodeSign() { metadata := baseca.CertificateRequest{ CommonName: "sandbox.coinbase.com", SubjectAlternateNames: []string{"sandbox.coinbase.com"}, - SigningAlgorithm: x509.SHA384WithRSA, - PublicKeyAlgorithm: x509.RSA, - KeySize: 4096, + SigningAlgorithm: x509.ECDSAWithSHA384, + PublicKeyAlgorithm: x509.ECDSA, + KeySize: 256, + DistinguishedName: baseca.DistinguishedName{ + Organization: []string{"Coinbase"}, + // Additional Fields + }, Output: baseca.Output{ PrivateKey: "/tmp/private.key", Certificate: "/tmp/certificate.crt", @@ -44,7 +51,19 @@ func CodeSign() { } // Validation Happens on Different Server - err = client.ValidateSignature(chain, *signature, data, "sandbox.coinbase.com", "/path/to/system/root") + manifest := types.Manifest{ + CertificateChain: chain, + Signature: *signature, + Data: data, + SigningAlgorithm: x509.SHA256WithRSA, + } + + tc := types.TrustChain{ + CommonName: "sandbox.coinbase.com", + CertificateAuthorityFiles: []string{"/path/to/intermediate.pem"}, + } + + err = client.ValidateSignature(tc, manifest) if err != nil { panic(err) } diff --git a/examples/certificate/baseca.v1.Certificate/operations_sign_csr.go b/examples/certificate/baseca.v1.Certificate/operations_sign_csr.go index 25520f1..b1d0e99 100644 --- a/examples/certificate/baseca.v1.Certificate/operations_sign_csr.go +++ b/examples/certificate/baseca.v1.Certificate/operations_sign_csr.go @@ -10,15 +10,17 @@ import ( ) func OperationsSignCSR() { - client_id := "[CLIENT_ID]" - client_token := "[CLIENT_TOKEN]" - configuration := baseca.Configuration{ URL: "localhost:9090", Environment: baseca.Env.Local, } - client, err := baseca.LoadDefaultConfiguration(configuration, client_id, client_token, baseca.Attestation.Local) + authentication := baseca.Authentication{ + ClientId: "CLIENT_ID", + ClientToken: "CLIENT_TOKEN", + } + + client, err := baseca.LoadDefaultConfiguration(configuration, baseca.Attestation.Local, authentication) if err != nil { fmt.Println(err) } @@ -37,6 +39,10 @@ func OperationsSignCSR() { SigningAlgorithm: x509.SHA384WithRSA, PublicKeyAlgorithm: x509.RSA, KeySize: 4096, + DistinguishedName: baseca.DistinguishedName{ + Organization: []string{"Coinbase"}, + // Additional Fields + }, Output: baseca.Output{ PrivateKey: "/tmp/sandbox.key", CertificateSigningRequest: "/tmp/sandbox.csr", diff --git a/examples/certificate/baseca.v1.Certificate/sign_csr.go b/examples/certificate/baseca.v1.Certificate/sign_csr.go index 8cb7833..8597e1a 100644 --- a/examples/certificate/baseca.v1.Certificate/sign_csr.go +++ b/examples/certificate/baseca.v1.Certificate/sign_csr.go @@ -9,15 +9,17 @@ import ( ) func SignCSR() { - client_id := "[CLIENT_ID]" - client_token := "[CLIENT_TOKEN]" - configuration := baseca.Configuration{ URL: "localhost:9090", Environment: baseca.Env.Local, } - client, err := baseca.LoadDefaultConfiguration(configuration, client_id, client_token, baseca.Attestation.Local) + authentication := baseca.Authentication{ + ClientId: "CLIENT_ID", + ClientToken: "CLIENT_TOKEN", + } + + client, err := baseca.LoadDefaultConfiguration(configuration, baseca.Attestation.Local, authentication) if err != nil { fmt.Println(err) } @@ -28,6 +30,10 @@ func SignCSR() { SigningAlgorithm: x509.SHA384WithRSA, PublicKeyAlgorithm: x509.RSA, KeySize: 4096, + DistinguishedName: baseca.DistinguishedName{ + Organization: []string{"Coinbase"}, + // Additional Fields + }, Output: baseca.Output{ PrivateKey: "/tmp/private.key", Certificate: "/tmp/certificate.crt", diff --git a/examples/config/config.primary.development.aws.yml b/examples/config/config.primary.development.aws.yml index c3fdf9a..a8394ea 100644 --- a/examples/config/config.primary.development.aws.yml +++ b/examples/config/config.primary.development.aws.yml @@ -25,11 +25,13 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true development_usw1: region: us-west-1 ca_arn: arn:aws:acm-pca:us-west-1:123456789012:certificate-authority/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy ca_active_day: 90 assume_role: false + default: false firehose: stream: baseca-development diff --git a/examples/config/config.primary.local.sandbox.yml b/examples/config/config.primary.local.sandbox.yml index dbb6af8..2c3e1f4 100644 --- a/examples/config/config.primary.local.sandbox.yml +++ b/examples/config/config.primary.local.sandbox.yml @@ -20,6 +20,7 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true firehose: stream: baseca-development diff --git a/examples/config/config.primary.production.aws.yml b/examples/config/config.primary.production.aws.yml index 5d4eab9..b2d2d3a 100644 --- a/examples/config/config.primary.production.aws.yml +++ b/examples/config/config.primary.production.aws.yml @@ -28,6 +28,7 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true # Configure Additional Certificate Authorities (development_use1, staging_use1, etc) diff --git a/gen/go/baseca/v1/api.pb.go b/gen/go/baseca/v1/api.pb.go index 9d76759..576f403 100644 --- a/gen/go/baseca/v1/api.pb.go +++ b/gen/go/baseca/v1/api.pb.go @@ -2638,6 +2638,7 @@ type ProvisionServiceAccountRequest struct { NodeAttestation *NodeAttestation `protobuf:"bytes,9,opt,name=node_attestation,json=nodeAttestation,proto3" json:"node_attestation,omitempty"` Team string `protobuf:"bytes,10,opt,name=team,proto3" json:"team,omitempty"` Email string `protobuf:"bytes,11,opt,name=email,proto3" json:"email,omitempty"` + Region *string `protobuf:"bytes,12,opt,name=region,proto3,oneof" json:"region,omitempty"` } func (x *ProvisionServiceAccountRequest) Reset() { @@ -2749,6 +2750,13 @@ func (x *ProvisionServiceAccountRequest) GetEmail() string { return "" } +func (x *ProvisionServiceAccountRequest) GetRegion() string { + if x != nil && x.Region != nil { + return *x.Region + } + return "" +} + type ProvisionServiceAccountResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3481,7 +3489,7 @@ var file_baseca_v1_api_proto_rawDesc = []byte{ 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0xfd, 0x03, + 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0xa5, 0x04, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, @@ -3513,197 +3521,200 @@ var file_baseca_v1_api_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x52, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x98, 0x05, - 0x0a, 0x1f, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1b, 0x0a, + 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x22, 0x98, 0x05, 0x0a, 0x1f, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x5f, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x19, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x61, + 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, + 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, + 0x37, 0x0a, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x10, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x13, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, + 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x43, 0x61, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x65, 0x61, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x22, 0x97, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, + 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, + 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x32, 0xac, 0x04, 0x0a, 0x0b, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x07, 0x53, 0x69, + 0x67, 0x6e, 0x43, 0x53, 0x52, 0x12, 0x24, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x47, 0x65, 0x74, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x1a, + 0x1f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x12, 0x58, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x11, 0x52, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, + 0x23, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x43, 0x53, 0x52, 0x12, + 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, + 0x68, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x32, 0xe0, 0x03, 0x0a, 0x07, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x46, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, + 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, + 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x36, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x62, 0x61, 0x73, + 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, + 0x10, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, + 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x4d, + 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x23, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x4d, 0x0a, + 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x32, 0xd8, 0x07, 0x0a, + 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x26, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, - 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, - 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x12, - 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x5f, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, - 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x19, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x10, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, - 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, - 0x0e, 0x73, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, - 0x74, 0x65, 0x43, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x44, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, - 0x10, 0x02, 0x32, 0xac, 0x04, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x07, 0x53, 0x69, 0x67, 0x6e, 0x43, 0x53, 0x52, 0x12, 0x24, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, - 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x58, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x62, - 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x62, - 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x69, 0x67, 0x6e, 0x43, 0x53, 0x52, 0x12, 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x69, - 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, - 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x32, 0xe0, 0x03, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x46, 0x0a, - 0x09, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x62, 0x61, 0x73, - 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x65, 0x12, 0x73, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x2e, + 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x62, 0x61, 0x73, 0x65, + 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x1d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, + 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, + 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x19, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x12, 0x44, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4f, 0x0a, 0x1f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, + 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, - 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x38, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x62, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x48, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x70, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x29, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x19, 0x2e, 0x62, 0x61, 0x73, + 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x12, 0x54, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x10, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, - 0x23, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, - 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x32, 0xd8, 0x07, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x67, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, - 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2b, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, - 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x1d, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x2b, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x62, - 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4f, - 0x0a, 0x1f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x48, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x61, - 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, - 0x64, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x70, 0x0a, 0x17, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x29, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x13, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x73, 0x12, 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x17, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x73, 0x12, 0x19, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, - 0x1e, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x32, - 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x46, 0x0a, 0x05, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2f, 0x76, 0x31, - 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1e, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x32, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x12, 0x46, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x62, 0x61, 0x73, + 0x65, 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x61, 0x73, 0x65, + 0x63, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, + 0x2f, 0x62, 0x61, 0x73, 0x65, 0x63, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x62, + 0x61, 0x73, 0x65, 0x63, 0x61, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4304,6 +4315,7 @@ func file_baseca_v1_api_proto_init() { file_baseca_v1_api_proto_msgTypes[9].OneofWrappers = []interface{}{} file_baseca_v1_api_proto_msgTypes[21].OneofWrappers = []interface{}{} file_baseca_v1_api_proto_msgTypes[25].OneofWrappers = []interface{}{} + file_baseca_v1_api_proto_msgTypes[33].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/go.mod b/go.mod index ea1d2ec..f2f439c 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,6 @@ require ( github.com/casbin/casbin/v2 v2.77.1 github.com/go-redis/redis/v8 v8.11.5 github.com/gogo/status v1.1.1 - github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/lib/pq v1.10.9 @@ -29,6 +28,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/wagslane/go-password-validator v0.3.0 go.uber.org/fx v1.20.0 + go.uber.org/mock v0.3.0 go.uber.org/zap v1.25.0 golang.org/x/crypto v0.12.0 golang.org/x/net v0.14.0 diff --git a/go.sum b/go.sum index 92e8458..7ba5ec0 100644 --- a/go.sum +++ b/go.sum @@ -289,7 +289,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -307,6 +306,8 @@ go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -356,7 +357,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -389,7 +389,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -414,7 +413,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -449,10 +447,8 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -530,7 +526,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/attestor/aws_iid/iid.go b/internal/attestation/aws_iid/iid.go similarity index 100% rename from internal/attestor/aws_iid/iid.go rename to internal/attestation/aws_iid/iid.go diff --git a/internal/attestation/aws_iid/iid_test.go b/internal/attestation/aws_iid/iid_test.go new file mode 100644 index 0000000..262c914 --- /dev/null +++ b/internal/attestation/aws_iid/iid_test.go @@ -0,0 +1,33 @@ +package aws_iid + +import ( + "testing" +) + +func TestIsValidRoleArn(t *testing.T) { + tests := []struct { + name string + arn string + want bool + }{ + { + name: "Valid ARN", + arn: "arn:aws:iam::123456789012:role/Example", + want: true, + }, + { + name: "Invalid ARN", + arn: "invalid:arn:format", + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := isValidRoleArn(tt.arn) + if got != tt.want { + t.Errorf("isValidRoleArn() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/attestor/aws_iid/certificate/ec2.amazonaws.com.crt b/internal/attestor/aws_iid/certificate/ec2.amazonaws.com.crt deleted file mode 100644 index 7e3885b..0000000 --- a/internal/attestor/aws_iid/certificate/ec2.amazonaws.com.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDIjCCAougAwIBAgIJAKnL4UEDMN/FMA0GCSqGSIb3DQEBBQUAMGoxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRgw -FgYDVQQKEw9BbWF6b24uY29tIEluYy4xGjAYBgNVBAMTEWVjMi5hbWF6b25hd3Mu -Y29tMB4XDTE0MDYwNTE0MjgwMloXDTI0MDYwNTE0MjgwMlowajELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxGDAWBgNV -BAoTD0FtYXpvbi5jb20gSW5jLjEaMBgGA1UEAxMRZWMyLmFtYXpvbmF3cy5jb20w -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIe9GN//SRK2knbjySG0ho3yqQM3 -e2TDhWO8D2e8+XZqck754gFSo99AbT2RmXClambI7xsYHZFapbELC4H91ycihvrD -jbST1ZjkLQgga0NE1q43eS68ZeTDccScXQSNivSlzJZS8HJZjgqzBlXjZftjtdJL -XeE4hwvo0sD4f3j9AgMBAAGjgc8wgcwwHQYDVR0OBBYEFCXWzAgVyrbwnFncFFIs -77VBdlE4MIGcBgNVHSMEgZQwgZGAFCXWzAgVyrbwnFncFFIs77VBdlE4oW6kbDBq -MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh -dHRsZTEYMBYGA1UEChMPQW1hem9uLmNvbSBJbmMuMRowGAYDVQQDExFlYzIuYW1h -em9uYXdzLmNvbYIJAKnL4UEDMN/FMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADgYEAFYcz1OgEhQBXIwIdsgCOS8vEtiJYF+j9uO6jz7VOmJqO+pRlAbRlvY8T -C1haGgSI/A1uZUKs/Zfnph0oEI0/hu1IIJ/SKBDtN5lvmZ/IzbOPIJWirlsllQIQ -7zvWbGd9c9+Rm3p04oTvhup99la7kZqevJK0QRdD/6NpCKsqP/0= ------END CERTIFICATE----- \ No newline at end of file diff --git a/internal/authentication/payload.go b/internal/authentication/payload.go deleted file mode 100644 index caa54a7..0000000 --- a/internal/authentication/payload.go +++ /dev/null @@ -1,38 +0,0 @@ -package authentication - -import ( - "errors" - - "github.com/google/uuid" -) - -var ( - ErrExpiredToken = errors.New("token has expired") - ErrInvalidToken = errors.New("token is invalid") -) - -type ServicePayload struct { - ServiceID uuid.UUID `json:"service_id"` - ServiceAccount string `json:"service_account"` - Environment string `json:"environment"` - ValidSubjectAlternateName []string `json:"subject_alternate_name"` - ValidCertificateAuthorities []string `json:"certificate_authorities"` - CertificateValidity int16 `json:"certificate_validity"` - SubordinateCa string `json:"subordinate_ca"` - ExtendedKey string `json:"certificate_request_extension"` - SANRegularExpression string `json:"regular_expression"` -} - -type ProvisionerAccountPayload struct { - ClientId uuid.UUID `json:"client_id"` - ProvisionerAccount string `json:"provisioner_account"` - Environments []string `json:"environments"` - ValidSubjectAlternateNames []string `json:"subject_alternate_names"` - MaxCertificateValidity uint32 `json:"max_certificate_validity"` - ExtendedKeys []string `json:"certificate_request_extension"` - RegularExpression string `json:"regular_expression"` -} - -type EnrollmentPayload struct { - SerialNumber string `json:"serial_number"` -} diff --git a/internal/authorization/permission.go b/internal/authorization/permission.go deleted file mode 100644 index e517628..0000000 --- a/internal/authorization/permission.go +++ /dev/null @@ -1,16 +0,0 @@ -package authorization - -const ( - ADMIN = "ADMIN" - PRIVILEGED = "PRIVILEGED" - READ = "READ" -) - -func IsSupportedPermission(permission string) bool { - switch permission { - case ADMIN, PRIVILEGED, READ: - return true - } - - return false -} diff --git a/internal/client/acmpca/client.go b/internal/client/acmpca/client.go index 23fbbe9..74c5a81 100644 --- a/internal/client/acmpca/client.go +++ b/internal/client/acmpca/client.go @@ -1,4 +1,4 @@ -package acm_pca +package acmpca import ( "context" diff --git a/internal/client/acmpca/issue.go b/internal/client/acmpca/issue.go index ef2da58..34512f9 100644 --- a/internal/client/acmpca/issue.go +++ b/internal/client/acmpca/issue.go @@ -1,4 +1,4 @@ -package acm_pca +package acmpca import ( "context" diff --git a/internal/client/acmpca/query.go b/internal/client/acmpca/query.go index 7ea2770..58cb5d3 100644 --- a/internal/client/acmpca/query.go +++ b/internal/client/acmpca/query.go @@ -1,4 +1,4 @@ -package acm_pca +package acmpca import ( "context" diff --git a/internal/client/acmpca/revoke.go b/internal/client/acmpca/revoke.go index 62898f2..119e0eb 100644 --- a/internal/client/acmpca/revoke.go +++ b/internal/client/acmpca/revoke.go @@ -1,4 +1,4 @@ -package acm_pca +package acmpca import ( "context" diff --git a/internal/config/config.go b/internal/config/config.go index 2b19e21..181f7e5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,6 +7,7 @@ type SubordinateCertificate struct { AssumeRole bool `mapstructure:"assume_role"` RoleArn string `mapstructure:"role_arn"` RootCa bool `mapstructure:"root_ca"` + Default bool `mapstructure:"default"` } type SubordinateCertificateAuthority struct { @@ -59,7 +60,7 @@ type SecretsManagerConfig struct { Region string `mapstructure:"region"` } -type Environment struct { +type Stage struct { Local []string `mapstructure:"local"` Sandbox []string `mapstructure:"sandbox"` Development []string `mapstructure:"development"` @@ -80,5 +81,5 @@ type Config struct { ACMPCA map[string]SubordinateCertificate `mapstructure:"acm_pca"` SecretsManager SecretsManagerConfig `mapstructure:"secrets_manager"` SubordinateMetadata SubordinateCertificateAuthority `mapstructure:"subordinate_ca_metadata"` - Environment Environment `mapstructure:"certificate_authority"` + Environment Stage `mapstructure:"certificate_authority"` } diff --git a/internal/environment/environment.go b/internal/config/environment.go similarity index 97% rename from internal/environment/environment.go rename to internal/config/environment.go index bba1fd9..30297a5 100644 --- a/internal/environment/environment.go +++ b/internal/config/environment.go @@ -1,4 +1,4 @@ -package environment +package config import ( "os" diff --git a/internal/config/fx.go b/internal/config/fx.go index b74f221..f773335 100644 --- a/internal/config/fx.go +++ b/internal/config/fx.go @@ -3,7 +3,6 @@ package config import ( "log" - "github.com/coinbase/baseca/internal/environment" "github.com/coinbase/baseca/internal/logger" "go.uber.org/fx" ) @@ -12,6 +11,7 @@ var Module = fx.Options( fx.Provide( ProvideConfigPathResolver, ProvideConfig, + ProvideEnvironment, ), ) @@ -20,7 +20,7 @@ var Configuration *Config type Parameter struct { fx.In - Environment environment.Environment + Environment Environment PathResolver ConfigFilePathResolver } @@ -32,7 +32,7 @@ type Result struct { } type ConfigProvider interface { - Get(path string, cfg interface{}) error + Get(path string, cfg any) error Exists(path string) bool } diff --git a/internal/config/load.go b/internal/config/load.go index 6758225..338df25 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -18,7 +18,7 @@ var _ ConfigProvider = (*configProvider)(nil) func BuildViper(path string) (*viper.Viper, error) { ctxLogger := logger.ContextLogger{Logger: logger.DefaultLogger} - ctxLogger.Info("Setting up Viper to load configuration", zap.String("config-path", path)) + ctxLogger.Info("setting up Viper to load configuration", zap.String("config-path", path)) v := viper.New() v.SetConfigFile(path) @@ -33,12 +33,12 @@ func BuildViper(path string) (*viper.Viper, error) { func LoadConfig(viper *viper.Viper) (*Config, error) { if viper == nil { - return nil, errors.New("Failed to load config.") + return nil, errors.New("failed to load config") } c := Config{} if err := viper.Unmarshal(&c); err != nil { - return nil, errors.New("Failed to read configuration file.") + return nil, errors.New("failed to read configuration file") } return &c, nil } @@ -47,9 +47,9 @@ func NewConfigProviderFromViper(v *viper.Viper) ConfigProvider { return &configProvider{v: v} } -func (cp *configProvider) Get(path string, cfg interface{}) error { +func (cp *configProvider) Get(path string, cfg any) error { if !cp.Exists(path) { - return fmt.Errorf("Path %s is not found in configuration.", path) + return fmt.Errorf("path %s is not found in configuration", path) } if err := cp.v.UnmarshalKey(path, cfg, func(setting *mapstructure.DecoderConfig) { diff --git a/internal/config/path.go b/internal/config/path.go index 03c0420..f06f311 100644 --- a/internal/config/path.go +++ b/internal/config/path.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/coinbase/baseca/internal/environment" ) const ( @@ -16,11 +15,11 @@ type ConfigFilePathResolver interface { } type Resolver struct { - Environment environment.Environment + Environment Environment Template string } -func ProvideConfigPathResolver(e environment.Environment) ConfigFilePathResolver { +func ProvideConfigPathResolver(e Environment) ConfigFilePathResolver { return &Resolver{Environment: e, Template: _template} } @@ -29,6 +28,7 @@ var _ ConfigFilePathResolver = (*Resolver)(nil) func (r Resolver) Resolve() (string, error) { configurationFileName := configurationFileName(r.Environment) location := fmt.Sprintf(r.Template, configurationFileName) + path, err := bazel.Runfile(location) if err != nil { return "", fmt.Errorf(location) @@ -36,6 +36,6 @@ func (r Resolver) Resolve() (string, error) { return path, nil } -func configurationFileName(e environment.Environment) string { +func configurationFileName(e Environment) string { return fmt.Sprintf("%s.%s.%s", e.Configuration, e.Stage, e.Provider) } diff --git a/internal/environment/fx.go b/internal/environment/fx.go deleted file mode 100644 index 73f0a6c..0000000 --- a/internal/environment/fx.go +++ /dev/null @@ -1,11 +0,0 @@ -package environment - -import ( - "go.uber.org/fx" -) - -var Module = fx.Options( - fx.Provide( - ProvideEnvironment, - ), -) diff --git a/internal/gateway/grpc/fx.go b/internal/gateway/fx.go similarity index 67% rename from internal/gateway/grpc/fx.go rename to internal/gateway/fx.go index eb5524f..a063b0c 100644 --- a/internal/gateway/grpc/fx.go +++ b/internal/gateway/fx.go @@ -1,4 +1,4 @@ -package grpc +package gateway import ( "context" @@ -6,16 +6,21 @@ import ( "fmt" "log" "net" + "time" + "github.com/allegro/bigcache/v3" "github.com/casbin/casbin/v2" - apiservice "github.com/coinbase/baseca/cmd/server/baseca" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" "github.com/coinbase/baseca/internal/client/secretsmanager" "github.com/coinbase/baseca/internal/config" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/coinbase/baseca/internal/logger" + "github.com/coinbase/baseca/internal/v1/accounts" "github.com/coinbase/baseca/internal/v1/certificate" "github.com/coinbase/baseca/internal/v1/health" + "github.com/coinbase/baseca/internal/v1/middleware" + "github.com/coinbase/baseca/internal/v1/users" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "go.uber.org/fx" "go.uber.org/zap" @@ -26,9 +31,20 @@ import ( ) const ( - authorization_path = "internal/authorization/casbin" + _authorization_path = "config/permissions" + _default_cleanup = 10 * time.Minute ) +type Server struct { + apiv1.CertificateServer + Store db.DatabaseEndpoints + Auth lib.Auth + Service *accounts.Service + Certificate *certificate.Certificate + User *users.User + Middleware *middleware.Middleware +} + var Module = fx.Options( fx.Invoke(StartRPC), ) @@ -62,8 +78,8 @@ func StartRPC(lc fx.Lifecycle, cfg *config.Config) error { log.Fatalf("cannot connect to the database: %s", err) } - authorization_model := fmt.Sprintf("%s/model.conf", authorization_path) - authorization_policy := fmt.Sprintf("%s/policy.csv", authorization_path) + authorization_model := fmt.Sprintf("%s/model.conf", _authorization_path) + authorization_policy := fmt.Sprintf("%s/policy.csv", _authorization_path) enforcer, _ := casbin.NewEnforcer(authorization_model, authorization_policy) writer_endpoint := db.BuildDatastore(database_endpoint) @@ -71,12 +87,12 @@ func StartRPC(lc fx.Lifecycle, cfg *config.Config) error { db := db.DatabaseEndpoints{Writer: writer_endpoint, Reader: reader_endpoint} // RPC Server - server, err := apiservice.BuildServer(db, cfg, enforcer) + server, err := BuildServer(db, cfg, enforcer) if err != nil { log.Fatal("cannot Start grpc server", err) } - extractor := func(resp interface{}, err error, code codes.Code) string { + extractor := func(resp any, err error, code codes.Code) string { if err != nil { if customErr, ok := err.(*logger.Error); ok && customErr.InternalError != nil { return customErr.InternalError.Error() @@ -94,7 +110,7 @@ func StartRPC(lc fx.Lifecycle, cfg *config.Config) error { // RPC Middleware Logger logInterceptor := logger.RpcLogger(extractor) - interceptors := grpc_middleware.ChainUnaryServer(logInterceptor, server.Middleware.ServerAuthenticationInterceptor) + interceptors := grpc_middleware.ChainUnaryServer(server.Middleware.ServerAuthenticationInterceptor, logInterceptor) grpcServer = grpc.NewServer(grpc.UnaryInterceptor(interceptors)) // Service Registration @@ -138,13 +154,49 @@ func StartRPC(lc fx.Lifecycle, cfg *config.Config) error { return nil } +func BuildServer(store db.DatabaseEndpoints, cfg *config.Config, enforcer *casbin.Enforcer) (*Server, error) { + signer, err := lib.BuildSigningClient(cfg) + if err != nil { + return nil, err + } + + auth, err := lib.NewAuthSigningMetadata(signer) + if err != nil { + return nil, err + } + + cache, err := bigcache.New(context.Background(), bigcache.DefaultConfig(_default_cleanup)) + if err != nil { + return nil, fmt.Errorf("error instantiating memory cache") + } + + service := accounts.New(cfg, store) + user := users.New(cfg, store, auth) + middleware := middleware.New(auth, store, enforcer, cache) + certificate, err := certificate.New(cfg, store) + if err != nil { + return nil, fmt.Errorf("issue instantiating certificate client [%s]", err) + } + + server := &Server{ + Store: store, + Auth: auth, + Service: service, + Certificate: certificate, + User: user, + Middleware: middleware, + } + + return server, nil +} + func GetPgConn(conf config.DatabaseConfig, endpoint, credentials string) (*sql.DB, error) { dataSource := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", endpoint, conf.Port, conf.User, credentials, conf.Table) if conf.SSLMode == "disable" { dataSource = fmt.Sprintf("%s sslmode=disable", dataSource) } else { - dataSource = fmt.Sprintf("%s sslmode=verify-full sslrootcert=internal/attestor/aws_iid/certificate/rds.global.bundle.pem", dataSource) + dataSource = fmt.Sprintf("%s sslmode=verify-full sslrootcert=config/certificate_authority/rds.global.bundle.pem", dataSource) } // Open Database Connection diff --git a/internal/authentication/authentication.go b/internal/lib/authentication/credentials.go similarity index 97% rename from internal/authentication/authentication.go rename to internal/lib/authentication/credentials.go index 55f0f6d..4d80d5c 100644 --- a/internal/authentication/authentication.go +++ b/internal/lib/authentication/credentials.go @@ -1,4 +1,4 @@ -package authentication +package lib import ( "crypto/rand" diff --git a/internal/authentication/issuer.go b/internal/lib/authentication/issuer.go similarity index 98% rename from internal/authentication/issuer.go rename to internal/lib/authentication/issuer.go index 1f9e37e..d5075ee 100644 --- a/internal/authentication/issuer.go +++ b/internal/lib/authentication/issuer.go @@ -1,9 +1,10 @@ -package authentication +package lib import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "strings" "time" @@ -220,11 +221,11 @@ func (s *signer) Verify(ctx context.Context, jwt string) (*Claims, error) { func (c *Claims) Valid() error { if time.Now().UTC().After(c.ExpiresAt) { - return ErrExpiredToken + return errors.New("token has expired") } if time.Now().UTC().Before(c.NotBefore) { - return ErrInvalidToken + return errors.New("token is invalid") } return nil } diff --git a/internal/lib/crypto/csr.go b/internal/lib/crypto/csr.go new file mode 100644 index 0000000..a81fe61 --- /dev/null +++ b/internal/lib/crypto/csr.go @@ -0,0 +1,99 @@ +package crypto + +import ( + "bytes" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + + "github.com/coinbase/baseca/internal/types" +) + +func GenerateCSR(csr types.CertificateRequest) (*types.SigningRequest, error) { + var generator CSRGenerator + + switch csr.PublicKeyAlgorithm { + case x509.RSA: + if _, ok := types.PublicKeyAlgorithms["RSA"].KeySize[csr.KeySize]; !ok { + return nil, fmt.Errorf("rsa invalid key size %d", csr.KeySize) + } + if _, ok := types.PublicKeyAlgorithms["RSA"].SigningAlgorithm[csr.SigningAlgorithm]; !ok { + return nil, fmt.Errorf("rsa invalid signing algorithm %s", csr.SigningAlgorithm) + } + generator = &SigningRequestGeneratorRSA{Size: csr.KeySize} + case x509.ECDSA: + if _, ok := types.PublicKeyAlgorithms["ECDSA"].KeySize[csr.KeySize]; !ok { + return nil, fmt.Errorf("ecdsa invalid key size %d", csr.KeySize) + } + if _, ok := types.PublicKeyAlgorithms["ECDSA"].SigningAlgorithm[csr.SigningAlgorithm]; !ok { + return nil, fmt.Errorf("ecdsa invalid signing algorithm %s", csr.SigningAlgorithm) + } + generator = &SigningRequestGeneratorECDSA{Curve: csr.KeySize} + default: + return nil, fmt.Errorf("unsupported public key algorithm") + } + + pk, err := generator.Generate() + if err != nil { + return nil, fmt.Errorf("error generating private key [%s]: %w", generator.KeyType(), err) + } + + subject := pkix.Name{ + CommonName: csr.CommonName, + Country: csr.DistinguishedName.Country, + Province: csr.DistinguishedName.Province, + Locality: csr.DistinguishedName.Locality, + Organization: csr.DistinguishedName.Organization, + OrganizationalUnit: csr.DistinguishedName.OrganizationalUnit, + } + + template := x509.CertificateRequest{ + Subject: subject, + SignatureAlgorithm: csr.SigningAlgorithm, + DNSNames: csr.SubjectAlternateNames, + } + + csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, pk) + if err != nil { + return nil, fmt.Errorf("error creating certificate request: %w", err) + } + + certificatePem := new(bytes.Buffer) + err = pem.Encode(certificatePem, &pem.Block{ + Type: "CERTIFICATE REQUEST", + Bytes: csrBytes, + }) + + if err != nil { + return nil, fmt.Errorf("error encoding certificate request (csr): %w", err) + } + + if len(csr.Output.CertificateSigningRequest) != 0 { + if err := writeFileToSystem(csr.Output.CertificateSigningRequest, certificatePem.Bytes()); err != nil { + return nil, fmt.Errorf("error writing certificate signing request (csr) to [%s]: %w", csr.Output.CertificateSigningRequest, err) + } + } + + pkBytes, err := generator.MarshalPrivateKey(pk) + if err != nil { + return nil, fmt.Errorf("error marshaling private key: %w", err) + } + + pkBlock := &pem.Block{ + Type: generator.KeyType(), + Bytes: pkBytes, + } + + if len(csr.Output.PrivateKey) != 0 { + if err := writeFileToSystem(csr.Output.PrivateKey, pem.EncodeToMemory(pkBlock)); err != nil { + return nil, fmt.Errorf("error writing private key to [%s]: %w", csr.Output.PrivateKey, err) + } + } + + return &types.SigningRequest{ + CSR: certificatePem, + PrivateKey: pkBlock, + }, nil +} diff --git a/internal/lib/crypto/csr_test.go b/internal/lib/crypto/csr_test.go new file mode 100644 index 0000000..9673887 --- /dev/null +++ b/internal/lib/crypto/csr_test.go @@ -0,0 +1,61 @@ +package crypto + +import ( + "crypto/x509" + "encoding/pem" + "testing" + + "github.com/coinbase/baseca/internal/types" + "github.com/stretchr/testify/assert" +) + +func TestGenerateCSR(t *testing.T) { + csr := types.CertificateRequest{ + PublicKeyAlgorithm: x509.RSA, + KeySize: 2048, + SigningAlgorithm: x509.SHA256WithRSA, + CommonName: "example.com", + DistinguishedName: types.DistinguishedName{ + Country: []string{"US"}, + Province: []string{"CA"}, + }, + SubjectAlternateNames: []string{"www.example.com", "sub.example.com"}, + Output: types.Output{ + CertificateSigningRequest: "/tmp/unit_test_csr.pem", + PrivateKey: "/tmp/unit_test_pk.pem", + }, + } + + // Generate CSR with RSA Key Pair + rsaSigningRequest, err := GenerateCSR(csr) + assert.NoError(t, err) + assert.NotNil(t, rsaSigningRequest) + + assert.Contains(t, string(rsaSigningRequest.CSR.String()), "CERTIFICATE REQUEST") + assert.Contains(t, string(pem.EncodeToMemory(rsaSigningRequest.PrivateKey)), "RSA PRIVATE KEY") + + // Create an ECDSA CertificateRequest + ecdsaCsr := types.CertificateRequest{ + PublicKeyAlgorithm: x509.ECDSA, + KeySize: 256, + SigningAlgorithm: x509.ECDSAWithSHA512, + CommonName: "example.com", + DistinguishedName: types.DistinguishedName{ + Country: []string{"US"}, + Province: []string{"CA"}, + }, + SubjectAlternateNames: []string{"www.example.com", "sub.example.com"}, + Output: types.Output{ + CertificateSigningRequest: "/tmp/unit_test_csr.pem", + PrivateKey: "/tmp/unit_test_pk.pem", + }, + } + + // Generate the CSR with ECDSA Key Pair + ecdsaSigningRequest, err := GenerateCSR(ecdsaCsr) + assert.NoError(t, err) + assert.NotNil(t, ecdsaSigningRequest) + + assert.Contains(t, string(ecdsaSigningRequest.CSR.String()), "CERTIFICATE REQUEST") + assert.Contains(t, string(pem.EncodeToMemory(ecdsaSigningRequest.PrivateKey)), "EC PRIVATE KEY") +} diff --git a/internal/lib/crypto/generate.go b/internal/lib/crypto/generate.go new file mode 100644 index 0000000..f6c4d79 --- /dev/null +++ b/internal/lib/crypto/generate.go @@ -0,0 +1,95 @@ +package crypto + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "fmt" + + "github.com/coinbase/baseca/internal/types" +) + +type CSRGenerator interface { + Generate() (crypto.PrivateKey, error) + KeyType() string + MarshalPrivateKey(key crypto.PrivateKey) ([]byte, error) + SupportsPublicKeyAlgorithm(algorithm x509.PublicKeyAlgorithm) bool + SupportsSigningAlgorithm(algorithm x509.SignatureAlgorithm) bool + SupportsKeySize(size int) bool +} + +type SigningRequestGeneratorRSA struct { + Size int +} + +type SigningRequestGeneratorECDSA struct { + Curve int +} + +// RSA Interface +func (r *SigningRequestGeneratorRSA) Generate() (crypto.PrivateKey, error) { + return rsa.GenerateKey(rand.Reader, r.Size) +} + +func (r *SigningRequestGeneratorRSA) KeyType() string { + return "RSA PRIVATE KEY" +} + +func (r *SigningRequestGeneratorRSA) MarshalPrivateKey(key crypto.PrivateKey) ([]byte, error) { + return x509.MarshalPKCS1PrivateKey(key.(*rsa.PrivateKey)), nil +} + +func (r *SigningRequestGeneratorRSA) SupportsPublicKeyAlgorithm(algorithm x509.PublicKeyAlgorithm) bool { + return algorithm == x509.RSA +} + +func (r *SigningRequestGeneratorRSA) SupportsSigningAlgorithm(algorithm x509.SignatureAlgorithm) bool { + _, ok := types.PublicKeyAlgorithms["RSA"].SigningAlgorithm[algorithm] + return ok +} + +func (r *SigningRequestGeneratorRSA) SupportsKeySize(size int) bool { + _, ok := types.PublicKeyAlgorithms["RSA"].KeySize[size] + return ok +} + +// ECDSA Interface +func (e *SigningRequestGeneratorECDSA) Generate() (crypto.PrivateKey, error) { + c, ok := types.PublicKeyAlgorithms["ECDSA"].KeySize[e.Curve] + + if !ok { + return nil, fmt.Errorf("ecdsa curve [%d] not supported", e.Curve) + } + + curve, ok := c.(elliptic.Curve) + if !ok { + return nil, fmt.Errorf("invalid elliptic.Curve type") + } + + return ecdsa.GenerateKey(curve, rand.Reader) +} + +func (e *SigningRequestGeneratorECDSA) KeyType() string { + return "EC PRIVATE KEY" +} + +func (e *SigningRequestGeneratorECDSA) MarshalPrivateKey(key crypto.PrivateKey) ([]byte, error) { + return x509.MarshalECPrivateKey(key.(*ecdsa.PrivateKey)) +} + +func (e *SigningRequestGeneratorECDSA) SupportsPublicKeyAlgorithm(algorithm x509.PublicKeyAlgorithm) bool { + return algorithm == x509.ECDSA +} + +func (e *SigningRequestGeneratorECDSA) SupportsSigningAlgorithm(algorithm x509.SignatureAlgorithm) bool { + _, ok := types.PublicKeyAlgorithms["ECDSA"].SigningAlgorithm[algorithm] + return ok +} + +func (e *SigningRequestGeneratorECDSA) SupportsKeySize(size int) bool { + _, ok := types.PublicKeyAlgorithms["ECDSA"].KeySize[size] + return ok +} diff --git a/internal/lib/crypto/generate_test.go b/internal/lib/crypto/generate_test.go new file mode 100644 index 0000000..d89bfd0 --- /dev/null +++ b/internal/lib/crypto/generate_test.go @@ -0,0 +1,71 @@ +package crypto + +import ( + "crypto/x509" + "testing" +) + +func TestSigningRequestGeneratorRSA(t *testing.T) { + r := &SigningRequestGeneratorRSA{ + Size: 2048, + } + + key, err := r.Generate() + if err != nil { + t.Fatalf("error generating rsa private key: %v", err) + } + + if keyType := r.KeyType(); keyType != "RSA PRIVATE KEY" { + t.Errorf("RSA PRIVATE KEY does not exist within private key") + + } + + if !r.SupportsPublicKeyAlgorithm(x509.RSA) { + t.Errorf("rsa public key algorithm not supported") + } + + if !r.SupportsSigningAlgorithm(x509.SHA256WithRSA) { + t.Errorf("SHA256WithRSA signing algorithm not supported") + } + + if !r.SupportsKeySize(2048) { + t.Errorf("rsa key size not supported") + } + + _, err = r.MarshalPrivateKey(key) + if err != nil { + t.Errorf("error marshaling rsa private key: %v", err) + } +} + +func TestSigningRequestGeneratorECDSA(t *testing.T) { + e := &SigningRequestGeneratorECDSA{ + Curve: 256, + } + + key, err := e.Generate() + if err != nil { + t.Fatalf("error generating ecdsa private key: %v", err) + } + + if keyType := e.KeyType(); keyType != "EC PRIVATE KEY" { + t.Errorf("EC PRIVATE KEY does not exist within private key") + } + + if !e.SupportsPublicKeyAlgorithm(x509.ECDSA) { + t.Errorf("ecdsa public key algorithm not supported") + } + + if !e.SupportsSigningAlgorithm(x509.ECDSAWithSHA256) { + t.Errorf("ECDSAWithSHA256 signing algorithm not supported") + } + + if !e.SupportsKeySize(256) { + t.Errorf("ecdsa curve size not supported") + } + + _, err = e.MarshalPrivateKey(key) + if err != nil { + t.Errorf("error marshaling ecdsa private key: %v", err) + } +} diff --git a/internal/lib/crypto/pk.go b/internal/lib/crypto/pk.go index 15be4a6..5c2f4f9 100644 --- a/internal/lib/crypto/pk.go +++ b/internal/lib/crypto/pk.go @@ -1,13 +1,11 @@ package crypto import ( - "bytes" "crypto" "crypto/ecdsa" "crypto/rand" "crypto/rsa" "crypto/x509" - "crypto/x509/pkix" "encoding/pem" "errors" "fmt" @@ -28,7 +26,7 @@ type ECDSA struct { PrivateKey *ecdsa.PrivateKey } -func (key *RSA) KeyPair() interface{} { +func (key *RSA) KeyPair() any { return key } @@ -39,7 +37,7 @@ func (key *RSA) Sign(data []byte) ([]byte, error) { return rsa.SignPKCS1v15(rand.Reader, key.PrivateKey, crypto.SHA256, hashed) } -func (key *ECDSA) KeyPair() interface{} { +func (key *ECDSA) KeyPair() any { return key } @@ -55,7 +53,7 @@ func (key *ECDSA) Sign(data []byte) ([]byte, error) { return signature, nil } -func ReturnPrivateKey(key types.AsymmetricKey) (interface{}, error) { +func ReturnPrivateKey(key types.AsymmetricKey) (any, error) { switch k := key.KeyPair().(type) { case *RSA: return k.PrivateKey, nil @@ -66,78 +64,6 @@ func ReturnPrivateKey(key types.AsymmetricKey) (interface{}, error) { } } -func GenerateCSR(csr types.CertificateRequest) (*types.SigningRequest, error) { - switch csr.PublicKeyAlgorithm { - case x509.RSA: - if csr.KeySize < 2048 { - return nil, errors.New("invalid key size, rsa minimum valid bits 2048]") - } - // TODO: ECDSA - } - - subject := pkix.Name{ - CommonName: csr.CommonName, - Country: csr.DistinguishedName.Country, - Province: csr.DistinguishedName.Province, - Locality: csr.DistinguishedName.Locality, - Organization: csr.DistinguishedName.Organization, - OrganizationalUnit: csr.DistinguishedName.OrganizationalUnit, - } - - template := x509.CertificateRequest{ - Subject: subject, - SignatureAlgorithm: csr.SigningAlgorithm, - DNSNames: csr.SubjectAlternateNames, - } - - switch csr.SigningAlgorithm { - case x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - pk, err := rsa.GenerateKey(rand.Reader, csr.KeySize) - if err != nil { - return nil, errors.New("error generating rsa key pair") - } - - csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, pk) - if err != nil { - return nil, err - } - - certificatePem := new(bytes.Buffer) - err = pem.Encode(certificatePem, &pem.Block{ - Type: "CERTIFICATE REQUEST", - Bytes: csrBytes, - }) - - if err != nil { - return nil, errors.New("error encoding certificate request (csr)") - } - - if len(csr.Output.CertificateSigningRequest) != 0 { - if err := os.WriteFile(csr.Output.CertificateSigningRequest, certificatePem.Bytes(), os.ModePerm); err != nil { - return nil, fmt.Errorf("error writing certificate signing request (csr) to [%s]", csr.Output.CertificateSigningRequest) - } - } - - pkBlock := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(pk), - } - - if len(csr.Output.PrivateKey) != 0 { - if err := os.WriteFile(csr.Output.PrivateKey, pem.EncodeToMemory(pkBlock), os.ModePerm); err != nil { - return nil, fmt.Errorf("error writing private key to [%s]", csr.Output.PrivateKey) - } - } - - return &types.SigningRequest{ - CSR: certificatePem, - PrivateKey: pkBlock, - }, nil - default: - return nil, errors.New("unsupported signing algorithm") - } -} - func GetSubordinateCaParameters(service string) (*types.CertificateAuthority, error) { subordinatePath := filepath.Join(types.SubordinatePath, service+_subordinateCertificate) subordinate, err := readFileFromSystem(subordinatePath) diff --git a/internal/lib/util/backoff.go b/internal/lib/util/backoff.go index 0a39c58..c257a5c 100644 --- a/internal/lib/util/backoff.go +++ b/internal/lib/util/backoff.go @@ -29,7 +29,7 @@ func LockfileBackoff(lockfilePath string) error { } time.Sleep(backoff) } - return errors.New(ERROR_LOCKFILE_PRESENT) + return errors.New("subordinate ca lockfile present") } return nil } diff --git a/internal/lib/util/errors.go b/internal/lib/util/errors.go deleted file mode 100644 index 3fbd746..0000000 --- a/internal/lib/util/errors.go +++ /dev/null @@ -1,11 +0,0 @@ -package util - -const ( - ERROR_HASHING_CREDENTIALS = "error hashing user credentials" // #nosec G101 False Positive - ERROR_CREATE_TOKEN = "error creating auth token" - ERROR_LOCKFILE_PRESENT = "subordinate ca lockfile present" - INVALID_SERIAL_NUMBER = "invalid serial number for enrollment" - ERROR_ENROLLING_DEVICE = "error enrolling device serial number" - MALFORMATTED_REQUEST = "malformatted request parameters" - UNAUTHORIZED_REQUEST = "unauthorized request" -) diff --git a/internal/lib/util/random.go b/internal/lib/util/random.go index 77363aa..2f4509c 100644 --- a/internal/lib/util/random.go +++ b/internal/lib/util/random.go @@ -9,14 +9,14 @@ import ( "time" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/google/uuid" ) func GenerateTestUser(t *testing.T, permissions string, length int) (db.User, string) { client_id, _ := uuid.NewRandom() credentials := generateRandomCredentials(length) - hashed_credentials, _ := authentication.HashPassword(credentials) + hashed_credentials, _ := lib.HashPassword(credentials) email := generateRandomEmail() username := generateRandomUsername() full_name := generateRandomName() diff --git a/internal/validator/domain.go b/internal/lib/util/validator/domain.go similarity index 76% rename from internal/validator/domain.go rename to internal/lib/util/validator/domain.go index a151a0f..6d76369 100644 --- a/internal/validator/domain.go +++ b/internal/lib/util/validator/domain.go @@ -56,24 +56,3 @@ func SupportedConfig(cfg *config.Config) { valid_certificate_authorities = append(valid_certificate_authorities, certificate_authority) } } - -func Contains(s []string, str string) bool { - for _, v := range s { - if v == str { - return true - } - } - return false -} - -func SanitizeInput(input []string) []string { - allKeys := make(map[string]bool) - list := []string{} - for _, item := range input { - if _, value := allKeys[item]; !value { - allKeys[item] = true - list = append(list, item) - } - } - return list -} diff --git a/internal/lib/util/validator/domain_test.go b/internal/lib/util/validator/domain_test.go new file mode 100644 index 0000000..1263ebf --- /dev/null +++ b/internal/lib/util/validator/domain_test.go @@ -0,0 +1,67 @@ +package validator + +import ( + "testing" + + "github.com/coinbase/baseca/internal/config" +) + +func TestIsValidateDomain(t *testing.T) { + valid_domains = []string{"coinbase.com"} + + tests := []struct { + name string + domain string + want bool + }{ + {"Valid Domain", "www.coinbase.com", true}, + {"Invalid Domain", "www.invalid.com", false}, + {"Valid IP Address", "192.168.1.1", true}, + {"Invalid String", "coinbase", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsValidDomain(tt.domain); got != tt.want { + t.Errorf("IsValidateDomain() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsSupportedCertificateAuthority(t *testing.T) { + // Setup + valid_certificate_authorities = []string{"certificate_authority_1", "certificate_authority_2"} + + if !IsSupportedCertificateAuthority("certificate_authority_1") { + t.Error("Expected certificate_authority_1 to be supported") + } + + if IsSupportedCertificateAuthority("certificate_authority_3") { + t.Error("Expected certificate_authority_3 not to be supported") + } +} + +func TestSupportedConfig(t *testing.T) { + cfg := &config.Config{ + Domains: []string{"domain1.com", "domain2.com"}, + ACMPCA: map[string]config.SubordinateCertificate{ + "certificate_authority_1": { + Region: "us-west-1", + }, + "certificate_authority_2": { + Region: "us-east-1", + }, + }, + } + + SupportedConfig(cfg) + + if !Contains(valid_domains, "domain1.com") { + t.Error("Expected domain1.com to be in valid_domains") + } + + if !Contains(valid_certificate_authorities, "certificate_authority_1") { + t.Error("Expected certificate_authority_1 to be in valid_certificate_authorities") + } +} diff --git a/internal/validator/environment.go b/internal/lib/util/validator/environment.go similarity index 100% rename from internal/validator/environment.go rename to internal/lib/util/validator/environment.go diff --git a/internal/lib/util/validator/environment_test.go b/internal/lib/util/validator/environment_test.go new file mode 100644 index 0000000..f04f93f --- /dev/null +++ b/internal/lib/util/validator/environment_test.go @@ -0,0 +1,45 @@ +package validator + +import ( + "testing" + + "github.com/coinbase/baseca/internal/config" + "github.com/coinbase/baseca/internal/types" +) + +func TestSupportedEnvironments(t *testing.T) { + cfg := &config.Config{ + Environment: config.Stage{ + Local: []string{"localhost"}, + }, + } + + SupportedEnvironments(cfg) + + if len(CertificateAuthorityEnvironments["local"]) == 0 { + t.Errorf("Expected non-empty local environments, got none") + } +} + +func TestSetBaseDirectory(t *testing.T) { + // When BaseDirectory is provided + cfg := &config.Config{ + SubordinateMetadata: config.SubordinateCertificateAuthority{ + BaseDirectory: "/some/dir", + }, + } + + SetBaseDirectory(cfg) + + if types.SubordinatePath != "/some/dir" { + t.Errorf("Expected SubordinatePath to be set to '/some/dir', got: %s", types.SubordinatePath) + } + + cfg.SubordinateMetadata.BaseDirectory = "" + + SetBaseDirectory(cfg) + + if types.SubordinatePath != BaseDirectory { + t.Errorf("Expected SubordinatePath to be set to BaseDirectory, got: %s", types.SubordinatePath) + } +} diff --git a/internal/validator/fx.go b/internal/lib/util/validator/fx.go similarity index 100% rename from internal/validator/fx.go rename to internal/lib/util/validator/fx.go diff --git a/internal/lib/util/validator/permission.go b/internal/lib/util/validator/permission.go new file mode 100644 index 0000000..7f6e3bc --- /dev/null +++ b/internal/lib/util/validator/permission.go @@ -0,0 +1,12 @@ +package validator + +import "github.com/coinbase/baseca/internal/types" + +func IsSupportedPermission(permission string) bool { + switch permission { + case types.ADMIN, types.PRIVILEGED, types.READ: + return true + } + + return false +} diff --git a/internal/validator/validate.go b/internal/lib/util/validator/validate.go similarity index 69% rename from internal/validator/validate.go rename to internal/lib/util/validator/validate.go index 655d235..1d5d18a 100644 --- a/internal/validator/validate.go +++ b/internal/lib/util/validator/validate.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "regexp" + "testing" "unicode" "github.com/coinbase/baseca/internal/config" @@ -13,7 +14,7 @@ import ( type NullString sql.NullString -func ValidateCertificateAuthorityEnvironment(config config.Environment, environment string, certificate_authorities []string) bool { +func ValidateCertificateAuthorityEnvironment(config config.Stage, environment string, certificate_authorities []string) bool { if len(certificate_authorities) == 0 { return false } @@ -94,7 +95,7 @@ func ConvertNullRawMessageToMap(nrm pqtype.NullRawMessage) (map[string]string, e return nil, nil } - var m map[string]interface{} + var m map[string]any err := json.Unmarshal(nrm.RawMessage, &m) if err != nil { return nil, err @@ -119,3 +120,48 @@ func ValidateInput(s string) bool { return true } + +func Contains(s []string, str string) bool { + for _, v := range s { + if v == str { + return true + } + } + return false +} + +func SanitizeInput(input []string) []string { + allKeys := make(map[string]bool) + list := []string{} + for _, item := range input { + if _, value := allKeys[item]; !value { + allKeys[item] = true + list = append(list, item) + } + } + return list +} + +func TestValidateInput(t *testing.T) { + tests := []struct { + input string + expected bool + }{ + {"HelloWorld", true}, // Only Letters + {"123456", true}, // Only Numbers + {"Hello123", true}, // Mix of Letters and Numbers + {"Hello World!", false}, // Contains a Space and Exclamation Mark + {"", true}, // Empty String + {"Hello@World", false}, // Contains Special Character + {"123#456", false}, // Contains Special Character + } + + for _, tt := range tests { + t.Run(tt.input, func(t *testing.T) { + result := ValidateInput(tt.input) + if result != tt.expected { + t.Errorf("got %v, want %v", result, tt.expected) + } + }) + } +} diff --git a/internal/validator/validate_test.go b/internal/lib/util/validator/validate_test.go similarity index 76% rename from internal/validator/validate_test.go rename to internal/lib/util/validator/validate_test.go index 7f94a8f..7c744de 100644 --- a/internal/validator/validate_test.go +++ b/internal/lib/util/validator/validate_test.go @@ -1,6 +1,7 @@ package validator import ( + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -61,3 +62,26 @@ func Test_ValidateSubjectAlternateNames_ValidSAN_Regex_Success(t *testing.T) { assert.NoError(t, err) } } + +func Test_Contains(t *testing.T) { + s := []string{"a", "b", "c"} + + if !Contains(s, "a") { + t.Error("Expected slice to contain 'a'") + } + + if Contains(s, "d") { + t.Error("Did not expect slice to contain 'd'") + } +} + +func Test_SanitizeInput(t *testing.T) { + input := []string{"a", "b", "a", "c", "c"} + expected := []string{"a", "b", "c"} + + result := SanitizeInput(input) + + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, got %v", expected, result) + } +} diff --git a/internal/logger/logger.go b/internal/logger/logger.go index f049867..4faca0d 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,25 +5,18 @@ import ( "time" "github.com/gogo/status" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "go.uber.org/zap" "go.uber.org/zap/zapcore" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/peer" -) - -const ( - AuthorizationPayloadKey = "authorization_payload" - LoggingContextKey = "request_header_context" - ClientAuthorizationPayload = "client_authorization_payload" - UserUuid = "user_uuid" - ServiceUuid = "service_uuid" - ErrorMessage = "error_message" + "github.com/coinbase/baseca/internal/types" ) -type Extractor func(resp interface{}, err error, code codes.Code) string +type Extractor func(resp any, err error, code codes.Code) string type Error struct { UserError error @@ -41,49 +34,59 @@ func RpcError(user, internal error) *Error { } } -func RpcLogger( - extractor Extractor, -) grpc.UnaryServerInterceptor { - return func( - ctx context.Context, - req interface{}, - info *grpc.UnaryServerInfo, - handler grpc.UnaryHandler, - ) (resp interface{}, err error) { +func RpcLogger(extractor Extractor) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { currentTime := time.Now().UTC() result, err := handler(ctx, req) duration := time.Since(currentTime) - statusCode := codes.Unknown - if st, ok := status.FromError(err); ok { - statusCode = st.Code() - } else if customErr, ok := err.(*Error); ok { - statusCode = status.Code(customErr.UserError) - } - - logger := log.Info() + var event *zerolog.Event if err != nil { - logger = log.Error().Err(err) + event = log.Error().Err(err) + } else { + event = log.Info() } - var clientIP string - if p, ok := peer.FromContext(ctx); ok { - clientIP = p.Addr.String() - } - - // TODO: Validate Request Identifier (Context Post-Authentication) + statusCode := extractStatusCode(err) + clientIP := extractClientIP(ctx) - logger.Str("protocol", "grpc"). + event.Str("protocol", "grpc"). Str("method", info.FullMethod). Int("status_code", int(statusCode)). Str("ip_address", clientIP). - Dur("duration", duration). - Msg(extractor(result, err, statusCode)) + Dur("duration", duration) + + provisioner, ok := ctx.Value(types.ProvisionerAuthenticationContextKey).(*types.ProvisionerAccountPayload) + if ok { + event.Str("provisioner_account_uuid", provisioner.ClientId.String()) + } + service, ok := ctx.Value(types.ServiceAuthenticationContextKey).(*types.ServiceAccountPayload) + if ok { + event.Str("service_account_uuid", service.ServiceID.String()) + } + + event.Msg(extractor(result, err, statusCode)) return result, err } } +func extractClientIP(ctx context.Context) string { + if p, ok := peer.FromContext(ctx); ok { + return p.Addr.String() + } + return "" +} + +func extractStatusCode(err error) codes.Code { + if st, ok := status.FromError(err); ok { + return st.Code() + } else if customErr, ok := err.(*Error); ok { + return status.Code(customErr.UserError) + } + return codes.Unknown +} + type Logger interface { AddFields(fields ...zap.Field) @@ -167,7 +170,7 @@ func (ctxLogger *ContextLogger) fields(fields []zap.Field) []zap.Field { } func (ctxLogger *ContextLogger) stackFields(fields []zap.Field) []zap.Field { - return append(ctxLogger.fields(fields)) + return ctxLogger.fields(fields) } func (ctxLogger *ContextLogger) Panic(msg string, fields ...zap.Field) { diff --git a/internal/types/account.go b/internal/types/account.go index 1fc3cef..57a31c8 100644 --- a/internal/types/account.go +++ b/internal/types/account.go @@ -1,24 +1,27 @@ package types import ( - "time" - "github.com/google/uuid" ) -type ServiceAccount struct { - ClientID uuid.UUID `json:"client_id"` - ApiToken string `json:"api_token,omitempty" ` - ServiceAccount string `json:"service_account"` - Environment string `json:"environment,omitempty"` - Team string `json:"team"` - Email string `json:"email"` - SANRegularExpression string `json:"regular_expression,omitempty"` - ValidSubjectAlternateName []string `json:"valid_subject_alternate_name"` - ValidCertificateAuthorities []string `json:"valid_certificate_authorities"` - CertificateValidity int16 `json:"certificate_validity"` - ExtendedKey string `json:"extended_key"` - NodeAttestation NodeAttestation `json:"node_attestation"` - CreatedAt time.Time `json:"created_at"` - CreatedBy uuid.UUID `json:"created_by"` +type ServiceAccountPayload struct { + ServiceID uuid.UUID `json:"service_id"` + ServiceAccount string `json:"service_account"` + Environment string `json:"environment"` + ValidSubjectAlternateName []string `json:"subject_alternate_name"` + ValidCertificateAuthorities []string `json:"certificate_authorities"` + CertificateValidity int16 `json:"certificate_validity"` + SubordinateCa string `json:"subordinate_ca"` + ExtendedKey string `json:"certificate_request_extension"` + SANRegularExpression string `json:"regular_expression"` +} + +type ProvisionerAccountPayload struct { + ClientId uuid.UUID `json:"client_id"` + ProvisionerAccount string `json:"provisioner_account"` + Environments []string `json:"environments"` + ValidSubjectAlternateNames []string `json:"subject_alternate_names"` + MaxCertificateValidity uint32 `json:"max_certificate_validity"` + ExtendedKeys []string `json:"certificate_request_extension"` + RegularExpression string `json:"regular_expression"` } diff --git a/internal/types/certificate.go b/internal/types/certificate.go index 941b1d7..64431d3 100644 --- a/internal/types/certificate.go +++ b/internal/types/certificate.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "crypto/elliptic" "crypto/x509" "encoding/pem" "time" @@ -27,9 +28,10 @@ type Extensions struct { } type Algorithm struct { - Algorithm x509.PublicKeyAlgorithm - KeySize map[int]bool - Signature map[string]bool + Algorithm x509.PublicKeyAlgorithm + KeySize map[int]any + Signature map[string]bool + SigningAlgorithm map[x509.SignatureAlgorithm]bool } type SignatureAlgorithm struct { @@ -37,6 +39,17 @@ type SignatureAlgorithm struct { PCA types.SigningAlgorithm } +type SigningRequest struct { + CSR *bytes.Buffer + PrivateKey *pem.Block +} + +type SignedCertificate struct { + CertificatePath string + IntermediateCertificateChainPath string + RootCertificateChainPath string +} + type CertificateMetadata struct { SerialNumber string CommonName string @@ -48,7 +61,6 @@ type CertificateMetadata struct { Revoked bool RevokedBy string RevokeDate time.Time - Timestamp time.Time } type CertificateRequest struct { @@ -88,13 +100,8 @@ type CertificateAuthority struct { CertificateAuthorityArn string } -type SigningRequest struct { - CSR *bytes.Buffer - PrivateKey *pem.Block -} - type AsymmetricKey interface { - KeyPair() interface{} + KeyPair() any Sign(data []byte) ([]byte, error) } @@ -126,10 +133,10 @@ var ValidSignatures = map[string]SignatureAlgorithm{ // TODO: Support Probabilistic Element to the Signature Scheme [SHA256WithRSAPSS] } -var ValidAlgorithms = map[string]Algorithm{ +var PublicKeyAlgorithms = map[string]Algorithm{ "RSA": { Algorithm: x509.RSA, - KeySize: map[int]bool{ + KeySize: map[int]any{ 2048: true, 4096: true, }, @@ -138,19 +145,36 @@ var ValidAlgorithms = map[string]Algorithm{ "SHA384WITHRSA": true, "SHA512WITHRSA": true, }, + SigningAlgorithm: map[x509.SignatureAlgorithm]bool{ + x509.SHA256WithRSA: true, + x509.SHA384WithRSA: true, + x509.SHA512WithRSA: true, + }, }, "ECDSA": { Algorithm: x509.ECDSA, - KeySize: map[int]bool{ - 256: true, - 384: true, - 521: true, + KeySize: map[int]any{ + 256: elliptic.P256(), + 384: elliptic.P384(), + 521: elliptic.P521(), }, Signature: map[string]bool{ "SHA256WITHECDSA": true, "SHA384WITHECDSA": true, "SHA512WITHECDSA": true, }, + SigningAlgorithm: map[x509.SignatureAlgorithm]bool{ + x509.ECDSAWithSHA256: true, + x509.ECDSAWithSHA384: true, + x509.ECDSAWithSHA512: true, + }, + }, + // TODO: Support Ed25519 + "Ed25519": { + Algorithm: x509.Ed25519, + KeySize: map[int]any{ + 256: true, + }, }, } diff --git a/internal/types/constants.go b/internal/types/constants.go index 7f8bc76..3372b65 100644 --- a/internal/types/constants.go +++ b/internal/types/constants.go @@ -1,9 +1,16 @@ package types +type ContextKey int + const ( // Context Metadata - AuthorizationPayloadKey = "authorization_payload" - LoggingContextKey = "request_header_context" - ClientAuthorizationPayload = "client_authorization_payload" - EnrollmentAuthorizationPayload = "enrollment_authorization_payload" + ServiceAuthenticationContextKey ContextKey = iota + ProvisionerAuthenticationContextKey ContextKey = iota + UserAuthenticationContextKey ContextKey = iota + EnrollmentAuthenticationContextKey ContextKey = iota + + // User Permissions + ADMIN = "ADMIN" + PRIVILEGED = "PRIVILEGED" + READ = "READ" ) diff --git a/internal/v1/accounts/accounts.go b/internal/v1/accounts/accounts.go index aef6313..18ee07f 100644 --- a/internal/v1/accounts/accounts.go +++ b/internal/v1/accounts/accounts.go @@ -10,7 +10,7 @@ type Service struct { apiv1.ServiceServer store db.DatabaseEndpoints acmConfig map[string]config.SubordinateCertificate - environment config.Environment + environment config.Stage } func New(cfg *config.Config, endpoints db.DatabaseEndpoints) *Service { diff --git a/internal/v1/accounts/accounts_test.go b/internal/v1/accounts/accounts_test.go index 6332ef5..01b0f44 100644 --- a/internal/v1/accounts/accounts_test.go +++ b/internal/v1/accounts/accounts_test.go @@ -3,7 +3,7 @@ package accounts import ( mock_store "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/validator" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/test" ) diff --git a/internal/v1/accounts/operation_test.go b/internal/v1/accounts/operation_test.go index 445e5bd..8e21461 100644 --- a/internal/v1/accounts/operation_test.go +++ b/internal/v1/accounts/operation_test.go @@ -7,9 +7,9 @@ import ( "github.com/coinbase/baseca/db/mock" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" "google.golang.org/protobuf/types/known/emptypb" ) diff --git a/internal/v1/accounts/provision.go b/internal/v1/accounts/provision.go index a89771a..fa09d21 100644 --- a/internal/v1/accounts/provision.go +++ b/internal/v1/accounts/provision.go @@ -9,11 +9,11 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/attestor/aws_iid" - "github.com/coinbase/baseca/internal/authentication" + "github.com/coinbase/baseca/internal/attestation/aws_iid" + lib "github.com/coinbase/baseca/internal/lib/authentication" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "github.com/google/uuid" "google.golang.org/grpc/codes" @@ -73,17 +73,17 @@ func (s *Service) CreateProvisionerAccount(ctx context.Context, req *apiv1.Creat return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - clientToken, err := authentication.GenerateClientToken(32) + clientToken, err := lib.GenerateClientToken(32) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - hashedClientToken, err := authentication.HashPassword(clientToken) + hashedClientToken, err := lib.HashPassword(clientToken) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - payload, ok := ctx.Value(types.AuthorizationPayloadKey).(*authentication.Claims) + payload, ok := ctx.Value(types.UserAuthenticationContextKey).(*lib.Claims) if !ok { return nil, status.Error(codes.InvalidArgument, "service auth context missing") } @@ -207,7 +207,7 @@ func (s *Service) ProvisionServiceAccount(ctx context.Context, req *apiv1.Provis subject_alternative_names := validator.SanitizeInput(req.SubjectAlternativeNames) certificate_authorities := validator.SanitizeInput(req.CertificateAuthorities) - payload, ok := ctx.Value(types.ClientAuthorizationPayload).(*authentication.ProvisionerAccountPayload) + payload, ok := ctx.Value(types.ProvisionerAuthenticationContextKey).(*types.ProvisionerAccountPayload) if !ok { return nil, logger.RpcError(status.Error(codes.InvalidArgument, "service auth context missing"), fmt.Errorf("service auth context missing")) } @@ -221,6 +221,11 @@ func (s *Service) ProvisionServiceAccount(ctx context.Context, req *apiv1.Provis return nil, logger.RpcError(status.Error(codes.InvalidArgument, "provisioner subject alternative name (san) validation error"), fmt.Errorf("provisioner subject alternative name validation error [%s]", err)) } + err = s.CheckSubordinateCaRegion(req.SubordinateCa, req.Region, req.Environment, req.CertificateAuthorities) + if err != nil { + return nil, logger.RpcError(status.Error(codes.InvalidArgument, "subordinate ca does not support region"), fmt.Errorf("subordinate ca does not support region [%s] for service account [%s] %s", *req.Region, req.ServiceAccount, err)) + } + regex, err := regexp.Compile(payload.RegularExpression) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) @@ -233,7 +238,25 @@ func (s *Service) ProvisionServiceAccount(ctx context.Context, req *apiv1.Provis } if len(certificate_authorities) == 0 { - certAuth = append(certAuth, validator.CertificateAuthorityEnvironments[req.Environment]...) + environment := req.Environment + certificate_authorities := validator.CertificateAuthorityEnvironments[environment] + + // Include Default Certificate Authorities + for _, ca := range certificate_authorities { + ca_metadata := s.acmConfig[ca] + if ca_metadata.Default { + // Add Default Certificate Authorities for Region + if req.Region != nil && ca_metadata.Region == *req.Region { + certAuth = append(certAuth, ca) + } else if req.Region == nil { + // Add All Default Certificate Authorities + certAuth = append(certAuth, ca) + } + } + } + if len(certAuth) == 0 { + return nil, logger.RpcError(status.Error(codes.InvalidArgument, "invalid default certificate authority"), fmt.Errorf("invalid default certificate authority for environment [%s]", req.Environment)) + } } else { certAuth = req.CertificateAuthorities } @@ -274,12 +297,12 @@ func (s *Service) ProvisionServiceAccount(ctx context.Context, req *apiv1.Provis return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - clientToken, err := authentication.GenerateClientToken(32) + clientToken, err := lib.GenerateClientToken(32) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - hashedClientToken, err := authentication.HashPassword(clientToken) + hashedClientToken, err := lib.HashPassword(clientToken) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } @@ -381,3 +404,48 @@ func (s *Service) ProvisionServiceAccount(ctx context.Context, req *apiv1.Provis return &response, nil } + +func (s *Service) CheckSubordinateCaRegion(subordinate_ca string, region *string, environment string, valid_certificate_authorities []string) error { + // Service Account Does Not Contain Region Requirements for CA + if region == nil { + return nil + } + + // Get Valid Certificate Authorities for Subordinate CA + arg := db.ListValidCertificateAuthorityFromSubordinateCAParams{ + SubordinateCa: subordinate_ca, + Environment: environment, + } + certificate_authorities, err := s.store.Reader.ListValidCertificateAuthorityFromSubordinateCA(context.Background(), arg) + if err != nil { + return fmt.Errorf("error listing valid certificate authority from subordinate ca [%s] %s", subordinate_ca, err) + } + + // Generate Map for Certificate Authority Regions for Subordinate CA + subordinate_ca_regions := make(map[string]bool) + for _, ca := range certificate_authorities { + ca_str, ok := ca.(string) + if !ok { + return fmt.Errorf("certificate authority [%s] is not a string in database", ca) + } + region := s.acmConfig[ca_str].Region + subordinate_ca_regions[region] = true + } + + // Subordinate CA Across All Service Accounts Must Be In The Same Region + if len(subordinate_ca_regions) != 1 { + return fmt.Errorf("multiple regions present for subordinate ca [%s], cannot support region [%s]", subordinate_ca, *region) + } + + if !subordinate_ca_regions[*region] { + return fmt.Errorf("invalid region [%s] for subordinate ca [%s]", *region, subordinate_ca) + } + + // Check Valid Certificate Authorities in Correct Region + for _, ca := range valid_certificate_authorities { + if s.acmConfig[ca].Region != *region { + return fmt.Errorf("invalid region [%s] for certificate authority [%s]", *region, ca) + } + } + return nil +} diff --git a/internal/v1/accounts/provision_test.go b/internal/v1/accounts/provision_test.go index 54ef955..80d329c 100644 --- a/internal/v1/accounts/provision_test.go +++ b/internal/v1/accounts/provision_test.go @@ -11,23 +11,23 @@ import ( "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/coinbase/baseca/internal/types" - "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) func TestCreateProvisionerAccount(t *testing.T) { id, err := uuid.NewRandom() require.NoError(t, err) - authClaim := &authentication.Claims{ + authClaim := &lib.Claims{ Permission: "ADMIN", Subject: id, - IssuedAt: time.Now(), - ExpiresAt: time.Now().AddDate(0, 0, 1), - NotBefore: time.Now(), + IssuedAt: time.Now().UTC(), + ExpiresAt: time.Now().UTC().AddDate(0, 0, 1), + NotBefore: time.Now().UTC(), } attestation := apiv1.AWSInstanceIdentityDocument{ @@ -70,7 +70,7 @@ func TestCreateProvisionerAccount(t *testing.T) { { name: "OK_NO_ATTESTATION", req: request, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), build: func(store *mock.MockStore) { account_arg := db.CreateProvisionerAccountParams{ ProvisionerAccount: "example", @@ -94,7 +94,7 @@ func TestCreateProvisionerAccount(t *testing.T) { { name: "OK", req: requestOK, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), build: func(store *mock.MockStore) { account_arg := db.CreateProvisionerAccountParams{ ProvisionerAccount: "example", @@ -147,12 +147,263 @@ func TestCreateProvisionerAccount(t *testing.T) { } } +func TestProvisionServiceAccount(t *testing.T) { + region := "us-east-1" + id, err := uuid.NewRandom() + require.NoError(t, err) + + authClaim := &types.ProvisionerAccountPayload{ + ClientId: id, + ProvisionerAccount: "provisioner", + Environments: []string{"sandbox"}, + ValidSubjectAlternateNames: []string{"*.example.com"}, + MaxCertificateValidity: uint32(30), + ExtendedKeys: []string{"EndEntityServerAuthCertificate"}, + RegularExpression: "^.{0,250}$", + } + + cases := []struct { + name string + req *apiv1.ProvisionServiceAccountRequest + ctx context.Context + build func(store *mock.MockStore) + check func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) + }{ + { + name: "OK_NO_ATTESTATION", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + CertificateAuthorities: []string{"sandbox_use1"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + account_arg := db.CreateServiceAccountParams{ + ServiceAccount: "example", + Environment: "sandbox", + ValidSubjectAlternateName: []string{"sandbox.example.com"}, + ExtendedKey: "EndEntityServerAuthCertificate", + CertificateValidity: 30, + ValidCertificateAuthorities: []string{"sandbox_use1"}, + SubordinateCa: "infrastructure", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + CreatedBy: authClaim.ClientId, + NodeAttestation: []string{}, + Provisioned: true, + } + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + store.EXPECT().CreateServiceAccount( + gomock.Any(), + EqProvisionServiceAccountParams(account_arg), + ).Times(1).Return(&db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.NoError(t, err) + }, + }, + { + name: "OK_DEFAULT_CERTIFICATE_AUTHORITIES", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + account_arg := db.CreateServiceAccountParams{ + ServiceAccount: "example", + Environment: "sandbox", + ValidSubjectAlternateName: []string{"sandbox.example.com"}, + ExtendedKey: "EndEntityServerAuthCertificate", + CertificateValidity: 30, + ValidCertificateAuthorities: []string{"sandbox_use1", "sandbox_use2"}, + SubordinateCa: "infrastructure", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + CreatedBy: authClaim.ClientId, + NodeAttestation: []string{}, + Provisioned: true, + } + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + store.EXPECT().CreateServiceAccount( + gomock.Any(), + EqProvisionServiceAccountParams(account_arg), + ).Times(1).Return(&db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.NoError(t, err) + }, + }, + { + name: "OK_REGION_REQUIRED_AND_VALID_CA", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + Region: ®ion, + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + account_arg := db.CreateServiceAccountParams{ + ServiceAccount: "example", + Environment: "sandbox", + ValidSubjectAlternateName: []string{"sandbox.example.com"}, + ExtendedKey: "EndEntityServerAuthCertificate", + CertificateValidity: 30, + ValidCertificateAuthorities: []string{"sandbox_use1"}, + SubordinateCa: "infrastructure", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + CreatedBy: authClaim.ClientId, + NodeAttestation: []string{}, + Provisioned: true, + } + + arg := db.ListValidCertificateAuthorityFromSubordinateCAParams{ + SubordinateCa: "infrastructure", + Environment: "sandbox", + } + store.EXPECT().ListValidCertificateAuthorityFromSubordinateCA(gomock.Any(), arg).Times(1).Return([]any{"sandbox_use1"}, nil) + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + store.EXPECT().CreateServiceAccount( + gomock.Any(), + EqProvisionServiceAccountParams(account_arg), + ).Times(1).Return(&db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.NoError(t, err) + }, + }, + { + name: "ERROR_REGION_REQUIRED_AND_CA_WITH_CONFLICTING_REGION", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + Region: ®ion, + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + arg := db.ListValidCertificateAuthorityFromSubordinateCAParams{ + SubordinateCa: "infrastructure", + Environment: "sandbox", + } + store.EXPECT().ListValidCertificateAuthorityFromSubordinateCA(gomock.Any(), arg).Times(1).Return([]any{"sandbox_use2"}, nil) + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.Error(t, err) + require.Empty(t, res) + require.EqualError(t, err, "rpc error: code = InvalidArgument desc = subordinate ca does not support region") + }, + }, + { + name: "ERROR_REGION_REQUIRED_AND_CA_WITH_MULTIPLE_REGIONS", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + Region: ®ion, + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + arg := db.ListValidCertificateAuthorityFromSubordinateCAParams{ + SubordinateCa: "infrastructure", + Environment: "sandbox", + } + store.EXPECT().ListValidCertificateAuthorityFromSubordinateCA(gomock.Any(), arg).Times(1).Return([]any{"sandbox_use2", "sandbox_use1"}, nil) + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.Error(t, err) + require.Empty(t, res) + require.EqualError(t, err, "rpc error: code = InvalidArgument desc = subordinate ca does not support region") + }, + }, + { + name: "ERROR_CERTIFICATE_AUTHORITY_DIFFERENT_REGION", + req: &apiv1.ProvisionServiceAccountRequest{ + ServiceAccount: "example", + Environment: "sandbox", + SubjectAlternativeNames: []string{"sandbox.example.com"}, + SubordinateCa: "infrastructure", + CertificateValidity: 30, + Region: ®ion, + CertificateAuthorities: []string{"sandbox_use2"}, // Different Region than Region Field (us-east-1) + ExtendedKey: "EndEntityServerAuthCertificate", + Team: "Infrastructure Security", + Email: "security@coinbase.com", + }, + build: func(store *mock.MockStore) { + arg := db.ListValidCertificateAuthorityFromSubordinateCAParams{ + SubordinateCa: "infrastructure", + Environment: "sandbox", + } + store.EXPECT().ListValidCertificateAuthorityFromSubordinateCA(gomock.Any(), arg).Times(1).Return([]any{"sandbox_use2", "sandbox_use1"}, nil) + store.EXPECT().ListServiceAccounts(gomock.Any(), gomock.Any()).Times(1).Return([]*db.Account{}, nil) + }, + ctx: context.WithValue(context.Background(), types.ProvisionerAuthenticationContextKey, authClaim), + check: func(t *testing.T, res *apiv1.ProvisionServiceAccountResponse, err error) { + require.Error(t, err) + require.Empty(t, res) + require.EqualError(t, err, "rpc error: code = InvalidArgument desc = subordinate ca does not support region") + }, + }, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + store := mock.NewMockStore(ctrl) + + for elem := range cases { + tc := cases[elem] + + t.Run(tc.name, func(t *testing.T) { + tc.build(store) + + c, err := buildAccountsConfig(store) + require.NoError(t, err) + + res, err := c.ProvisionServiceAccount(tc.ctx, tc.req) + tc.check(t, res, err) + }) + } +} + type eqCreateProvisionerProvisionerParamsMatcher struct { arg db.CreateProvisionerAccountParams password string } -func (e eqCreateProvisionerProvisionerParamsMatcher) Matches(x interface{}) bool { +func (e eqCreateProvisionerProvisionerParamsMatcher) Matches(x any) bool { arg, ok := x.(db.CreateProvisionerAccountParams) if !ok { return false @@ -171,3 +422,28 @@ func (e eqCreateProvisionerProvisionerParamsMatcher) String() string { func EqCreateProvisionerAccountParams(arg db.CreateProvisionerAccountParams, password string) gomock.Matcher { return eqCreateProvisionerProvisionerParamsMatcher{arg, password} } + +type eqProvisionServiceAccountParams struct { + arg db.CreateServiceAccountParams +} + +func EqProvisionServiceAccountParams(arg db.CreateServiceAccountParams) gomock.Matcher { + return eqProvisionServiceAccountParams{arg} +} + +func (e eqProvisionServiceAccountParams) Matches(x any) bool { + arg, ok := x.(db.CreateServiceAccountParams) + if !ok { + return false + } + + e.arg.ClientID = arg.ClientID + e.arg.ApiToken = arg.ApiToken + e.arg.CreatedAt = arg.CreatedAt + + return reflect.DeepEqual(e.arg, arg) +} + +func (e eqProvisionServiceAccountParams) String() string { + return fmt.Sprintf("%v", e.arg) +} diff --git a/internal/v1/accounts/query.go b/internal/v1/accounts/query.go index 9e0dd03..f2b7408 100644 --- a/internal/v1/accounts/query.go +++ b/internal/v1/accounts/query.go @@ -7,9 +7,9 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "github.com/google/uuid" "google.golang.org/grpc/codes" diff --git a/internal/v1/accounts/query_test.go b/internal/v1/accounts/query_test.go index c3f78c0..0b95edc 100644 --- a/internal/v1/accounts/query_test.go +++ b/internal/v1/accounts/query_test.go @@ -8,9 +8,9 @@ import ( "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) func TestListServiceAccounts(t *testing.T) { diff --git a/internal/v1/accounts/service.go b/internal/v1/accounts/service.go index 978ca16..ab782d0 100644 --- a/internal/v1/accounts/service.go +++ b/internal/v1/accounts/service.go @@ -8,11 +8,11 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/attestor/aws_iid" - "github.com/coinbase/baseca/internal/authentication" + "github.com/coinbase/baseca/internal/attestation/aws_iid" + lib "github.com/coinbase/baseca/internal/lib/authentication" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "github.com/google/uuid" "google.golang.org/grpc/codes" @@ -54,19 +54,19 @@ func (s *Service) CreateServiceAccount(ctx context.Context, req *apiv1.CreateSer return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - clientToken, err := authentication.GenerateClientToken(32) + clientToken, err := lib.GenerateClientToken(32) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - hashedClientToken, err := authentication.HashPassword(clientToken) + hashedClientToken, err := lib.HashPassword(clientToken) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - payload, ok := ctx.Value(types.AuthorizationPayloadKey).(*authentication.Claims) + payload, ok := ctx.Value(types.UserAuthenticationContextKey).(*lib.Claims) if !ok { - logger.RpcError(status.Error(codes.Internal, "internal server error"), fmt.Errorf("service auth context missing")) + return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), fmt.Errorf("service auth context missing")) } // Production Service Accounts Require Attestation diff --git a/internal/v1/accounts/service_test.go b/internal/v1/accounts/service_test.go index 3fd6933..198ccc9 100644 --- a/internal/v1/accounts/service_test.go +++ b/internal/v1/accounts/service_test.go @@ -11,23 +11,23 @@ import ( "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/coinbase/baseca/internal/types" - "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) func TestCreateServiceAccount(t *testing.T) { id, err := uuid.NewRandom() require.NoError(t, err) - authClaim := &authentication.Claims{ + authClaim := &lib.Claims{ Permission: "ADMIN", Subject: id, - IssuedAt: time.Now(), - ExpiresAt: time.Now().AddDate(0, 0, 1), - NotBefore: time.Now(), + IssuedAt: time.Now().UTC(), + ExpiresAt: time.Now().UTC().AddDate(0, 0, 1), + NotBefore: time.Now().UTC(), } attestation := apiv1.AWSInstanceIdentityDocument{ @@ -92,7 +92,7 @@ func TestCreateServiceAccount(t *testing.T) { EqStoreInstanceIdentityDocumentParams(attestationParam, "iid arg matcher"), ).Times(1).Return(&db.Account{}, nil) }, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), check: func(t *testing.T, res *apiv1.CreateServiceAccountResponse, err error) { require.NoError(t, err) }, @@ -130,7 +130,7 @@ func TestCreateServiceAccount(t *testing.T) { EqCreateServiceAccountParams(account_arg, "account arg matcher"), ).Times(1).Return(&db.Account{}, nil) }, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), check: func(t *testing.T, res *apiv1.CreateServiceAccountResponse, err error) { require.NoError(t, err) }, @@ -168,7 +168,7 @@ func TestCreateServiceAccount(t *testing.T) { EqCreateServiceAccountParams(account_arg, "account arg matcher"), ).Times(1).Return(&db.Account{}, nil) }, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), check: func(t *testing.T, res *apiv1.CreateServiceAccountResponse, err error) { require.NoError(t, err) }, @@ -187,7 +187,7 @@ func TestCreateServiceAccount(t *testing.T) { Email: "security@coinbase.com", }, build: func(store *mock.MockStore) {}, - ctx: context.WithValue(context.Background(), types.AuthorizationPayloadKey, authClaim), + ctx: context.WithValue(context.Background(), types.UserAuthenticationContextKey, authClaim), check: func(t *testing.T, res *apiv1.CreateServiceAccountResponse, err error) { require.Error(t, err) }, @@ -218,7 +218,7 @@ type eqCreateServiceAccountParamsMatcher struct { password string } -func (e eqCreateServiceAccountParamsMatcher) Matches(x interface{}) bool { +func (e eqCreateServiceAccountParamsMatcher) Matches(x any) bool { arg, ok := x.(db.CreateServiceAccountParams) if !ok { return false @@ -243,7 +243,7 @@ type eqStoreInstanceIdentityDocumentParamsMatcher struct { password string } -func (e eqStoreInstanceIdentityDocumentParamsMatcher) Matches(x interface{}) bool { +func (e eqStoreInstanceIdentityDocumentParamsMatcher) Matches(x any) bool { arg, ok := x.(db.StoreInstanceIdentityDocumentParams) if !ok { return false diff --git a/internal/v1/accounts/validate.go b/internal/v1/accounts/validate.go index de13339..1b20f44 100644 --- a/internal/v1/accounts/validate.go +++ b/internal/v1/accounts/validate.go @@ -7,7 +7,7 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/validator" + "github.com/coinbase/baseca/internal/lib/util/validator" ) const ( diff --git a/internal/v1/certificate/certificate.go b/internal/v1/certificate/certificate.go index 8f92321..6e6a4bd 100644 --- a/internal/v1/certificate/certificate.go +++ b/internal/v1/certificate/certificate.go @@ -5,7 +5,7 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - acm_pca "github.com/coinbase/baseca/internal/client/acmpca" + "github.com/coinbase/baseca/internal/client/acmpca" "github.com/coinbase/baseca/internal/client/firehose" "github.com/coinbase/baseca/internal/client/redis" "github.com/coinbase/baseca/internal/config" @@ -17,10 +17,10 @@ type Certificate struct { acmConfig map[string]config.SubordinateCertificate ca config.SubordinateCertificateAuthority ocsp []string - environment config.Environment + environment config.Stage redis *redis.RedisClient firehose *firehose.FirehoseClient - pca *acm_pca.PrivateCaClient + pca *acmpca.PrivateCaClient } func New(cfg *config.Config, endpoints db.DatabaseEndpoints) (*Certificate, error) { diff --git a/internal/v1/certificate/certificate_test.go b/internal/v1/certificate/certificate_test.go index 2e15bc0..9bab8c5 100644 --- a/internal/v1/certificate/certificate_test.go +++ b/internal/v1/certificate/certificate_test.go @@ -2,9 +2,8 @@ package certificate import ( "context" - "crypto/ecdsa" - "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" @@ -19,7 +18,7 @@ import ( acm_pca "github.com/coinbase/baseca/internal/client/acmpca" "github.com/coinbase/baseca/internal/client/firehose" redis_client "github.com/coinbase/baseca/internal/client/redis" - "github.com/coinbase/baseca/internal/validator" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/test" "github.com/go-redis/redis/v8" "github.com/stretchr/testify/mock" @@ -28,7 +27,7 @@ import ( var csr *acmpca.IssueCertificateInput var rootCrt string -var pk *ecdsa.PrivateKey +var pk *rsa.PrivateKey var root []byte var template *x509.Certificate @@ -84,8 +83,8 @@ func (m *mockedPrivateCaClient) GetCertificate(ctx context.Context, params *acmp certTemplate := x509.Certificate{ SerialNumber: big.NewInt(2), Subject: req.Subject, - NotBefore: time.Now(), - NotAfter: time.Now().Add(60 * 24 * time.Hour), + NotBefore: time.Now().UTC(), + NotAfter: time.Now().UTC().Add(60 * 24 * time.Hour), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, } @@ -188,8 +187,8 @@ func buildCertificateConfig(store *mock_store.MockStore) (*Certificate, error) { }, nil } -func mockRootCertificateAuthority() (*ecdsa.PrivateKey, *x509.Certificate, []byte) { - rootKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) +func mockRootCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, []byte) { + rootKey, _ := rsa.GenerateKey(rand.Reader, 2048) rootTemplate := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ diff --git a/internal/v1/certificate/operations.go b/internal/v1/certificate/operations.go index 9202566..c31a5e8 100644 --- a/internal/v1/certificate/operations.go +++ b/internal/v1/certificate/operations.go @@ -10,11 +10,11 @@ import ( pca_types "github.com/aws/aws-sdk-go-v2/service/acmpca/types" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" - acm_pca "github.com/coinbase/baseca/internal/client/acmpca" + "github.com/coinbase/baseca/internal/client/acmpca" + lib "github.com/coinbase/baseca/internal/lib/authentication" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/timestamppb" @@ -40,10 +40,10 @@ func (c *Certificate) RevokeCertificate(ctx context.Context, req *apiv1.RevokeCe var parameters types.CertificateParameters var processed *pca_types.RequestAlreadyProcessedException - if _, ok := ctx.Value(types.AuthorizationPayloadKey).(*authentication.Claims); !ok { + if _, ok := ctx.Value(types.UserAuthenticationContextKey).(*lib.Claims); !ok { return nil, status.Error(codes.InvalidArgument, "authentication error") } - uuid := ctx.Value(types.AuthorizationPayloadKey).(*authentication.Claims).Subject + uuid := ctx.Value(types.UserAuthenticationContextKey).(*lib.Claims).Subject certificate, err := c.store.Reader.GetCertificate(ctx, req.SerialNumber) if err != nil { @@ -64,7 +64,7 @@ func (c *Certificate) RevokeCertificate(ctx context.Context, req *apiv1.RevokeCe // c.pca Mock Private CA if c.pca == nil { - client, err := acm_pca.NewPrivateCaClient(parameters) + client, err := acmpca.NewPrivateCaClient(parameters) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "acm pca client error"), err) } @@ -121,7 +121,7 @@ func (c *Certificate) OperationsSignCSR(ctx context.Context, req *apiv1.Operatio serviceAccount, err := c.store.Reader.GetServiceAccountByMetadata(ctx, arg) if err != nil { - logger.RpcError(status.Error(codes.Internal, "error issuing certificate [OperationsSignCSR]"), fmt.Errorf("error querying service account metadata [%s]: %s", req.ServiceAccount, err)) + return nil, logger.RpcError(status.Error(codes.Internal, "error issuing certificate [OperationsSignCSR]"), fmt.Errorf("error querying service account metadata [%s]: %s", req.ServiceAccount, err)) } if len(serviceAccount) != 1 { @@ -141,7 +141,7 @@ func (c *Certificate) OperationsSignCSR(ctx context.Context, req *apiv1.Operatio } else { expirationDate := time.Now().UTC().AddDate(0, 0, int(req.CertificateAuthority.Validity)).UTC() if expirationDate.Before(time.Now().UTC().Add(time.Minute).UTC()) { - logger.RpcError(status.Error(codes.Internal, "invalid certificate validity"), fmt.Errorf("invalid certificate validity [%s]", req.ServiceAccount)) + return nil, logger.RpcError(status.Error(codes.Internal, "invalid certificate validity"), fmt.Errorf("invalid certificate validity [%s]", req.ServiceAccount)) } certificateAuthorityParameters = &apiv1.CertificateAuthorityParameter{ @@ -155,7 +155,7 @@ func (c *Certificate) OperationsSignCSR(ctx context.Context, req *apiv1.Operatio } // c.pca Mock Private CA if c.pca == nil { - client, err := acm_pca.NewPrivateCaClient(types.CertificateParameters{ + client, err := acmpca.NewPrivateCaClient(types.CertificateParameters{ AssumeRole: certificateAuthorityParameters.AssumeRole, RoleArn: certificateAuthorityParameters.RoleArn, Region: certificateAuthorityParameters.Region, diff --git a/internal/v1/certificate/operations_test.go b/internal/v1/certificate/operations_test.go index dbd6009..56a37fa 100644 --- a/internal/v1/certificate/operations_test.go +++ b/internal/v1/certificate/operations_test.go @@ -12,8 +12,8 @@ import ( db "github.com/coinbase/baseca/db/sqlc" "github.com/coinbase/baseca/internal/lib/crypto" "github.com/coinbase/baseca/internal/types" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" ) @@ -39,8 +39,8 @@ func TestGetCertificate(t *testing.T) { Environment: "development", ExtendedKey: "EndEntityServerAuthCertificate", SubjectAlternativeName: []string{"development.example.com"}, - ExpirationDate: time.Now(), - IssuedDate: time.Now().Add(24 * time.Hour), + ExpirationDate: time.Now().UTC(), + IssuedDate: time.Now().UTC().Add(24 * time.Hour), Revoked: false, CertificateAuthorityArn: sql.NullString{String: "arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", Valid: true}, } @@ -154,6 +154,7 @@ func TestOperationsSignCSR(t *testing.T) { CaArn: "arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", SignAlgorithm: "SHA512WITHRSA", AssumeRole: false, + Validity: 30, } return &apiv1.OperationsSignRequest{ @@ -215,7 +216,7 @@ type certificateLogArgMatcher struct { ExtendedKey string } -func (m *certificateLogArgMatcher) Matches(x interface{}) bool { +func (m *certificateLogArgMatcher) Matches(x any) bool { if arg, ok := x.(db.LogCertificateParams); ok { return arg.Account == m.Account && arg.Environment == m.Environment diff --git a/internal/v1/certificate/pca.go b/internal/v1/certificate/pca.go index ce31413..99f5647 100644 --- a/internal/v1/certificate/pca.go +++ b/internal/v1/certificate/pca.go @@ -4,14 +4,11 @@ import ( "context" "crypto/rand" "crypto/x509" - "encoding/binary" "fmt" "math/big" - math_rand "math/rand" "time" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/authentication" "github.com/coinbase/baseca/internal/client/firehose" "github.com/coinbase/baseca/internal/lib/crypto" "github.com/coinbase/baseca/internal/types" @@ -28,13 +25,12 @@ func (c *Certificate) buildCertificateAuthorityParameters(certificate_authority } } -func (c *Certificate) issueEndEntityCertificate(auth *authentication.ServicePayload, ca_certificate *types.CertificateAuthority, request_csr *x509.CertificateRequest) (*db.CertificateResponseData, error) { +func (c *Certificate) issueEndEntityCertificate(auth *types.ServiceAccountPayload, ca_certificate *types.CertificateAuthority, request_csr *x509.CertificateRequest) (*db.CertificateResponseData, error) { block := make([]byte, 20) _, err := rand.Read(block[:]) if err != nil { return nil, err } - math_rand.Seed(int64(binary.LittleEndian.Uint64(block[:]))) output := big.NewInt(0).SetBytes(block) issuedDate := time.Now().UTC() @@ -47,7 +43,7 @@ func (c *Certificate) issueEndEntityCertificate(auth *authentication.ServicePayl certificateTemplate := x509.Certificate{ DNSNames: request_csr.DNSNames, Signature: request_csr.Signature, - SignatureAlgorithm: request_csr.SignatureAlgorithm, + SignatureAlgorithm: ca_certificate.Certificate.SignatureAlgorithm, PublicKeyAlgorithm: request_csr.PublicKeyAlgorithm, PublicKey: request_csr.PublicKey, SerialNumber: output, @@ -93,7 +89,6 @@ func (c *Certificate) issueEndEntityCertificate(auth *authentication.ServicePayl IssuedDate: issuedDate, CaSerialNumber: ca_certificate.SerialNumber, CertificateAuthorityArn: ca_certificate.CertificateAuthorityArn, - Timestamp: time.Now().UTC(), } event := firehose.ForwardedEventUploadEvent{ diff --git a/internal/v1/certificate/query.go b/internal/v1/certificate/query.go index ddb7b99..0f94528 100644 --- a/internal/v1/certificate/query.go +++ b/internal/v1/certificate/query.go @@ -7,9 +7,9 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/timestamppb" diff --git a/internal/v1/certificate/query_test.go b/internal/v1/certificate/query_test.go index a7ec986..d6a573e 100644 --- a/internal/v1/certificate/query_test.go +++ b/internal/v1/certificate/query_test.go @@ -7,8 +7,8 @@ import ( "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) func TestQueryCertificateMetadata(t *testing.T) { diff --git a/internal/v1/certificate/sign.go b/internal/v1/certificate/sign.go index d1766d4..aedde1d 100644 --- a/internal/v1/certificate/sign.go +++ b/internal/v1/certificate/sign.go @@ -10,24 +10,23 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" - acm_pca "github.com/coinbase/baseca/internal/client/acmpca" + "github.com/coinbase/baseca/internal/client/acmpca" "github.com/coinbase/baseca/internal/config" "github.com/coinbase/baseca/internal/lib/crypto" "github.com/coinbase/baseca/internal/lib/util" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/timestamppb" ) func (c *Certificate) SignCSR(ctx context.Context, req *apiv1.CertificateSigningRequest) (*apiv1.SignedCertificate, error) { - var service *authentication.ServicePayload + var service *types.ServiceAccountPayload var ok bool - if service, ok = ctx.Value(types.ClientAuthorizationPayload).(*authentication.ServicePayload); !ok { + if service, ok = ctx.Value(types.ServiceAuthenticationContextKey).(*types.ServiceAccountPayload); !ok { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), fmt.Errorf("service payload malformatted: %+v", service)) } @@ -79,7 +78,7 @@ func (c *Certificate) SignCSR(ctx context.Context, req *apiv1.CertificateSigning } -func (c *Certificate) requestCertificate(ctx context.Context, authPayload *authentication.ServicePayload, certificateRequest *x509.CertificateRequest) (*db.CertificateResponseData, error) { +func (c *Certificate) requestCertificate(ctx context.Context, authPayload *types.ServiceAccountPayload, certificateRequest *x509.CertificateRequest) (*db.CertificateResponseData, error) { var subordinate *types.CertificateAuthority var parameters types.CertificateRequest var csr *bytes.Buffer @@ -113,7 +112,7 @@ func (c *Certificate) requestCertificate(ctx context.Context, authPayload *authe CommonName: intermediateCa, SubjectAlternateNames: []string{intermediateCa}, SigningAlgorithm: signingAlgorithm.Common, - PublicKeyAlgorithm: types.ValidAlgorithms[c.ca.KeyAlgorithm].Algorithm, + PublicKeyAlgorithm: types.PublicKeyAlgorithms[c.ca.KeyAlgorithm].Algorithm, KeySize: c.ca.KeySize, DistinguishedName: types.DistinguishedName{ Country: []string{c.ca.Country}, @@ -174,7 +173,7 @@ func (c *Certificate) requestCertificate(ctx context.Context, authPayload *authe } } -func (c *Certificate) validateCertificateRequestParameters(csr *x509.CertificateRequest, auth authentication.ServicePayload) error { +func (c *Certificate) validateCertificateRequestParameters(csr *x509.CertificateRequest, auth types.ServiceAccountPayload) error { if err := csr.CheckSignature(); err != nil { return logger.RpcError(status.Error(codes.InvalidArgument, "invalid signature for certificate signing request (csr)"), err) } @@ -213,7 +212,7 @@ func (c *Certificate) rateLimit(ctx context.Context, certificateRequest *x509.Ce return nil } -func (c *Certificate) issueSubordinate(auth *authentication.ServicePayload, certificate_signing_request *bytes.Buffer, service_name string) error { +func (c *Certificate) issueSubordinate(auth *types.ServiceAccountPayload, certificate_signing_request *bytes.Buffer, service_name string) error { var ca_certificate *x509.Certificate var err error @@ -223,7 +222,7 @@ func (c *Certificate) issueSubordinate(auth *authentication.ServicePayload, cert // c.pca Mock Private CA if c.pca == nil { - client, err := acm_pca.NewPrivateCaClient(ca_parameters) + client, err := acmpca.NewPrivateCaClient(ca_parameters) if err != nil { return err } diff --git a/internal/v1/certificate/sign_test.go b/internal/v1/certificate/sign_test.go index d9f6f97..e2dd171 100644 --- a/internal/v1/certificate/sign_test.go +++ b/internal/v1/certificate/sign_test.go @@ -7,15 +7,11 @@ import ( "github.com/coinbase/baseca/db/mock" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" + "github.com/coinbase/baseca/internal/types" baseca "github.com/coinbase/baseca/pkg/client" - "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" -) - -const ( - _client_header = "client_authorization_payload" + "go.uber.org/mock/gomock" ) func TestSignCSR(t *testing.T) { @@ -60,7 +56,7 @@ func TestSignCSR(t *testing.T) { c, err := buildCertificateConfig(store) require.NoError(t, err) - ctx := context.WithValue(context.Background(), _client_header, &authentication.ServicePayload{ + ctx := context.WithValue(context.Background(), types.ServiceAuthenticationContextKey, &types.ServiceAccountPayload{ ServiceID: uuid.New(), ServiceAccount: "example", Environment: "development", @@ -68,6 +64,7 @@ func TestSignCSR(t *testing.T) { ValidCertificateAuthorities: []string{"sandbox_use1"}, CertificateValidity: int16(30), ExtendedKey: "EndEntityServerAuthCertificate", + SubordinateCa: "infrastructure", }) req := tc.req() diff --git a/internal/v1/certificate/validate.go b/internal/v1/certificate/validate.go index 2f418ad..4da86cf 100644 --- a/internal/v1/certificate/validate.go +++ b/internal/v1/certificate/validate.go @@ -12,12 +12,11 @@ import ( "time" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" "github.com/coinbase/baseca/internal/config" "github.com/coinbase/baseca/internal/lib/crypto" "github.com/coinbase/baseca/internal/lib/util" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" ) const ( @@ -59,7 +58,7 @@ func checkLockfile(serviceId string) error { } // Check if Subordinate Certificate Exists for Service -func loadSubordinateCaParameters(service string, auth *authentication.ServicePayload) (*types.CertificateAuthority, error) { +func loadSubordinateCaParameters(service string, auth *types.ServiceAccountPayload) (*types.CertificateAuthority, error) { x509_metadata, err := crypto.GetSubordinateCaParameters(service) if err != nil { return nil, err @@ -121,17 +120,17 @@ func convertX509toString(certificate []byte) (*bytes.Buffer, error) { func ValidateSubordinateParameters(parameter config.SubordinateCertificateAuthority) error { switch parameter.KeyAlgorithm { case "RSA": - if _, ok := types.ValidAlgorithms[parameter.KeyAlgorithm].KeySize[parameter.KeySize]; !ok { + if _, ok := types.PublicKeyAlgorithms[parameter.KeyAlgorithm].KeySize[parameter.KeySize]; !ok { return fmt.Errorf("invalid rsa key size: %d", parameter.KeySize) } - if _, ok := types.ValidAlgorithms[parameter.KeyAlgorithm].Signature[parameter.SigningAlgorithm]; !ok { + if _, ok := types.PublicKeyAlgorithms[parameter.KeyAlgorithm].Signature[parameter.SigningAlgorithm]; !ok { return fmt.Errorf("invalid rsa signing algorithm: %s", parameter.SigningAlgorithm) } case "ECDSA": - if _, ok := types.ValidAlgorithms[parameter.KeyAlgorithm].KeySize[parameter.KeySize]; !ok { + if _, ok := types.PublicKeyAlgorithms[parameter.KeyAlgorithm].KeySize[parameter.KeySize]; !ok { return fmt.Errorf("invalid ecdsa key size: %d", parameter.KeySize) } - if _, ok := types.ValidAlgorithms[parameter.KeyAlgorithm].Signature[parameter.SigningAlgorithm]; !ok { + if _, ok := types.PublicKeyAlgorithms[parameter.KeyAlgorithm].Signature[parameter.SigningAlgorithm]; !ok { return fmt.Errorf("invalid ecdsa signing algorithm: %s", parameter.SigningAlgorithm) } default: diff --git a/internal/v1/middleware/authentication.go b/internal/v1/middleware/authentication.go index 3544df0..ff956a3 100644 --- a/internal/v1/middleware/authentication.go +++ b/internal/v1/middleware/authentication.go @@ -7,11 +7,11 @@ import ( "strings" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/attestor/aws_iid" - "github.com/coinbase/baseca/internal/authentication" + "github.com/coinbase/baseca/internal/attestation/aws_iid" + lib "github.com/coinbase/baseca/internal/lib/authentication" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" "github.com/coinbase/baseca/internal/types" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "github.com/google/uuid" "google.golang.org/grpc" @@ -25,7 +25,7 @@ const ( _provisioner_auth = "provisioner_authentication" ) -func (m *Middleware) ServerAuthenticationInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { +func (m *Middleware) ServerAuthenticationInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { var auth string var ok bool @@ -78,7 +78,7 @@ func (m *Middleware) ServerAuthenticationInterceptor(ctx context.Context, req in if !ok { return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication failed"), fmt.Errorf("invalid permission error %s", userPermission)) } - ctx = context.WithValue(ctx, types.AuthorizationPayloadKey, payload) + ctx = context.WithValue(ctx, types.UserAuthenticationContextKey, payload) } } else if auth == _service_auth { service, err := m.AuthenticateServiceAccount(ctx) @@ -86,19 +86,19 @@ func (m *Middleware) ServerAuthenticationInterceptor(ctx context.Context, req in return nil, err } - ctx = context.WithValue(ctx, types.ClientAuthorizationPayload, service) + ctx = context.WithValue(ctx, types.ServiceAuthenticationContextKey, service) } else if auth == _provisioner_auth { service, err := m.AuthenticateProvisionerAccount(ctx) if err != nil { return nil, err } - ctx = context.WithValue(ctx, types.ClientAuthorizationPayload, service) + ctx = context.WithValue(ctx, types.ProvisionerAuthenticationContextKey, service) } return handler(ctx, req) } -func (m *Middleware) AuthenticateServiceAccount(ctx context.Context) (*authentication.ServicePayload, error) { +func (m *Middleware) AuthenticateServiceAccount(ctx context.Context) (*types.ServiceAccountPayload, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, status.Errorf(codes.Internal, "failed to retrieve metadata from context") @@ -125,7 +125,7 @@ func (m *Middleware) AuthenticateServiceAccount(ctx context.Context) (*authentic } account := cachedServiceAccount.ServiceAccount - if err := authentication.CheckPassword(clientTokenAuthorizationHeader[0], account.ApiToken); err != nil { + if err := lib.CheckPassword(clientTokenAuthorizationHeader[0], account.ApiToken); err != nil { return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication error"), err) } @@ -145,7 +145,7 @@ func (m *Middleware) AuthenticateServiceAccount(ctx context.Context) (*authentic } } - service := &authentication.ServicePayload{ + service := &types.ServiceAccountPayload{ ServiceID: account.ClientID, ServiceAccount: account.ServiceAccount, Environment: account.Environment, @@ -160,7 +160,7 @@ func (m *Middleware) AuthenticateServiceAccount(ctx context.Context) (*authentic return service, nil } -func (m *Middleware) AuthenticateProvisionerAccount(ctx context.Context) (*authentication.ProvisionerAccountPayload, error) { +func (m *Middleware) AuthenticateProvisionerAccount(ctx context.Context) (*types.ProvisionerAccountPayload, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, status.Errorf(codes.Internal, "failed to retrieve metadata from context") @@ -187,7 +187,7 @@ func (m *Middleware) AuthenticateProvisionerAccount(ctx context.Context) (*authe } account := cachedProvisionerAccount.ProvisionerAccount - if err := authentication.CheckPassword(clientTokenAuthorizationHeader[0], account.ApiToken); err != nil { + if err := lib.CheckPassword(clientTokenAuthorizationHeader[0], account.ApiToken); err != nil { return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication error"), err) } @@ -207,7 +207,7 @@ func (m *Middleware) AuthenticateProvisionerAccount(ctx context.Context) (*authe } } - service := &authentication.ProvisionerAccountPayload{ + service := &types.ProvisionerAccountPayload{ ClientId: account.ClientID, ProvisionerAccount: account.ProvisionerAccount, Environments: account.Environments, diff --git a/internal/v1/middleware/middleware.go b/internal/v1/middleware/middleware.go index 4328730..bd972b8 100644 --- a/internal/v1/middleware/middleware.go +++ b/internal/v1/middleware/middleware.go @@ -4,7 +4,7 @@ import ( "github.com/allegro/bigcache/v3" "github.com/casbin/casbin/v2" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" ) const ( @@ -16,20 +16,16 @@ const ( clientIdAuthorizationHeaderKey = "x-baseca-client-id" // #nosec G101 False Positive clientTokenAuthorizationHeaderKey = "x-baseca-client-token" // #nosec G101 False Positive clientIdentityDocumentHeaderKey = "x-baseca-instance-metadata" - - // Enrollment Authorization - enrollmentIdAuthorizationHeaderKey = "x-baseca-enrollment-id" - enrollmentAuthorizationHeaderToken = "x-baseca-enrollment-token" // #nosec G101 False Positive ) type Middleware struct { - auth authentication.Auth + auth lib.Auth store db.DatabaseEndpoints enforcer *casbin.Enforcer cache *bigcache.BigCache } -func New(auth authentication.Auth, endpoints db.DatabaseEndpoints, enforcer *casbin.Enforcer, cache *bigcache.BigCache) *Middleware { +func New(auth lib.Auth, endpoints db.DatabaseEndpoints, enforcer *casbin.Enforcer, cache *bigcache.BigCache) *Middleware { return &Middleware{ auth: auth, store: endpoints, diff --git a/internal/v1/users/operations.go b/internal/v1/users/operations.go index 1a4cbe6..acce65b 100644 --- a/internal/v1/users/operations.go +++ b/internal/v1/users/operations.go @@ -7,10 +7,9 @@ import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" - "github.com/coinbase/baseca/internal/authorization" + lib "github.com/coinbase/baseca/internal/lib/authentication" + "github.com/coinbase/baseca/internal/lib/util/validator" "github.com/coinbase/baseca/internal/logger" - "github.com/coinbase/baseca/internal/validator" "github.com/gogo/status" "github.com/google/uuid" passwordvalidator "github.com/wagslane/go-password-validator" @@ -33,7 +32,7 @@ func (u *User) LoginUser(ctx context.Context, req *apiv1.LoginUserRequest) (*api return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication failed"), err) } - if err := authentication.CheckPassword(req.Password, user.HashedCredential); err != nil { + if err := lib.CheckPassword(req.Password, user.HashedCredential); err != nil { return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication failed"), err) } @@ -44,7 +43,7 @@ func (u *User) LoginUser(ctx context.Context, req *apiv1.LoginUserRequest) (*api return int64(u.validity) }() - accessToken, err := u.auth.Issue(ctx, authentication.ClaimProps{ + accessToken, err := u.auth.Issue(ctx, lib.ClaimProps{ Subject: user.Uuid, Permission: user.Permissions, ValidForMinutes: validity, @@ -68,7 +67,7 @@ func (u *User) LoginUser(ctx context.Context, req *apiv1.LoginUserRequest) (*api } func (u *User) CreateUser(ctx context.Context, req *apiv1.CreateUserRequest) (*apiv1.User, error) { - if !authorization.IsSupportedPermission(req.Permissions) { + if !validator.IsSupportedPermission(req.Permissions) { return nil, logger.RpcError(status.Error(codes.InvalidArgument, "invalid permission field"), fmt.Errorf("invalid permission %s", req.Permissions)) } @@ -77,7 +76,7 @@ func (u *User) CreateUser(ctx context.Context, req *apiv1.CreateUserRequest) (*a return nil, logger.RpcError(status.Error(codes.InvalidArgument, "minimum password strength requirement not met"), err) } - hashedCredential, err := authentication.HashPassword(req.Password) + hashedCredential, err := lib.HashPassword(req.Password) if err != nil { return nil, logger.RpcError(status.Error(codes.Unauthenticated, "authentication error"), err) } @@ -188,7 +187,7 @@ func (u *User) ListUsers(ctx context.Context, req *apiv1.QueryParameter) (*apiv1 } func (u *User) UpdateUserPermissions(ctx context.Context, req *apiv1.UpdatePermissionsRequest) (*apiv1.User, error) { - if !authorization.IsSupportedPermission(req.Permissions) { + if !validator.IsSupportedPermission(req.Permissions) { return nil, logger.RpcError(status.Error(codes.InvalidArgument, "invalid permission field"), fmt.Errorf("invalid permission %s", req.Permissions)) } @@ -218,7 +217,7 @@ func (u *User) UpdateUserCredentials(ctx context.Context, req *apiv1.UpdateCrede return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } - if err := authentication.CheckPassword(req.Password, user.HashedCredential); err != nil { + if err := lib.CheckPassword(req.Password, user.HashedCredential); err != nil { return nil, logger.RpcError(status.Error(codes.PermissionDenied, "authentication failed"), err) } @@ -227,7 +226,7 @@ func (u *User) UpdateUserCredentials(ctx context.Context, req *apiv1.UpdateCrede return nil, logger.RpcError(status.Error(codes.InvalidArgument, "minimum password strength requirement not met"), err) } - hashedCredential, err := authentication.HashPassword(req.UpdatedPassword) + hashedCredential, err := lib.HashPassword(req.UpdatedPassword) if err != nil { return nil, logger.RpcError(status.Error(codes.Internal, "internal server error"), err) } diff --git a/internal/v1/users/operations_test.go b/internal/v1/users/operations_test.go index a130120..58f4a2c 100644 --- a/internal/v1/users/operations_test.go +++ b/internal/v1/users/operations_test.go @@ -10,10 +10,10 @@ import ( "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/coinbase/baseca/internal/lib/util" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) const ( @@ -122,13 +122,13 @@ type eqCreateUserParamsMatcher struct { password string } -func (e eqCreateUserParamsMatcher) Matches(x interface{}) bool { +func (e eqCreateUserParamsMatcher) Matches(x any) bool { arg, ok := x.(db.CreateUserParams) if !ok { return false } - err := authentication.CheckPassword(e.password, arg.HashedCredential) + err := lib.CheckPassword(e.password, arg.HashedCredential) if err != nil { return false } diff --git a/internal/v1/users/users.go b/internal/v1/users/users.go index 8263ea9..ede8c9b 100644 --- a/internal/v1/users/users.go +++ b/internal/v1/users/users.go @@ -3,18 +3,18 @@ package users import ( db "github.com/coinbase/baseca/db/sqlc" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" - "github.com/coinbase/baseca/internal/authentication" "github.com/coinbase/baseca/internal/config" + lib "github.com/coinbase/baseca/internal/lib/authentication" ) type User struct { apiv1.AccountServer store db.DatabaseEndpoints - auth authentication.Auth + auth lib.Auth validity int } -func New(cfg *config.Config, endpoints db.DatabaseEndpoints, auth authentication.Auth) *User { +func New(cfg *config.Config, endpoints db.DatabaseEndpoints, auth lib.Auth) *User { return &User{ store: endpoints, auth: auth, diff --git a/internal/v1/users/users_test.go b/internal/v1/users/users_test.go index 5503662..0c0f300 100644 --- a/internal/v1/users/users_test.go +++ b/internal/v1/users/users_test.go @@ -6,7 +6,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/kms" mock_store "github.com/coinbase/baseca/db/mock" db "github.com/coinbase/baseca/db/sqlc" - "github.com/coinbase/baseca/internal/authentication" + lib "github.com/coinbase/baseca/internal/lib/authentication" "github.com/coinbase/baseca/test" "github.com/stretchr/testify/mock" ) @@ -38,13 +38,13 @@ func buildUsersConfig(store *mock_store.MockStore) (*User, error) { }, nil, ) - signer := &authentication.Client{ + signer := &lib.Client{ KmsClient: mockKms, KeyId: config.KMS.KeyId, SigningAlgorithm: config.KMS.SigningAlgorithm, } - auth, err := authentication.NewAuthSigningMetadata(signer) + auth, err := lib.NewAuthSigningMetadata(signer) if err != nil { return nil, err } diff --git a/pkg/attestor/aws_iid/iid.go b/pkg/attestor/aws_iid/iid.go index 49007b9..6990435 100644 --- a/pkg/attestor/aws_iid/iid.go +++ b/pkg/attestor/aws_iid/iid.go @@ -3,7 +3,7 @@ package aws_iid import ( "bytes" "encoding/json" - "io/ioutil" + "io" "net/http" ) @@ -48,7 +48,7 @@ func httpGetRequest(uri string) ([]byte, error) { return nil, err } else { defer response.Body.Close() // #nosec G307 False Positive - response, err := ioutil.ReadAll(response.Body) + response, err := io.ReadAll(response.Body) if err != nil { return nil, err } diff --git a/pkg/client/certificate.go b/pkg/client/certificate.go index 8385682..b7f0277 100644 --- a/pkg/client/certificate.go +++ b/pkg/client/certificate.go @@ -6,6 +6,7 @@ import ( "os" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" + "github.com/coinbase/baseca/pkg/types" ) func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1.SignedCertificate, error) { @@ -23,7 +24,7 @@ func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1 return nil, err } - err = parseCertificateFormat(signedCertificate, SignedCertificate{ + err = parseCertificateFormat(signedCertificate, types.SignedCertificate{ CertificatePath: certificateRequest.Output.Certificate, IntermediateCertificateChainPath: certificateRequest.Output.IntermediateCertificateChain, RootCertificateChainPath: certificateRequest.Output.RootCertificateChain, @@ -36,7 +37,7 @@ func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1 return signedCertificate, nil } -func parseCertificateFormat(certificate *apiv1.SignedCertificate, parameter SignedCertificate) error { +func parseCertificateFormat(certificate *apiv1.SignedCertificate, parameter types.SignedCertificate) error { // Leaf Certificate Path if len(parameter.CertificatePath) != 0 { certificate := []byte(certificate.Certificate) diff --git a/pkg/client/client.go b/pkg/client/client.go index 731bffa..23a6541 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -109,10 +109,10 @@ type ServiceClient interface { DeleteProvisionedServiceAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*emptypb.Empty, error) } -func LoadDefaultConfiguration(configuration Configuration, client_id, client_token, attestation string) (*client, error) { +func LoadDefaultConfiguration(configuration Configuration, attestation string, authentication Authentication) (*client, error) { c := client{ endpoint: configuration.URL, - authentication: Authentication{client_id, client_token}, + authentication: authentication, attestation: attestation, } diff --git a/pkg/client/csr.go b/pkg/client/csr.go index a135789..6ed2c99 100644 --- a/pkg/client/csr.go +++ b/pkg/client/csr.go @@ -12,20 +12,11 @@ import ( "errors" "fmt" "os" -) - -type SigningRequest struct { - CSR *bytes.Buffer - PrivateKey *pem.Block -} -type SignedCertificate struct { - CertificatePath string - IntermediateCertificateChainPath string - RootCertificateChainPath string -} + "github.com/coinbase/baseca/pkg/types" +) -func GenerateCSR(csr CertificateRequest) (*SigningRequest, error) { +func GenerateCSR(csr CertificateRequest) (*types.SigningRequest, error) { switch csr.PublicKeyAlgorithm { case x509.RSA: if csr.KeySize < 2048 { @@ -88,7 +79,7 @@ func GenerateCSR(csr CertificateRequest) (*SigningRequest, error) { } } - return &SigningRequest{ + return &types.SigningRequest{ CSR: certificatePem, PrivateKey: pkBlock, }, nil @@ -136,7 +127,7 @@ func GenerateCSR(csr CertificateRequest) (*SigningRequest, error) { } } - return &SigningRequest{ + return &types.SigningRequest{ CSR: certificatePem, PrivateKey: pkBlock, }, nil diff --git a/pkg/client/provisioner.go b/pkg/client/provisioner.go index ead3258..d1edf5b 100644 --- a/pkg/client/provisioner.go +++ b/pkg/client/provisioner.go @@ -4,6 +4,7 @@ import ( "context" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" + "github.com/coinbase/baseca/pkg/types" ) func (c *client) ProvisionIssueCertificate(certificateRequest CertificateRequest, ca *apiv1.CertificateAuthorityParameter, service, environment, extendedKey string) (*apiv1.SignedCertificate, error) { @@ -25,7 +26,7 @@ func (c *client) ProvisionIssueCertificate(certificateRequest CertificateRequest return nil, err } - err = parseCertificateFormat(signedCertificate, SignedCertificate{ + err = parseCertificateFormat(signedCertificate, types.SignedCertificate{ CertificatePath: certificateRequest.Output.Certificate, IntermediateCertificateChainPath: certificateRequest.Output.IntermediateCertificateChain, RootCertificateChainPath: certificateRequest.Output.RootCertificateChain, diff --git a/pkg/client/sign.go b/pkg/client/sign.go index 6885be9..150cfae 100644 --- a/pkg/client/sign.go +++ b/pkg/client/sign.go @@ -14,6 +14,7 @@ import ( "path/filepath" apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1" + "github.com/coinbase/baseca/pkg/types" ) func (c *client) GenerateSignature(csr CertificateRequest, element []byte) (*[]byte, []*x509.Certificate, error) { @@ -34,10 +35,11 @@ func (c *client) GenerateSignature(csr CertificateRequest, element []byte) (*[]b return nil, nil, err } - err = parseCertificateFormat(signedCertificate, SignedCertificate{ + err = parseCertificateFormat(signedCertificate, types.SignedCertificate{ CertificatePath: csr.Output.Certificate, IntermediateCertificateChainPath: csr.Output.IntermediateCertificateChain, - RootCertificateChainPath: csr.Output.RootCertificateChain}) + RootCertificateChainPath: csr.Output.RootCertificateChain, + }) if err != nil { return nil, nil, err @@ -81,28 +83,28 @@ func (c *client) GenerateSignature(csr CertificateRequest, element []byte) (*[]b return &signature, certificateChain, nil } -func (c *client) ValidateSignature(certificates []*x509.Certificate, signature []byte, element []byte, cn string, ca string) error { - err := certificates[0].CheckSignature(x509.SHA256WithRSA, element, signature) +func (c *client) ValidateSignature(tc types.TrustChain, manifest types.Manifest) error { + err := manifest.CertificateChain[0].CheckSignature(manifest.SigningAlgorithm, manifest.Data, manifest.Signature) if err != nil { return fmt.Errorf("signature verification failed: %s", err) } - // Validate Entire Certificate Chain Valid - for i := range certificates[:len(certificates)-1] { - err = certificates[i].CheckSignatureFrom(certificates[i+1]) + // Validate Entire Certificate Chain Does Not Break + for i := range manifest.CertificateChain[:len(manifest.CertificateChain)-1] { + err = manifest.CertificateChain[i].CheckSignatureFrom(manifest.CertificateChain[i+1]) if err != nil { return fmt.Errorf("certificate chain invalid: %s", err) } } - if certificates[0].Subject.CommonName != cn { + if manifest.CertificateChain[0].Subject.CommonName != tc.CommonName { return fmt.Errorf("invalid common name (cn) from code signing certificate") } validSubjectAlternativeName := false - if len(certificates[0].DNSNames) > 0 { - for _, san := range certificates[0].DNSNames { - if san == cn { + if len(manifest.CertificateChain[0].DNSNames) > 0 { + for _, san := range manifest.CertificateChain[0].DNSNames { + if san == tc.CommonName { validSubjectAlternativeName = true } } @@ -112,7 +114,7 @@ func (c *client) ValidateSignature(certificates []*x509.Certificate, signature [ return fmt.Errorf("invalid subject alternative name (san) from code signing certificate") } - rootCertificatePool, err := c.generateCertificatePool(ca) + rootCertificatePool, err := c.generateCertificatePool(tc) if err != nil { return err } @@ -121,25 +123,43 @@ func (c *client) ValidateSignature(certificates []*x509.Certificate, signature [ Roots: rootCertificatePool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, } - _, err = certificates[1].Verify(opts) + _, err = manifest.CertificateChain[1].Verify(opts) if err != nil { return fmt.Errorf("error validating code signing certificate validity: %s", err) } return nil } -func (c *client) generateCertificatePool(ca string) (*x509.CertPool, error) { +func (c *client) generateCertificatePool(tc types.TrustChain) (*x509.CertPool, error) { certPool := x509.NewCertPool() - files, err := os.ReadDir(ca) - if err != nil { - return nil, errors.New("invalid certificate authority directory") + for _, dir := range tc.CertificateAuthorityDirectory { + files, err := os.ReadDir(dir) + if err != nil { + return nil, errors.New("invalid certificate authority directory") + } + + for _, certFile := range files { // #nosec G304 User Only Has Predefined Environment Parameters + data, err := os.ReadFile(filepath.Join(dir, certFile.Name())) + if err != nil { + return nil, errors.New("invalid certificate file") + } + pemBlock, _ := pem.Decode(data) + if pemBlock == nil || pemBlock.Type != "CERTIFICATE" { + return nil, errors.New("invalid input file") + } + cert, err := x509.ParseCertificate(pemBlock.Bytes) + if err != nil { + return nil, errors.New("error parsing x.509 certificate") + } + certPool.AddCert(cert) + } } - for _, certFile := range files { // #nosec G304 User Only Has Predefined Environment Parameters - data, err := os.ReadFile(filepath.Join(ca, certFile.Name())) + for _, ca := range tc.CertificateAuthorityFiles { + data, err := os.ReadFile(filepath.Clean(ca)) if err != nil { - return nil, errors.New("invalid certificate file") + return nil, errors.New("invalid certificate authority file") } pemBlock, _ := pem.Decode(data) if pemBlock == nil || pemBlock.Type != "CERTIFICATE" { diff --git a/pkg/types/certificate.go b/pkg/types/certificate.go new file mode 100644 index 0000000..7f298d4 --- /dev/null +++ b/pkg/types/certificate.go @@ -0,0 +1,71 @@ +package types + +import ( + "bytes" + "crypto/elliptic" + "crypto/x509" + "encoding/pem" +) + +type SigningRequest struct { + CSR *bytes.Buffer + PrivateKey *pem.Block +} + +type SignedCertificate struct { + CertificatePath string + IntermediateCertificateChainPath string + RootCertificateChainPath string +} + +type PublicKeyAlgorithm struct { + Algorithm x509.PublicKeyAlgorithm + KeySize map[int]any + Signature map[string]bool + SigningAlgorithm map[x509.SignatureAlgorithm]bool +} + +var PublicKeyAlgorithms = map[string]PublicKeyAlgorithm{ + "RSA": { + Algorithm: x509.RSA, + KeySize: map[int]interface{}{ + 2048: true, + 4096: true, + }, + Signature: map[string]bool{ + "SHA256WITHRSA": true, + "SHA384WITHRSA": true, + "SHA512WITHRSA": true, + }, + SigningAlgorithm: map[x509.SignatureAlgorithm]bool{ + x509.SHA256WithRSA: true, + x509.SHA384WithRSA: true, + x509.SHA512WithRSA: true, + }, + }, + "ECDSA": { + Algorithm: x509.ECDSA, + KeySize: map[int]interface{}{ + 256: elliptic.P256(), + 384: elliptic.P384(), + 521: elliptic.P521(), + }, + Signature: map[string]bool{ + "SHA256WITHECDSA": true, + "SHA384WITHECDSA": true, + "SHA512WITHECDSA": true, + }, + SigningAlgorithm: map[x509.SignatureAlgorithm]bool{ + x509.ECDSAWithSHA256: true, + x509.ECDSAWithSHA384: true, + x509.ECDSAWithSHA512: true, + }, + }, + // TODO: Support Ed25519 + "Ed25519": { + Algorithm: x509.Ed25519, + KeySize: map[int]interface{}{ + 256: true, + }, + }, +} diff --git a/pkg/types/sign.go b/pkg/types/sign.go new file mode 100644 index 0000000..c08d88e --- /dev/null +++ b/pkg/types/sign.go @@ -0,0 +1,16 @@ +package types + +import "crypto/x509" + +type TrustChain struct { + CommonName string + CertificateAuthorityDirectory []string + CertificateAuthorityFiles []string +} + +type Manifest struct { + CertificateChain []*x509.Certificate + Signature []byte + Data []byte + SigningAlgorithm x509.SignatureAlgorithm +} diff --git a/protos/baseca/v1/api.proto b/protos/baseca/v1/api.proto index 1b90a38..b043213 100644 --- a/protos/baseca/v1/api.proto +++ b/protos/baseca/v1/api.proto @@ -295,6 +295,7 @@ message ProvisionServiceAccountRequest { NodeAttestation node_attestation = 9; string team = 10; string email = 11; + optional string region = 12; } message ProvisionServiceAccountResponse { diff --git a/test/config/config.test.local.sandbox.yml b/test/config/config.test.local.sandbox.yml index 5f1e6ca..53f372b 100644 --- a/test/config/config.test.local.sandbox.yml +++ b/test/config/config.test.local.sandbox.yml @@ -29,6 +29,14 @@ acm_pca: ca_active_day: 90 assume_role: false root_ca: false + default: true + sandbox_use2: + region: us-east-2 + ca_arn: arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy + ca_active_day: 90 + assume_role: false + root_ca: false + default: true firehose: stream: baseca-test @@ -57,4 +65,5 @@ subordinate_ca_metadata: certificate_authority: sandbox: - - sandbox_use1 \ No newline at end of file + - sandbox_use1 + - sandbox_use2 \ No newline at end of file