From bf3b0340e5b28e54593b8e219c50ab5eecbfd145 Mon Sep 17 00:00:00 2001 From: irenarindos Date: Fri, 27 May 2022 13:17:29 -0400 Subject: [PATCH] feat(workerauth): add storage for RootCertificates aggregate --- .../99/03_worker_authentication.up.sql | 58 ++++++- .../servers/store/v1/root_certificate.proto | 14 ++ internal/servers/root_certificate.go | 37 ++++- internal/servers/store/root_certificate.pb.go | 155 ++++++++++++++---- internal/servers/workerauth_store_test.go | 9 +- 5 files changed, 237 insertions(+), 36 deletions(-) diff --git a/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql b/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql index d64967532f..b2aca4b537 100644 --- a/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql +++ b/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql @@ -16,6 +16,39 @@ values ('next'), ('current'); +create table worker_auth_ca( + private_id text primary key + constraint only_roots_id_allowed + check (private_id in ('roots')), + version wt_version, + create_time wt_timestamp, + update_time wt_timestamp +); + +create trigger + immutable_columns + before + update on worker_auth_ca + for each row execute procedure immutable_columns('private_id','create_time'); + +create trigger worker_auth_ca_default_create_time_column + before + insert on worker_auth_ca + for each row execute procedure default_create_time(); + +create trigger worker_auth_ca_update_time_column + before + update on worker_auth_ca + for each row execute procedure update_time_column(); + +insert into worker_auth_ca(private_id) values('roots'); + +create trigger update_version_column after update on worker_auth_ca + for each row execute procedure update_version_column(); + +comment on table worker_auth_ca is + 'worker_auth_ca is a one-row versioned table used for locking for certificate rotation on the worker_auth_ca_certificate table.'; + create table worker_auth_ca_certificate( serial_number numeric, certificate bytea not null @@ -40,9 +73,19 @@ create table worker_auth_ca_certificate( constraint worker_auth_operational_indicator_enm_fkey references worker_auth_operational_indicator_enm(state) on delete restrict - on update cascade + on update cascade, + issuing_ca text not null + constraint worker_auth_ca_fkey + references worker_auth_ca(private_id) ); +create trigger + immutable_columns + before + update on worker_auth_ca_certificate + for each row execute procedure immutable_columns('serial_number', 'certificate', 'not_valid_before', 'not_valid_after', + 'public_key', 'private_key', 'key_id', 'state', 'issuing_ca'); + comment on table worker_auth_ca_certificate is 'worker_auth_ca_certificate is a table where each row represents a root certificate for used for worker authentication.'; @@ -70,6 +113,13 @@ create table worker_auth_authorized( nonce bytea ); +create trigger + immutable_columns + before + update on worker_auth_authorized + for each row execute procedure immutable_columns('worker_key_identifier', 'worker_id', 'worker_signing_pub_key', + 'worker_encryption_pub_key', 'controller_encryption_priv_key', 'key_id', 'nonce'); + comment on table worker_auth_authorized is 'worker_auth_authorized is a table where each row represents key and cert data associated with an authorized worker.'; @@ -93,4 +143,10 @@ create table worker_auth_certificate_bundle( comment on table worker_auth_certificate_bundle is 'worker_auth_certificate_bundle is a table where each row represents a cert bundle issued by a ca certificate for a worker.'; +create trigger + immutable_columns + before + update on worker_auth_certificate_bundle + for each row execute procedure immutable_columns('certificate_public_key', 'worker_key_identifier', 'cert_bundle'); + commit; \ No newline at end of file diff --git a/internal/proto/controller/storage/servers/store/v1/root_certificate.proto b/internal/proto/controller/storage/servers/store/v1/root_certificate.proto index 16a4d29072..1094e0bdee 100644 --- a/internal/proto/controller/storage/servers/store/v1/root_certificate.proto +++ b/internal/proto/controller/storage/servers/store/v1/root_certificate.proto @@ -7,6 +7,16 @@ import "controller/storage/timestamp/v1/timestamp.proto"; option go_package = "github.com/hashicorp/boundary/internal/servers/store;store"; +// CertificateAuthority is a versioned entity used to lock the database when rotation RootCertificates +message CertificateAuthority { + // @inject_tag: `gorm:"primary_key"` + string private_id = 10; + + // version allows optimistic locking of the resource. + // @inject_tag: `gorm:"default:null"` + uint32 version = 20; +} + // RootCertificate contains all fields related to a RootCertificate resource message RootCertificate { // The serial number of the root certificate @@ -39,4 +49,8 @@ message RootCertificate { // State is an enum value indicating if this is the next or current root cert // @inject_tag: `gorm:"not_null"` string state = 80; + + // A reference to the CertificateAuthority + // @inject_tag: `gorm:"not_null"` + string issuing_ca = 90; } diff --git a/internal/servers/root_certificate.go b/internal/servers/root_certificate.go index 4e935fa95e..f944c7e68f 100644 --- a/internal/servers/root_certificate.go +++ b/internal/servers/root_certificate.go @@ -11,6 +11,38 @@ import ( "google.golang.org/protobuf/proto" ) +// The CertificateAuthority id will always be set to "roots". +// The const ca_id contains this value +const ca_id = "roots" + +// CertificateAuthority is a versioned entity used to lock the database when rotation RootCertificates +type CertificateAuthority struct { + *store.CertificateAuthority + tableName string `gorm:"-"` +} + +func newCertificateAuthority() *CertificateAuthority { + ca := &CertificateAuthority{ + CertificateAuthority: &store.CertificateAuthority{ + PrivateId: ca_id, + }, + } + return ca +} + +// TableName returns the table name. +func (r *CertificateAuthority) TableName() string { + if r.tableName != "" { + return r.tableName + } + return "worker_auth_ca" +} + +// SetTableName sets the table name. +func (r *CertificateAuthority) SetTableName(n string) { + r.tableName = n +} + // RootCertificate contains fields related to a RootCertificate resource // This includes public/ private keys, the PEM encoded certificate, and the certificate validity period type RootCertificate struct { @@ -18,6 +50,7 @@ type RootCertificate struct { tableName string `gorm:"-"` } +// RootCertificateKeys contains the public and private keys for use in constructing a RootCertificate type RootCertificateKeys struct { publicKey []byte privateKey []byte @@ -63,12 +96,13 @@ func newRootCertificate(ctx context.Context, serialNumber uint64, certificate [] PrivateKey: rootCertificateKeys.privateKey, KeyId: keyId, State: string(state), + IssuingCa: ca_id, }, } return l, nil } -func AllocRootCertificate() *RootCertificate { +func allocRootCertificate() *RootCertificate { return &RootCertificate{ RootCertificate: &store.RootCertificate{}, } @@ -81,6 +115,7 @@ func (r *RootCertificate) clone() *RootCertificate { } } +// Validate the RootCertificate. On success, return nil func (r *RootCertificate) ValidateNewRootCertificate(ctx context.Context) error { const op = "servers.(RootCertificate).ValidateNewRootCertificate" if &r.SerialNumber == nil { diff --git a/internal/servers/store/root_certificate.pb.go b/internal/servers/store/root_certificate.pb.go index 7e8feee6a4..f3a32e013b 100644 --- a/internal/servers/store/root_certificate.pb.go +++ b/internal/servers/store/root_certificate.pb.go @@ -23,6 +23,65 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// CertificateAuthority is a versioned entity used to lock the database when rotation RootCertificates +type CertificateAuthority struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // @inject_tag: `gorm:"primary_key"` + PrivateId string `protobuf:"bytes,10,opt,name=private_id,json=privateId,proto3" json:"private_id,omitempty" gorm:"primary_key"` + // version allows optimistic locking of the resource. + // @inject_tag: `gorm:"default:null"` + Version uint32 `protobuf:"varint,20,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"` +} + +func (x *CertificateAuthority) Reset() { + *x = CertificateAuthority{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CertificateAuthority) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertificateAuthority) ProtoMessage() {} + +func (x *CertificateAuthority) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CertificateAuthority.ProtoReflect.Descriptor instead. +func (*CertificateAuthority) Descriptor() ([]byte, []int) { + return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP(), []int{0} +} + +func (x *CertificateAuthority) GetPrivateId() string { + if x != nil { + return x.PrivateId + } + return "" +} + +func (x *CertificateAuthority) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + // RootCertificate contains all fields related to a RootCertificate resource type RootCertificate struct { state protoimpl.MessageState @@ -52,12 +111,15 @@ type RootCertificate struct { // State is an enum value indicating if this is the next or current root cert // @inject_tag: `gorm:"not_null"` State string `protobuf:"bytes,80,opt,name=state,proto3" json:"state,omitempty" gorm:"not_null"` + // A reference to the CertificateAuthority + // @inject_tag: `gorm:"not_null"` + IssuingCa string `protobuf:"bytes,90,opt,name=issuing_ca,json=issuingCa,proto3" json:"issuing_ca,omitempty" gorm:"not_null"` } func (x *RootCertificate) Reset() { *x = RootCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0] + mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -70,7 +132,7 @@ func (x *RootCertificate) String() string { func (*RootCertificate) ProtoMessage() {} func (x *RootCertificate) ProtoReflect() protoreflect.Message { - mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0] + mi := &file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -83,7 +145,7 @@ func (x *RootCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use RootCertificate.ProtoReflect.Descriptor instead. func (*RootCertificate) Descriptor() ([]byte, []int) { - return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP(), []int{0} + return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP(), []int{1} } func (x *RootCertificate) GetSerialNumber() uint64 { @@ -142,6 +204,13 @@ func (x *RootCertificate) GetState() string { return "" } +func (x *RootCertificate) GetIssuingCa() string { + if x != nil { + return x.IssuingCa + } + return "" +} + var File_controller_storage_servers_store_v1_root_certificate_proto protoreflect.FileDescriptor var file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc = []byte{ @@ -154,30 +223,37 @@ var file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc = [] 0x31, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0xef, 0x02, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x73, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x54, 0x0a, - 0x10, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, - 0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x74, 0x6f, 0x22, 0x4f, 0x0a, 0x14, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x8e, 0x03, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x54, + 0x0a, 0x10, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x62, 0x65, 0x66, 0x6f, + 0x72, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, + 0x5f, 0x63, 0x61, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x73, 0x73, 0x75, 0x69, + 0x6e, 0x67, 0x43, 0x61, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, @@ -196,14 +272,15 @@ func file_controller_storage_servers_store_v1_root_certificate_proto_rawDescGZIP return file_controller_storage_servers_store_v1_root_certificate_proto_rawDescData } -var file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_controller_storage_servers_store_v1_root_certificate_proto_goTypes = []interface{}{ - (*RootCertificate)(nil), // 0: controller.storage.servers.store.v1.RootCertificate - (*timestamp.Timestamp)(nil), // 1: controller.storage.timestamp.v1.Timestamp + (*CertificateAuthority)(nil), // 0: controller.storage.servers.store.v1.CertificateAuthority + (*RootCertificate)(nil), // 1: controller.storage.servers.store.v1.RootCertificate + (*timestamp.Timestamp)(nil), // 2: controller.storage.timestamp.v1.Timestamp } var file_controller_storage_servers_store_v1_root_certificate_proto_depIdxs = []int32{ - 1, // 0: controller.storage.servers.store.v1.RootCertificate.not_valid_before:type_name -> controller.storage.timestamp.v1.Timestamp - 1, // 1: controller.storage.servers.store.v1.RootCertificate.not_valid_after:type_name -> controller.storage.timestamp.v1.Timestamp + 2, // 0: controller.storage.servers.store.v1.RootCertificate.not_valid_before:type_name -> controller.storage.timestamp.v1.Timestamp + 2, // 1: controller.storage.servers.store.v1.RootCertificate.not_valid_after:type_name -> controller.storage.timestamp.v1.Timestamp 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name @@ -218,6 +295,18 @@ func file_controller_storage_servers_store_v1_root_certificate_proto_init() { } if !protoimpl.UnsafeEnabled { file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertificateAuthority); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_servers_store_v1_root_certificate_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RootCertificate); i { case 0: return &v.state @@ -236,7 +325,7 @@ func file_controller_storage_servers_store_v1_root_certificate_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_storage_servers_store_v1_root_certificate_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/servers/workerauth_store_test.go b/internal/servers/workerauth_store_test.go index d362ce78e1..488f5fe6ad 100644 --- a/internal/servers/workerauth_store_test.go +++ b/internal/servers/workerauth_store_test.go @@ -75,6 +75,7 @@ func TestRootCertStore(t *testing.T) { NotValidAfter: afterTimestamp, KeyId: testKey, State: "next", + IssuingCa: ca_id, }, wantErr: false, }, @@ -98,6 +99,7 @@ func TestRootCertStore(t *testing.T) { NotValidAfter: afterTimestamp, KeyId: testKey, State: "current", + IssuingCa: ca_id, }, wantErr: false, }, @@ -240,7 +242,12 @@ func TestDuplicateRootCert(t *testing.T) { beforeTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(-1 * time.Hour))} afterTimestamp := ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(1 * time.Hour))} - // Make two current and next root CAs + // Attempt to create a duplicate CA and expect a failure + certAuthority := newCertificateAuthority() + err = rw.Create(ctx, certAuthority) + require.Error(t, err) + + // Make two current and next root certs current1, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp, RootCertificateKeys{publicKey: populateBytes(defaultLength), privateKey: populateBytes(defaultLength)}, testKey, CurrentState)