diff --git a/builtin/logical/database/backend_get_test.go b/builtin/logical/database/backend_get_test.go index ec6e3966cd..5e2e5df2c9 100644 --- a/builtin/logical/database/backend_get_test.go +++ b/builtin/logical/database/backend_get_test.go @@ -35,6 +35,10 @@ func (s *systemViewWrapper) TPMByID(ctx context.Context, id string) (*logical.TP panic("nope") } +func (s *systemViewWrapper) GroupsForTPM(ctx context.Context, id string) ([]*logical.TPMGroup, error) { + panic("nope") +} + func (s *systemViewWrapper) RequestWellKnownRedirect(ctx context.Context, src, dest string) error { panic("nope") } diff --git a/helper/identity/types.pb.go b/helper/identity/types.pb.go index e3b5b1c90d..39263857bd 100644 --- a/helper/identity/types.pb.go +++ b/helper/identity/types.pb.go @@ -1157,6 +1157,106 @@ func (x *TPM) GetBucketKey() string { return "" } +type TPMGroup struct { + state protoimpl.MessageState `protogen:"open.v1"` + // ID is the unique identifier for this group + // @inject_tag: sentinel:"-" + ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" sentinel:"-"` + // Name is the unique name for this group + // @inject_tag: sentinel:"-" + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" sentinel:"-"` + // Metadata represents the custom data tied with this group + // @inject_tag: sentinel:"-" + Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value" sentinel:"-"` + // NamespaceID is the identifier of the namespace to which this group + // belongs to. Do not return this value over the API when reading the + // group. + // @inject_tag: sentinel:"-" + NamespaceID string `protobuf:"bytes,4,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty" sentinel:"-"` + // MemberTpmIDs are the identifiers of entities which are members of this + // group + // @inject_tag: sentinel:"-" + MemberTpmIDs []string `protobuf:"bytes,5,rep,name=member_tpm_ids,json=memberTpmIds,proto3" json:"member_tpm_ids,omitempty" sentinel:"-"` + // BucketKey is the path of the storage packer key into which this + // tpmgroup is stored. + // @inject_tag: sentinel:"-" + BucketKey string `protobuf:"bytes,6,opt,name=bucket_key,json=bucketKey,proto3" json:"bucket_key,omitempty" sentinel:"-"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TPMGroup) Reset() { + *x = TPMGroup{} + mi := &file_helper_identity_types_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TPMGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TPMGroup) ProtoMessage() {} + +func (x *TPMGroup) ProtoReflect() protoreflect.Message { + mi := &file_helper_identity_types_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TPMGroup.ProtoReflect.Descriptor instead. +func (*TPMGroup) Descriptor() ([]byte, []int) { + return file_helper_identity_types_proto_rawDescGZIP(), []int{8} +} + +func (x *TPMGroup) GetID() string { + if x != nil { + return x.ID + } + return "" +} + +func (x *TPMGroup) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TPMGroup) GetMetadata() map[string]string { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *TPMGroup) GetNamespaceID() string { + if x != nil { + return x.NamespaceID + } + return "" +} + +func (x *TPMGroup) GetMemberTpmIDs() []string { + if x != nil { + return x.MemberTpmIDs + } + return nil +} + +func (x *TPMGroup) GetBucketKey() string { + if x != nil { + return x.BucketKey + } + return "" +} + var File_helper_identity_types_proto protoreflect.FileDescriptor var file_helper_identity_types_proto_rawDesc = string([]byte{ @@ -1412,10 +1512,28 @@ var file_helper_identity_types_proto_rawDesc = string([]byte{ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x2f, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x91, 0x02, 0x0a, 0x08, 0x54, 0x50, 0x4d, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x54, 0x50, 0x4d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x74, 0x70, 0x6d, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x54, 0x70, 0x6d, 0x49, 0x64, 0x73, + 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x1a, + 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2c, 0x5a, 0x2a, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x68, 0x65, 0x6c, 0x70, 0x65, + 0x72, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, }) var ( @@ -1430,7 +1548,7 @@ func file_helper_identity_types_proto_rawDescGZIP() []byte { return file_helper_identity_types_proto_rawDescData } -var file_helper_identity_types_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_helper_identity_types_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_helper_identity_types_proto_goTypes = []any{ (*Group)(nil), // 0: identity.Group (*LocalAliases)(nil), // 1: identity.LocalAliases @@ -1440,49 +1558,52 @@ var file_helper_identity_types_proto_goTypes = []any{ (*EntityStorageEntry)(nil), // 5: identity.EntityStorageEntry (*PersonaIndexEntry)(nil), // 6: identity.PersonaIndexEntry (*TPM)(nil), // 7: identity.TPM - nil, // 8: identity.Group.MetadataEntry - nil, // 9: identity.Entity.MetadataEntry - nil, // 10: identity.Entity.MFASecretsEntry - nil, // 11: identity.Alias.MetadataEntry - nil, // 12: identity.Alias.CustomMetadataEntry - nil, // 13: identity.EntityStorageEntry.MetadataEntry - nil, // 14: identity.EntityStorageEntry.MFASecretsEntry - nil, // 15: identity.PersonaIndexEntry.MetadataEntry - nil, // 16: identity.TPM.MetadataEntry - (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp - (*mfa.Secret)(nil), // 18: mfa.Secret + (*TPMGroup)(nil), // 8: identity.TPMGroup + nil, // 9: identity.Group.MetadataEntry + nil, // 10: identity.Entity.MetadataEntry + nil, // 11: identity.Entity.MFASecretsEntry + nil, // 12: identity.Alias.MetadataEntry + nil, // 13: identity.Alias.CustomMetadataEntry + nil, // 14: identity.EntityStorageEntry.MetadataEntry + nil, // 15: identity.EntityStorageEntry.MFASecretsEntry + nil, // 16: identity.PersonaIndexEntry.MetadataEntry + nil, // 17: identity.TPM.MetadataEntry + nil, // 18: identity.TPMGroup.MetadataEntry + (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp + (*mfa.Secret)(nil), // 20: mfa.Secret } var file_helper_identity_types_proto_depIDxs = []int32{ - 8, // 0: identity.Group.metadata:type_name -> identity.Group.MetadataEntry - 17, // 1: identity.Group.creation_time:type_name -> google.protobuf.Timestamp - 17, // 2: identity.Group.last_update_time:type_name -> google.protobuf.Timestamp + 9, // 0: identity.Group.metadata:type_name -> identity.Group.MetadataEntry + 19, // 1: identity.Group.creation_time:type_name -> google.protobuf.Timestamp + 19, // 2: identity.Group.last_update_time:type_name -> google.protobuf.Timestamp 3, // 3: identity.Group.alias:type_name -> identity.Alias 3, // 4: identity.LocalAliases.aliases:type_name -> identity.Alias 3, // 5: identity.Entity.aliases:type_name -> identity.Alias - 9, // 6: identity.Entity.metadata:type_name -> identity.Entity.MetadataEntry - 17, // 7: identity.Entity.creation_time:type_name -> google.protobuf.Timestamp - 17, // 8: identity.Entity.last_update_time:type_name -> google.protobuf.Timestamp - 10, // 9: identity.Entity.mfa_secrets:type_name -> identity.Entity.MFASecretsEntry - 11, // 10: identity.Alias.metadata:type_name -> identity.Alias.MetadataEntry - 17, // 11: identity.Alias.creation_time:type_name -> google.protobuf.Timestamp - 17, // 12: identity.Alias.last_update_time:type_name -> google.protobuf.Timestamp - 12, // 13: identity.Alias.custom_metadata:type_name -> identity.Alias.CustomMetadataEntry + 10, // 6: identity.Entity.metadata:type_name -> identity.Entity.MetadataEntry + 19, // 7: identity.Entity.creation_time:type_name -> google.protobuf.Timestamp + 19, // 8: identity.Entity.last_update_time:type_name -> google.protobuf.Timestamp + 11, // 9: identity.Entity.mfa_secrets:type_name -> identity.Entity.MFASecretsEntry + 12, // 10: identity.Alias.metadata:type_name -> identity.Alias.MetadataEntry + 19, // 11: identity.Alias.creation_time:type_name -> google.protobuf.Timestamp + 19, // 12: identity.Alias.last_update_time:type_name -> google.protobuf.Timestamp + 13, // 13: identity.Alias.custom_metadata:type_name -> identity.Alias.CustomMetadataEntry 6, // 14: identity.EntityStorageEntry.personas:type_name -> identity.PersonaIndexEntry - 13, // 15: identity.EntityStorageEntry.metadata:type_name -> identity.EntityStorageEntry.MetadataEntry - 17, // 16: identity.EntityStorageEntry.creation_time:type_name -> google.protobuf.Timestamp - 17, // 17: identity.EntityStorageEntry.last_update_time:type_name -> google.protobuf.Timestamp - 14, // 18: identity.EntityStorageEntry.mfa_secrets:type_name -> identity.EntityStorageEntry.MFASecretsEntry - 15, // 19: identity.PersonaIndexEntry.metadata:type_name -> identity.PersonaIndexEntry.MetadataEntry - 17, // 20: identity.PersonaIndexEntry.creation_time:type_name -> google.protobuf.Timestamp - 17, // 21: identity.PersonaIndexEntry.last_update_time:type_name -> google.protobuf.Timestamp - 16, // 22: identity.TPM.metadata:type_name -> identity.TPM.MetadataEntry - 18, // 23: identity.Entity.MFASecretsEntry.value:type_name -> mfa.Secret - 18, // 24: identity.EntityStorageEntry.MFASecretsEntry.value:type_name -> mfa.Secret - 25, // [25:25] is the sub-list for method output_type - 25, // [25:25] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 14, // 15: identity.EntityStorageEntry.metadata:type_name -> identity.EntityStorageEntry.MetadataEntry + 19, // 16: identity.EntityStorageEntry.creation_time:type_name -> google.protobuf.Timestamp + 19, // 17: identity.EntityStorageEntry.last_update_time:type_name -> google.protobuf.Timestamp + 15, // 18: identity.EntityStorageEntry.mfa_secrets:type_name -> identity.EntityStorageEntry.MFASecretsEntry + 16, // 19: identity.PersonaIndexEntry.metadata:type_name -> identity.PersonaIndexEntry.MetadataEntry + 19, // 20: identity.PersonaIndexEntry.creation_time:type_name -> google.protobuf.Timestamp + 19, // 21: identity.PersonaIndexEntry.last_update_time:type_name -> google.protobuf.Timestamp + 17, // 22: identity.TPM.metadata:type_name -> identity.TPM.MetadataEntry + 18, // 23: identity.TPMGroup.metadata:type_name -> identity.TPMGroup.MetadataEntry + 20, // 24: identity.Entity.MFASecretsEntry.value:type_name -> mfa.Secret + 20, // 25: identity.EntityStorageEntry.MFASecretsEntry.value:type_name -> mfa.Secret + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_helper_identity_types_proto_init() } @@ -1496,7 +1617,7 @@ func file_helper_identity_types_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_helper_identity_types_proto_rawDesc), len(file_helper_identity_types_proto_rawDesc)), NumEnums: 0, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 0, }, diff --git a/helper/identity/types.proto b/helper/identity/types.proto index 8e21502a3b..a2c6f1a9e0 100644 --- a/helper/identity/types.proto +++ b/helper/identity/types.proto @@ -376,3 +376,33 @@ message TPM { // @inject_tag: sentinel:"-" string bucket_key = 7; } + +message TPMGroup { + // ID is the unique identifier for this group + // @inject_tag: sentinel:"-" + string id = 1; + + // Name is the unique name for this group + // @inject_tag: sentinel:"-" + string name = 2; + + // Metadata represents the custom data tied with this group + // @inject_tag: sentinel:"-" + map metadata = 3; + + // NamespaceID is the identifier of the namespace to which this group + // belongs to. Do not return this value over the API when reading the + // group. + // @inject_tag: sentinel:"-" + string namespace_id = 4; + + // MemberTpmIDs are the identifiers of entities which are members of this + // group + // @inject_tag: sentinel:"-" + repeated string member_tpm_ids = 5; + + // BucketKey is the path of the storage packer key into which this + // tpmgroup is stored. + // @inject_tag: sentinel:"-" + string bucket_key = 6; +} diff --git a/sdk/logical/identity.pb.go b/sdk/logical/identity.pb.go index 9ee05143c8..b5ffb4fc5d 100644 --- a/sdk/logical/identity.pb.go +++ b/sdk/logical/identity.pb.go @@ -593,6 +593,79 @@ func (x *TPM) GetDisabled() bool { return false } +type TPMGroup struct { + state protoimpl.MessageState `protogen:"open.v1"` + // ID is the unique identifier for the group + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + // Name is the human-friendly unique identifier for the group + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Metadata represents the custom data tied to this group + Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // NamespaceID is the identifier of the namespace to which this group + // belongs to. + NamespaceID string `protobuf:"bytes,4,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TPMGroup) Reset() { + *x = TPMGroup{} + mi := &file_sdk_logical_identity_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TPMGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TPMGroup) ProtoMessage() {} + +func (x *TPMGroup) ProtoReflect() protoreflect.Message { + mi := &file_sdk_logical_identity_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TPMGroup.ProtoReflect.Descriptor instead. +func (*TPMGroup) Descriptor() ([]byte, []int) { + return file_sdk_logical_identity_proto_rawDescGZIP(), []int{7} +} + +func (x *TPMGroup) GetID() string { + if x != nil { + return x.ID + } + return "" +} + +func (x *TPMGroup) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TPMGroup) GetMetadata() map[string]string { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *TPMGroup) GetNamespaceID() string { + if x != nil { + return x.NamespaceID + } + return "" +} + var File_sdk_logical_identity_proto protoreflect.FileDescriptor var file_sdk_logical_identity_proto_rawDesc = string([]byte{ @@ -704,10 +777,23 @@ var file_sdk_logical_identity_proto_rawDesc = string([]byte{ 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x02, 0x38, 0x01, 0x22, 0xcb, 0x01, 0x0a, 0x08, 0x54, 0x50, 0x4d, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, + 0x2e, 0x54, 0x50, 0x4d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x49, 0x64, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, + 0x73, 0x64, 0x6b, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, }) var ( @@ -722,7 +808,7 @@ func file_sdk_logical_identity_proto_rawDescGZIP() []byte { return file_sdk_logical_identity_proto_rawDescData } -var file_sdk_logical_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_sdk_logical_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_sdk_logical_identity_proto_goTypes = []any{ (*Entity)(nil), // 0: logical.Entity (*Alias)(nil), // 1: logical.Alias @@ -731,28 +817,31 @@ var file_sdk_logical_identity_proto_goTypes = []any{ (*MFAConstraintAny)(nil), // 4: logical.MFAConstraintAny (*MFARequirement)(nil), // 5: logical.MFARequirement (*TPM)(nil), // 6: logical.TPM - nil, // 7: logical.Entity.MetadataEntry - nil, // 8: logical.Alias.MetadataEntry - nil, // 9: logical.Alias.CustomMetadataEntry - nil, // 10: logical.Group.MetadataEntry - nil, // 11: logical.MFARequirement.MFAConstraintsEntry - nil, // 12: logical.TPM.MetadataEntry + (*TPMGroup)(nil), // 7: logical.TPMGroup + nil, // 8: logical.Entity.MetadataEntry + nil, // 9: logical.Alias.MetadataEntry + nil, // 10: logical.Alias.CustomMetadataEntry + nil, // 11: logical.Group.MetadataEntry + nil, // 12: logical.MFARequirement.MFAConstraintsEntry + nil, // 13: logical.TPM.MetadataEntry + nil, // 14: logical.TPMGroup.MetadataEntry } var file_sdk_logical_identity_proto_depIDxs = []int32{ 1, // 0: logical.Entity.aliases:type_name -> logical.Alias - 7, // 1: logical.Entity.metadata:type_name -> logical.Entity.MetadataEntry - 8, // 2: logical.Alias.metadata:type_name -> logical.Alias.MetadataEntry - 9, // 3: logical.Alias.custom_metadata:type_name -> logical.Alias.CustomMetadataEntry - 10, // 4: logical.Group.metadata:type_name -> logical.Group.MetadataEntry + 8, // 1: logical.Entity.metadata:type_name -> logical.Entity.MetadataEntry + 9, // 2: logical.Alias.metadata:type_name -> logical.Alias.MetadataEntry + 10, // 3: logical.Alias.custom_metadata:type_name -> logical.Alias.CustomMetadataEntry + 11, // 4: logical.Group.metadata:type_name -> logical.Group.MetadataEntry 3, // 5: logical.MFAConstraintAny.any:type_name -> logical.MFAMethodID - 11, // 6: logical.MFARequirement.mfa_constraints:type_name -> logical.MFARequirement.MFAConstraintsEntry - 12, // 7: logical.TPM.metadata:type_name -> logical.TPM.MetadataEntry - 4, // 8: logical.MFARequirement.MFAConstraintsEntry.value:type_name -> logical.MFAConstraintAny - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 12, // 6: logical.MFARequirement.mfa_constraints:type_name -> logical.MFARequirement.MFAConstraintsEntry + 13, // 7: logical.TPM.metadata:type_name -> logical.TPM.MetadataEntry + 14, // 8: logical.TPMGroup.metadata:type_name -> logical.TPMGroup.MetadataEntry + 4, // 9: logical.MFARequirement.MFAConstraintsEntry.value:type_name -> logical.MFAConstraintAny + 10, // [10:10] is the sub-list for method output_type + 10, // [10:10] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_sdk_logical_identity_proto_init() } @@ -766,7 +855,7 @@ func file_sdk_logical_identity_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_sdk_logical_identity_proto_rawDesc), len(file_sdk_logical_identity_proto_rawDesc)), NumEnums: 0, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 0, }, diff --git a/sdk/logical/identity.proto b/sdk/logical/identity.proto index 7efa2b9133..c651f040a7 100644 --- a/sdk/logical/identity.proto +++ b/sdk/logical/identity.proto @@ -128,3 +128,18 @@ message TPM { // a disabled TPM cannot generate certs or login bool disabled = 6; } + +message TPMGroup { + // ID is the unique identifier for the group + string ID = 1; + + // Name is the human-friendly unique identifier for the group + string name = 2; + + // Metadata represents the custom data tied to this group + map metadata = 3; + + // NamespaceID is the identifier of the namespace to which this group + // belongs to. + string namespace_id = 4; +} diff --git a/sdk/logical/system_view.go b/sdk/logical/system_view.go index 64f5fe5188..9cf768018d 100644 --- a/sdk/logical/system_view.go +++ b/sdk/logical/system_view.go @@ -161,6 +161,10 @@ type ExtendedSystemView interface { // for the given TPM ID. TPMByID(ctx context.Context, id string) (*TPM, error) + // GroupsForTPM returns the TPM group membership information for the provided + // TPM ID. + GroupsForTPM(ctx context.Context, id string) ([]*TPMGroup, error) + // GetPinnedPluginVersion returns the pinned version for the given plugin, if any. GetPinnedPluginVersion(ctx context.Context, pluginType consts.PluginType, pluginName string) (*pluginutil.PinnedVersion, error) } @@ -275,6 +279,10 @@ func (d StaticSystemView) TPMByID(ctx context.Context, id string) (*TPM, error) return nil, errors.New("TPMByID is not implemented in StaticSystemView") } +func (d StaticSystemView) GroupsForTPM(ctx context.Context, id string) ([]*TPMGroup, error) { + return nil, errors.New("GroupsForTPM is not implemented in StaticSystemView") +} + func (d StaticSystemView) HasFeature(feature license.Features) bool { return d.Features.HasFeature(feature) } diff --git a/vault/dynamic_system_view_stubs_oss.go b/vault/dynamic_system_view_stubs_oss.go index 5b845e167e..317ed0585a 100644 --- a/vault/dynamic_system_view_stubs_oss.go +++ b/vault/dynamic_system_view_stubs_oss.go @@ -21,3 +21,7 @@ func (d dynamicSystemView) DownloadExtractVerifyPlugin(_ context.Context, _ *plu func (d dynamicSystemView) TPMByID(ctx context.Context, id string) (*logical.TPM, error) { return nil, fmt.Errorf("enterprise only feature") } + +func (d dynamicSystemView) GroupsForTPM(ctx context.Context, id string) ([]*logical.TPMGroup, error) { + return nil, fmt.Errorf("enterprise only feature") +} diff --git a/vault/identity_store.go b/vault/identity_store.go index 06d69b6667..22b3188639 100644 --- a/vault/identity_store.go +++ b/vault/identity_store.go @@ -35,6 +35,7 @@ const ( groupBucketsPrefix = "packer/group/buckets/" localAliasesBucketsPrefix = "packer/local-aliases/buckets/" tpmBucketsPrefix = "packer/tpm/buckets/" + tpmgroupBucketsPrefix = "packer/tpmgroup/buckets/" ) var ( @@ -127,6 +128,13 @@ func NewIdentityStore(ctx context.Context, core *Core, config *logical.BackendCo return nil, fmt.Errorf("failed to create tpm packer: %w", err) } + tpmgroupsPackerLogger := iStore.logger.Named("storagepacker").Named("tpmgroups") + core.AddLogger(tpmgroupsPackerLogger) + iStore.tpmgroupPacker, err = storagepacker.NewStoragePacker(iStore.view, tpmgroupsPackerLogger, tpmgroupBucketsPrefix) + if err != nil { + return nil, fmt.Errorf("failed to create tpmgroup packer: %w", err) + } + unauthenticatedPaths := []string{ "oidc/.well-known/*", "oidc/+/.well-known/*", @@ -192,6 +200,7 @@ func (i *IdentityStore) paths() []*framework.Path { mfaLoginEnterprisePaths(i), scimPaths(i), tpmPaths(i), + tpmgroupPaths(i), ) } @@ -718,6 +727,8 @@ func (i *IdentityStore) Invalidate(ctx context.Context, key string) { i.invalidateSCIMClient(ctx, key) case strings.HasPrefix(key, tpmBucketsPrefix): i.invalidateTPMBucket(ctx, key) + case strings.HasPrefix(key, tpmgroupBucketsPrefix): + i.invalidateTPMGroupBucket(ctx, key) } } diff --git a/vault/identity_store_schema.go b/vault/identity_store_schema.go index 844ab22f6f..e33315509f 100644 --- a/vault/identity_store_schema.go +++ b/vault/identity_store_schema.go @@ -34,6 +34,7 @@ func identityStoreSchema(lowerCaseName bool) *memdb.DBSchema { oidcClientsTableSchema, scimClientSchema, tpmsTableSchema, + tpmgroupsTableSchema, } for _, schemaFunc := range schemas { diff --git a/vault/identity_store_structs.go b/vault/identity_store_structs.go index 0a6db13090..0d47f55f93 100644 --- a/vault/identity_store_structs.go +++ b/vault/identity_store_structs.go @@ -104,6 +104,10 @@ type IdentityStore struct { // buckets tpmPacker *storagepacker.StoragePacker + // tpmgroupPacker is used to pack multiple TPMGroup storage entries into 256 + // buckets + tpmgroupPacker *storagepacker.StoragePacker + // disableLowerCaseNames indicates whether or not identity artifacts are // operated case insensitively disableLowerCasedNames bool diff --git a/vault/identity_store_tpmgroups_oss.go b/vault/identity_store_tpmgroups_oss.go new file mode 100644 index 0000000000..66c6874845 --- /dev/null +++ b/vault/identity_store_tpmgroups_oss.go @@ -0,0 +1,13 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !enterprise + +package vault + +import "github.com/hashicorp/vault/sdk/framework" + +// tpmgroupPaths returns empty paths for OSS builds +func tpmgroupPaths(i *IdentityStore) []*framework.Path { + return nil +} diff --git a/vault/identity_store_tpmgroups_schema.go b/vault/identity_store_tpmgroups_schema.go new file mode 100644 index 0000000000..7ec9ff339a --- /dev/null +++ b/vault/identity_store_tpmgroups_schema.go @@ -0,0 +1,61 @@ +// Copyright IBM Corp. 2016, 2026 +// SPDX-License-Identifier: BUSL-1.1 + +package vault + +import ( + memdb "github.com/hashicorp/go-memdb" +) + +const ( + tpmgroupsTable = "tpmgroups" +) + +func tpmgroupsTableSchema(lowerCaseName bool) *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tpmgroupsTable, + Indexes: map[string]*memdb.IndexSchema{ + "id": { + Name: "id", + Unique: true, + Indexer: &memdb.StringFieldIndex{ + Field: "ID", + }, + }, + "name": { + Name: "name", + Unique: true, + Indexer: &memdb.CompoundIndex{ + Indexes: []memdb.Indexer{ + &memdb.StringFieldIndex{ + Field: "NamespaceID", + }, + &memdb.StringFieldIndex{ + Field: "Name", + Lowercase: lowerCaseName, + }, + }, + }, + }, + "namespace_id": { + Name: "namespace_id", + Indexer: &memdb.StringFieldIndex{ + Field: "NamespaceID", + }, + }, + "member_tpm_ids": { + Name: "member_tpm_ids", + AllowMissing: true, + Indexer: &memdb.StringSliceFieldIndex{ + Field: "MemberTpmIDs", + }, + }, + "bucket_key": { + Name: "bucket_key", + Indexer: &memdb.StringFieldIndex{ + Field: "BucketKey", + }, + }, + }, + } +} diff --git a/vault/identity_store_tpmgroups_util_oss.go b/vault/identity_store_tpmgroups_util_oss.go new file mode 100644 index 0000000000..f60ba1bacb --- /dev/null +++ b/vault/identity_store_tpmgroups_util_oss.go @@ -0,0 +1,16 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !enterprise + +package vault + +import "context" + +// loadTPMGroups is a no-op for OSS builds +func (i *IdentityStore) loadTPMGroups(ctx context.Context) error { + return nil +} + +// invalidateTPMGroupBucket is a no-op for OSS builds +func (i *IdentityStore) invalidateTPMGroupBucket(ctx context.Context, key string) {} diff --git a/vault/identity_store_util.go b/vault/identity_store_util.go index c8dd5ca5dc..b13458512a 100644 --- a/vault/identity_store_util.go +++ b/vault/identity_store_util.go @@ -116,6 +116,10 @@ func (i *IdentityStore) loadArtifacts(ctx context.Context, isActive bool) error return fmt.Errorf("failed to load TPMs: %w", err) } + if err := i.loadTPMGroups(ctx); err != nil { + return fmt.Errorf("failed to load TPMGroups: %w", err) + } + return nil }