From 3cbb1780ea7bed421acaf2db2c087a466e83a69e Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 14:27:00 -0700 Subject: [PATCH 01/14] adding changes --- helper/forwarding/types.pb.go | 2 +- helper/identity/mfa/types.pb.go | 2 +- helper/identity/types.pb.go | 84 +++++++----- helper/identity/types.proto | 5 + helper/storagepacker/types.pb.go | 2 +- physical/raft/types.pb.go | 2 +- sdk/database/dbplugin/database.pb.go | 2 +- sdk/database/dbplugin/v5/proto/database.pb.go | 2 +- sdk/logical/identity.pb.go | 2 +- sdk/logical/plugin.pb.go | 2 +- sdk/plugin/pb/backend.pb.go | 2 +- vault/activity/activity_log.pb.go | 2 +- vault/identity_store_aliases.go | 126 +++++++++++++++--- vault/identity_store_util.go | 7 +- vault/request_forwarding_service.pb.go | 2 +- 15 files changed, 183 insertions(+), 61 deletions(-) diff --git a/helper/forwarding/types.pb.go b/helper/forwarding/types.pb.go index be61f311a1a63..b7ffa70569e09 100644 --- a/helper/forwarding/types.pb.go +++ b/helper/forwarding/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: helper/forwarding/types.proto diff --git a/helper/identity/mfa/types.pb.go b/helper/identity/mfa/types.pb.go index 5230f4a1b2a2e..19724c2eebee0 100644 --- a/helper/identity/mfa/types.pb.go +++ b/helper/identity/mfa/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: helper/identity/mfa/types.proto diff --git a/helper/identity/types.pb.go b/helper/identity/types.pb.go index a5bd81f8df1a7..bedcd48089017 100644 --- a/helper/identity/types.pb.go +++ b/helper/identity/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: helper/identity/types.proto @@ -405,6 +405,8 @@ type Alias struct { // NamespaceID is the identifier of the namespace to which this alias // belongs. NamespaceID string `sentinel:"" protobuf:"bytes,11,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty"` + // Custom Metadata + CustomMetadata map[string]string `sentinel:"" protobuf:"bytes,12,rep,name=customMetadata,proto3" json:"customMetadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Alias) Reset() { @@ -516,6 +518,13 @@ func (x *Alias) GetNamespaceID() string { return "" } +func (x *Alias) GetCustomMetadata() map[string]string { + if x != nil { + return x.CustomMetadata + } + return nil +} + // Deprecated. Retained for backwards compatibility. type EntityStorageEntry struct { state protoimpl.MessageState @@ -842,7 +851,7 @@ var file_helper_identity_types_proto_rawDesc = []byte{ 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x6d, 0x66, 0x61, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x90, 0x04, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x05, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, @@ -871,8 +880,17 @@ var file_helper_identity_types_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x16, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0b, 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, + 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4b, 0x0a, + 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 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, 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x75, 0x73, 0x74, 0x6f, + 0x6d, 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, 0x22, 0x88, 0x05, 0x0a, 0x12, 0x45, @@ -966,7 +984,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, 12) +var file_helper_identity_types_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_helper_identity_types_proto_goTypes = []interface{}{ (*Group)(nil), // 0: identity.Group (*Entity)(nil), // 1: identity.Entity @@ -977,40 +995,42 @@ var file_helper_identity_types_proto_goTypes = []interface{}{ nil, // 6: identity.Entity.MetadataEntry nil, // 7: identity.Entity.MFASecretsEntry nil, // 8: identity.Alias.MetadataEntry - nil, // 9: identity.EntityStorageEntry.MetadataEntry - nil, // 10: identity.EntityStorageEntry.MFASecretsEntry - nil, // 11: identity.PersonaIndexEntry.MetadataEntry - (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp - (*mfa.Secret)(nil), // 13: mfa.Secret + nil, // 9: identity.Alias.CustomMetadataEntry + nil, // 10: identity.EntityStorageEntry.MetadataEntry + nil, // 11: identity.EntityStorageEntry.MFASecretsEntry + nil, // 12: identity.PersonaIndexEntry.MetadataEntry + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp + (*mfa.Secret)(nil), // 14: mfa.Secret } var file_helper_identity_types_proto_depIDxs = []int32{ 5, // 0: identity.Group.metadata:type_name -> identity.Group.MetadataEntry - 12, // 1: identity.Group.creation_time:type_name -> google.protobuf.Timestamp - 12, // 2: identity.Group.last_update_time:type_name -> google.protobuf.Timestamp + 13, // 1: identity.Group.creation_time:type_name -> google.protobuf.Timestamp + 13, // 2: identity.Group.last_update_time:type_name -> google.protobuf.Timestamp 2, // 3: identity.Group.alias:type_name -> identity.Alias 2, // 4: identity.Entity.aliases:type_name -> identity.Alias 6, // 5: identity.Entity.metadata:type_name -> identity.Entity.MetadataEntry - 12, // 6: identity.Entity.creation_time:type_name -> google.protobuf.Timestamp - 12, // 7: identity.Entity.last_update_time:type_name -> google.protobuf.Timestamp + 13, // 6: identity.Entity.creation_time:type_name -> google.protobuf.Timestamp + 13, // 7: identity.Entity.last_update_time:type_name -> google.protobuf.Timestamp 7, // 8: identity.Entity.mfa_secrets:type_name -> identity.Entity.MFASecretsEntry 8, // 9: identity.Alias.metadata:type_name -> identity.Alias.MetadataEntry - 12, // 10: identity.Alias.creation_time:type_name -> google.protobuf.Timestamp - 12, // 11: identity.Alias.last_update_time:type_name -> google.protobuf.Timestamp - 4, // 12: identity.EntityStorageEntry.personas:type_name -> identity.PersonaIndexEntry - 9, // 13: identity.EntityStorageEntry.metadata:type_name -> identity.EntityStorageEntry.MetadataEntry - 12, // 14: identity.EntityStorageEntry.creation_time:type_name -> google.protobuf.Timestamp - 12, // 15: identity.EntityStorageEntry.last_update_time:type_name -> google.protobuf.Timestamp - 10, // 16: identity.EntityStorageEntry.mfa_secrets:type_name -> identity.EntityStorageEntry.MFASecretsEntry - 11, // 17: identity.PersonaIndexEntry.metadata:type_name -> identity.PersonaIndexEntry.MetadataEntry - 12, // 18: identity.PersonaIndexEntry.creation_time:type_name -> google.protobuf.Timestamp - 12, // 19: identity.PersonaIndexEntry.last_update_time:type_name -> google.protobuf.Timestamp - 13, // 20: identity.Entity.MFASecretsEntry.value:type_name -> mfa.Secret - 13, // 21: identity.EntityStorageEntry.MFASecretsEntry.value:type_name -> mfa.Secret - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 13, // 10: identity.Alias.creation_time:type_name -> google.protobuf.Timestamp + 13, // 11: identity.Alias.last_update_time:type_name -> google.protobuf.Timestamp + 9, // 12: identity.Alias.customMetadata:type_name -> identity.Alias.CustomMetadataEntry + 4, // 13: identity.EntityStorageEntry.personas:type_name -> identity.PersonaIndexEntry + 10, // 14: identity.EntityStorageEntry.metadata:type_name -> identity.EntityStorageEntry.MetadataEntry + 13, // 15: identity.EntityStorageEntry.creation_time:type_name -> google.protobuf.Timestamp + 13, // 16: identity.EntityStorageEntry.last_update_time:type_name -> google.protobuf.Timestamp + 11, // 17: identity.EntityStorageEntry.mfa_secrets:type_name -> identity.EntityStorageEntry.MFASecretsEntry + 12, // 18: identity.PersonaIndexEntry.metadata:type_name -> identity.PersonaIndexEntry.MetadataEntry + 13, // 19: identity.PersonaIndexEntry.creation_time:type_name -> google.protobuf.Timestamp + 13, // 20: identity.PersonaIndexEntry.last_update_time:type_name -> google.protobuf.Timestamp + 14, // 21: identity.Entity.MFASecretsEntry.value:type_name -> mfa.Secret + 14, // 22: identity.EntityStorageEntry.MFASecretsEntry.value:type_name -> mfa.Secret + 23, // [23:23] is the sub-list for method output_type + 23, // [23:23] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_helper_identity_types_proto_init() } @@ -1086,7 +1106,7 @@ func file_helper_identity_types_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_helper_identity_types_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/helper/identity/types.proto b/helper/identity/types.proto index 8fed733436d47..ad43b054497ad 100644 --- a/helper/identity/types.proto +++ b/helper/identity/types.proto @@ -172,6 +172,11 @@ message Alias { // NamespaceID is the identifier of the namespace to which this alias // belongs. string namespace_id = 11; + + // Custom Metadata + map customMetadata = 12; + + } // Deprecated. Retained for backwards compatibility. diff --git a/helper/storagepacker/types.pb.go b/helper/storagepacker/types.pb.go index ba00547df72c1..7763a09b578b6 100644 --- a/helper/storagepacker/types.pb.go +++ b/helper/storagepacker/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: helper/storagepacker/types.proto diff --git a/physical/raft/types.pb.go b/physical/raft/types.pb.go index 07a5a30ec977e..98dc729828816 100644 --- a/physical/raft/types.pb.go +++ b/physical/raft/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: physical/raft/types.proto diff --git a/sdk/database/dbplugin/database.pb.go b/sdk/database/dbplugin/database.pb.go index 2bd3b2ffc8b0d..4367193429133 100644 --- a/sdk/database/dbplugin/database.pb.go +++ b/sdk/database/dbplugin/database.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: sdk/database/dbplugin/database.proto diff --git a/sdk/database/dbplugin/v5/proto/database.pb.go b/sdk/database/dbplugin/v5/proto/database.pb.go index 9f72fda53bffc..ce4e2ca034c70 100644 --- a/sdk/database/dbplugin/v5/proto/database.pb.go +++ b/sdk/database/dbplugin/v5/proto/database.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: sdk/database/dbplugin/v5/proto/database.proto diff --git a/sdk/logical/identity.pb.go b/sdk/logical/identity.pb.go index 0a99bc74e13d1..f66ad7a304f45 100644 --- a/sdk/logical/identity.pb.go +++ b/sdk/logical/identity.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: sdk/logical/identity.proto diff --git a/sdk/logical/plugin.pb.go b/sdk/logical/plugin.pb.go index 539e0579aaf51..46de77666df8d 100644 --- a/sdk/logical/plugin.pb.go +++ b/sdk/logical/plugin.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: sdk/logical/plugin.proto diff --git a/sdk/plugin/pb/backend.pb.go b/sdk/plugin/pb/backend.pb.go index 9b550a0c52e40..ca67fc343b2eb 100644 --- a/sdk/plugin/pb/backend.pb.go +++ b/sdk/plugin/pb/backend.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: sdk/plugin/pb/backend.proto diff --git a/vault/activity/activity_log.pb.go b/vault/activity/activity_log.pb.go index 3c94d2bbd23d5..3b5c90dba0d6b 100644 --- a/vault/activity/activity_log.pb.go +++ b/vault/activity/activity_log.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: vault/activity/activity_log.proto diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 422e25a97b102..a5b8a16f4bb43 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -3,9 +3,14 @@ package vault import ( "context" "fmt" + "reflect" "strings" + "q" + "github.com/golang/protobuf/ptypes" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/vault/helper/identity" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/helper/storagepacker" @@ -13,6 +18,13 @@ import ( "github.com/hashicorp/vault/sdk/logical" ) +//TODO : ask correct place to add these consts + +const maxCustomMetadataKeys = 64 +const maxCustomMetadataKeyLength = 128 +const maxCustomMetadataValueLength = 512 +const customMetadataValidationErrorPrefix = "custom_metadata validation failed" + // aliasPaths returns the API endpoints to operate on aliases. // Following are the paths supported: // entity-alias - To register/modify an alias @@ -44,6 +56,11 @@ This field is deprecated, use canonical_id.`, Type: framework.TypeString, Description: "Name of the alias; unused for a modify", }, + //TODO : add cutom metadata here + "custom_metadata": { + Type: framework.TypeKVPairs, + Description: "User-provided key-value pairs", + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ logical.UpdateOperation: i.handleAliasCreateUpdate(), @@ -77,6 +94,11 @@ This field is deprecated, use canonical_id.`, Type: framework.TypeString, Description: "(Unused)", }, + //TODO : add cutom metadata here + "custom_metadata": { + Type: framework.TypeKVPairs, + Description: "User-provided key-value pairs", + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ logical.UpdateOperation: i.handleAliasCreateUpdate(), @@ -103,7 +125,7 @@ This field is deprecated, use canonical_id.`, func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { var err error - + q.Q("Create update alias function") ns, err := namespace.FromContext(ctx) if err != nil { return nil, err @@ -118,6 +140,9 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { // Get ID, if any id := d.Get("id").(string) + // Get custom metadata, if any + customMetadata := d.Get("custom_metadata").(map[string]string) + // Get entity id canonicalID := d.Get("canonical_id").(string) if canonicalID == "" { @@ -125,6 +150,15 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { canonicalID = d.Get("entity_id").(string) } + //validate customMetadata if provided + if customMetadata != nil { + + err := validateCustomMetadata(customMetadata) + if err != nil { + return nil, err + } + } + i.lock.Lock() defer i.lock.Unlock() @@ -145,8 +179,9 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { } switch { - case mountAccessor == "" && name == "": + case mountAccessor == "" && name == "" && customMetadata == nil: // Just a canonical ID update, maybe + //TODO: need to also check for custom metadata befor returning if canonicalID == "" { // Nothing to do, so be idempotent return nil, nil @@ -154,6 +189,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { name = alias.Name mountAccessor = alias.MountAccessor + customMetadata = alias.CustomMetadata case mountAccessor == "": // No change to mount accessor @@ -163,11 +199,15 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { // No change to mount name name = alias.Name + case customMetadata == nil: + // No change to custom metadata + customMetadata = alias.CustomMetadata + default: - // Both provided + // mountAccessor,name and customMetadata provided } - return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias) + return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias, customMetadata) } } @@ -196,23 +236,25 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { return logical.ErrorResponse("cannot modify aliases across namespaces"), logical.ErrPermissionDenied } - return i.handleAliasUpdate(ctx, req, alias.CanonicalID, name, mountAccessor, alias) + return i.handleAliasUpdate(ctx, req, alias.CanonicalID, name, mountAccessor, alias, customMetadata) } - // At this point we know it's a new creation request - return i.handleAliasCreate(ctx, req, canonicalID, name, mountAccessor) + return i.handleAliasCreate(ctx, req, canonicalID, name, mountAccessor, customMetadata) } } -func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string) (*logical.Response, error) { +func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, customMetadata map[string]string) (*logical.Response, error) { + q.Q("Alias Creation ") + ns, err := namespace.FromContext(ctx) if err != nil { return nil, err } alias := &identity.Alias{ - MountAccessor: mountAccessor, - Name: name, + MountAccessor: mountAccessor, + Name: name, + CustomMetadata: customMetadata, } entity := &identity.Entity{} @@ -266,10 +308,11 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ }, nil } -func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias) (*logical.Response, error) { +func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias, customMetadata map[string]string) (*logical.Response, error) { + q.Q("Alias Update function") if name == alias.Name && mountAccessor == alias.MountAccessor && - (canonicalID == alias.CanonicalID || canonicalID == "") { + (canonicalID == alias.CanonicalID || canonicalID == "") && (reflect.DeepEqual(customMetadata, alias.CustomMetadata)) { // Nothing to do; return nil to be idempotent return nil, nil } @@ -279,7 +322,7 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ // If we're changing one or the other or both of these, make sure that // there isn't a matching alias already, and make sure it's in the same // namespace. - if name != alias.Name || mountAccessor != alias.MountAccessor { + if name != alias.Name || mountAccessor != alias.MountAccessor || !reflect.DeepEqual(customMetadata, alias.CustomMetadata) { // Check here to see if such an alias already exists, if so bail mountEntry := i.router.MatchingMountByAccessor(mountAccessor) if mountEntry == nil { @@ -296,14 +339,16 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ if err != nil { return nil, err } - // Bail unless it's just a case change - if existingAlias != nil && !strings.EqualFold(existingAlias.Name, name) { + + // Bail unless it's just a case change or no custom meta data change + if existingAlias != nil && !strings.EqualFold(existingAlias.Name, name) && reflect.DeepEqual(customMetadata, alias.CustomMetadata) { return logical.ErrorResponse("alias with combination of mount accessor and name already exists"), nil } // Update the values in the alias alias.Name = name alias.MountAccessor = mountAccessor + alias.CustomMetadata = customMetadata } // Get our current entity, which may be the same as the new one if the @@ -373,6 +418,56 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ }, nil } +//TODO: ask if we can use the same validation code from kv secrets plugin +func validateCustomMetadata(customMetadata map[string]string) error { + var errs *multierror.Error + + if keyCount := len(customMetadata); keyCount > maxCustomMetadataKeys { + errs = multierror.Append(errs, fmt.Errorf("%s: payload must contain at most %d keys, provided %d", + customMetadataValidationErrorPrefix, + maxCustomMetadataKeys, + keyCount)) + + return errs.ErrorOrNil() + } + + // Perform validation on each key and value and return ALL errors + for key, value := range customMetadata { + if keyLen := len(key); 0 == keyLen || keyLen > maxCustomMetadataKeyLength { + errs = multierror.Append(errs, fmt.Errorf("%s: length of key %q is %d but must be 0 < len(key) <= %d", + customMetadataValidationErrorPrefix, + key, + keyLen, + maxCustomMetadataKeyLength)) + } + + if valueLen := len(value); 0 == valueLen || valueLen > maxCustomMetadataValueLength { + errs = multierror.Append(errs, fmt.Errorf("%s: length of value for key %q is %d but must be 0 < len(value) <= %d", + customMetadataValidationErrorPrefix, + key, + valueLen, + maxCustomMetadataValueLength)) + } + + if !strutil.Printable(key) { + // Include unquoted format (%s) to also include the string without the unprintable + // characters visible to allow for easier debug and key identification + errs = multierror.Append(errs, fmt.Errorf("%s: key %q (%s) contains unprintable characters", + customMetadataValidationErrorPrefix, + key, + key)) + } + + if !strutil.Printable(value) { + errs = multierror.Append(errs, fmt.Errorf("%s: value for key %q contains unprintable characters", + customMetadataValidationErrorPrefix, + key)) + } + } + + return errs.ErrorOrNil() +} + // pathAliasIDRead returns the properties of an alias for a given // alias ID func (i *IdentityStore) pathAliasIDRead() framework.OperationFunc { @@ -409,6 +504,7 @@ func (i *IdentityStore) handleAliasReadCommon(ctx context.Context, alias *identi respData["canonical_id"] = alias.CanonicalID respData["mount_accessor"] = alias.MountAccessor respData["metadata"] = alias.Metadata + respData["customMetadata"] = alias.CustomMetadata respData["name"] = alias.Name respData["merged_from_canonical_ids"] = alias.MergedFromCanonicalIDs respData["namespace_id"] = alias.NamespaceID diff --git a/vault/identity_store_util.go b/vault/identity_store_util.go index 99e556ac9e07c..53b347f4e284f 100644 --- a/vault/identity_store_util.go +++ b/vault/identity_store_util.go @@ -2080,9 +2080,10 @@ func (i *IdentityStore) handleAliasListCommon(ctx context.Context, groupAlias bo alias := raw.(*identity.Alias) aliasIDs = append(aliasIDs, alias.ID) aliasInfoEntry := map[string]interface{}{ - "name": alias.Name, - "canonical_id": alias.CanonicalID, - "mount_accessor": alias.MountAccessor, + "name": alias.Name, + "canonical_id": alias.CanonicalID, + "mount_accessor": alias.MountAccessor, + "custom_metadata": alias.CustomMetadata, } mi, ok := mountAccessorMap[alias.MountAccessor] diff --git a/vault/request_forwarding_service.pb.go b/vault/request_forwarding_service.pb.go index ecf5e0da93394..40f696dad190e 100644 --- a/vault/request_forwarding_service.pb.go +++ b/vault/request_forwarding_service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 +// protoc-gen-go v1.27.1 // protoc v3.17.3 // source: vault/request_forwarding_service.proto From b4a59e22687576ff178fcd2c27153a1c92aeb422 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 14:35:57 -0700 Subject: [PATCH 02/14] removing q.Q --- vault/identity_store_aliases.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index a5b8a16f4bb43..bed9f33049ec4 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -6,8 +6,6 @@ import ( "reflect" "strings" - "q" - "github.com/golang/protobuf/ptypes" "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-secure-stdlib/strutil" @@ -18,8 +16,6 @@ import ( "github.com/hashicorp/vault/sdk/logical" ) -//TODO : ask correct place to add these consts - const maxCustomMetadataKeys = 64 const maxCustomMetadataKeyLength = 128 const maxCustomMetadataValueLength = 512 @@ -56,7 +52,6 @@ This field is deprecated, use canonical_id.`, Type: framework.TypeString, Description: "Name of the alias; unused for a modify", }, - //TODO : add cutom metadata here "custom_metadata": { Type: framework.TypeKVPairs, Description: "User-provided key-value pairs", @@ -94,7 +89,6 @@ This field is deprecated, use canonical_id.`, Type: framework.TypeString, Description: "(Unused)", }, - //TODO : add cutom metadata here "custom_metadata": { Type: framework.TypeKVPairs, Description: "User-provided key-value pairs", @@ -125,7 +119,7 @@ This field is deprecated, use canonical_id.`, func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { var err error - q.Q("Create update alias function") + ns, err := namespace.FromContext(ctx) if err != nil { return nil, err @@ -181,7 +175,6 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { switch { case mountAccessor == "" && name == "" && customMetadata == nil: // Just a canonical ID update, maybe - //TODO: need to also check for custom metadata befor returning if canonicalID == "" { // Nothing to do, so be idempotent return nil, nil @@ -244,8 +237,6 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { } func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, customMetadata map[string]string) (*logical.Response, error) { - q.Q("Alias Creation ") - ns, err := namespace.FromContext(ctx) if err != nil { return nil, err @@ -309,7 +300,6 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ } func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias, customMetadata map[string]string) (*logical.Response, error) { - q.Q("Alias Update function") if name == alias.Name && mountAccessor == alias.MountAccessor && (canonicalID == alias.CanonicalID || canonicalID == "") && (reflect.DeepEqual(customMetadata, alias.CustomMetadata)) { @@ -504,7 +494,7 @@ func (i *IdentityStore) handleAliasReadCommon(ctx context.Context, alias *identi respData["canonical_id"] = alias.CanonicalID respData["mount_accessor"] = alias.MountAccessor respData["metadata"] = alias.Metadata - respData["customMetadata"] = alias.CustomMetadata + respData["custom_metadata"] = alias.CustomMetadata respData["name"] = alias.Name respData["merged_from_canonical_ids"] = alias.MergedFromCanonicalIDs respData["namespace_id"] = alias.NamespaceID From fbe128279b40432beb6513487c41f2d2039eec1b Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 14:42:49 -0700 Subject: [PATCH 03/14] removing empty lines --- vault/identity_store_aliases.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index bed9f33049ec4..aff78be3ac7bb 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -3,9 +3,6 @@ package vault import ( "context" "fmt" - "reflect" - "strings" - "github.com/golang/protobuf/ptypes" "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-secure-stdlib/strutil" @@ -14,6 +11,8 @@ import ( "github.com/hashicorp/vault/helper/storagepacker" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" + "reflect" + "strings" ) const maxCustomMetadataKeys = 64 From b002bd787d2224fd607f4e4623649e94bf0d8b8e Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 15:00:02 -0700 Subject: [PATCH 04/14] testing --- vault/identity_store_aliases.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index aff78be3ac7bb..5499da099804f 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -3,6 +3,11 @@ package vault import ( "context" "fmt" + "reflect" + "strings" + + "q" + "github.com/golang/protobuf/ptypes" "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-secure-stdlib/strutil" @@ -11,8 +16,6 @@ import ( "github.com/hashicorp/vault/helper/storagepacker" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" - "reflect" - "strings" ) const maxCustomMetadataKeys = 64 @@ -236,6 +239,8 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { } func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, customMetadata map[string]string) (*logical.Response, error) { + + q.Q("alias creation") ns, err := namespace.FromContext(ctx) if err != nil { return nil, err @@ -246,6 +251,8 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ Name: name, CustomMetadata: customMetadata, } + q.Q("alias") + q.Q(alias) entity := &identity.Entity{} // If a canonical ID is provided pull up the entity and make sure we're in @@ -299,6 +306,13 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ } func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias, customMetadata map[string]string) (*logical.Response, error) { + q.Q("alias update") + + q.Q(req) + q.Q(canonicalID) + q.Q(name) + q.Q(mountAccessor) + q.Q(alias) if name == alias.Name && mountAccessor == alias.MountAccessor && (canonicalID == alias.CanonicalID || canonicalID == "") && (reflect.DeepEqual(customMetadata, alias.CustomMetadata)) { @@ -311,6 +325,7 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ // If we're changing one or the other or both of these, make sure that // there isn't a matching alias already, and make sure it's in the same // namespace. + q.Q("1") if name != alias.Name || mountAccessor != alias.MountAccessor || !reflect.DeepEqual(customMetadata, alias.CustomMetadata) { // Check here to see if such an alias already exists, if so bail mountEntry := i.router.MatchingMountByAccessor(mountAccessor) @@ -323,9 +338,11 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ if mountEntry.NamespaceID != alias.NamespaceID { return logical.ErrorResponse("given mount accessor is not in the same namespace as the existing alias"), logical.ErrPermissionDenied } + q.Q("2") existingAlias, err := i.MemDBAliasByFactors(mountAccessor, name, false, false) if err != nil { + q.Q(err.Error()) return nil, err } @@ -339,13 +356,14 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ alias.MountAccessor = mountAccessor alias.CustomMetadata = customMetadata } - + q.Q("3") // Get our current entity, which may be the same as the new one if the // canonical ID hasn't changed currentEntity, err := i.MemDBEntityByAliasID(alias.ID, true) if err != nil { return nil, err } + q.Q(currentEntity) if currentEntity == nil { return logical.ErrorResponse("given alias is not associated with an entity"), nil } From 8a98e7593e15e315592d5f30bb6d06c794111825 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 15:29:33 -0700 Subject: [PATCH 05/14] checking tests --- vault/identity_store_aliases.go | 10 +++++++--- vault/identity_store_aliases_test.go | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 5499da099804f..91e0a43810a75 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -163,10 +163,13 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { // If they provide an ID it must be an update. Find the alias, perform // due diligence, call the update function. if id != "" { + q.Q(" before get alias by id ") alias, err := i.MemDBAliasByID(id, true, false) if err != nil { return nil, err } + q.Q("get alias by id ") + q.Q(alias) if alias == nil { return logical.ErrorResponse("invalid alias ID provided"), nil } @@ -181,7 +184,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { // Nothing to do, so be idempotent return nil, nil } - + q.Q("before name 1") name = alias.Name mountAccessor = alias.MountAccessor customMetadata = alias.CustomMetadata @@ -189,7 +192,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { case mountAccessor == "": // No change to mount accessor mountAccessor = alias.MountAccessor - + q.Q("before name ") case name == "": // No change to mount name name = alias.Name @@ -201,7 +204,8 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { default: // mountAccessor,name and customMetadata provided } - + q.Q("here 1") + q.Q(name) return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias, customMetadata) } } diff --git a/vault/identity_store_aliases_test.go b/vault/identity_store_aliases_test.go index a0779c68adc0f..406541cac7f18 100644 --- a/vault/identity_store_aliases_test.go +++ b/vault/identity_store_aliases_test.go @@ -1,6 +1,7 @@ package vault import ( + "q" "reflect" "strings" "testing" @@ -38,6 +39,8 @@ func TestIdentityStore_DuplicateAliases(t *testing.T) { } aliasID := resp.Data["id"].(string) + q.Q(aliasID) + // Create another entity without an alias resp, err = c.identityStore.HandleRequest(namespace.RootContext(nil), &logical.Request{ Path: "entity", From 5b0dea6e301db453be8373f1ab87804fa3015f04 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 7 Sep 2021 16:39:18 -0700 Subject: [PATCH 06/14] fixing tests --- vault/identity_store_aliases.go | 34 ++++------------------------ vault/identity_store_aliases_test.go | 3 --- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 91e0a43810a75..a1fc4511d0199 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -6,8 +6,6 @@ import ( "reflect" "strings" - "q" - "github.com/golang/protobuf/ptypes" "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-secure-stdlib/strutil" @@ -147,7 +145,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { } //validate customMetadata if provided - if customMetadata != nil { + if len(customMetadata) != 0 { err := validateCustomMetadata(customMetadata) if err != nil { @@ -163,28 +161,23 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { // If they provide an ID it must be an update. Find the alias, perform // due diligence, call the update function. if id != "" { - q.Q(" before get alias by id ") alias, err := i.MemDBAliasByID(id, true, false) if err != nil { return nil, err } - q.Q("get alias by id ") - q.Q(alias) if alias == nil { return logical.ErrorResponse("invalid alias ID provided"), nil } if alias.NamespaceID != ns.ID { return logical.ErrorResponse("cannot modify aliases across namespaces"), logical.ErrPermissionDenied } - switch { - case mountAccessor == "" && name == "" && customMetadata == nil: + case mountAccessor == "" && name == "" && len(customMetadata) == 0: // Just a canonical ID update, maybe if canonicalID == "" { // Nothing to do, so be idempotent return nil, nil } - q.Q("before name 1") name = alias.Name mountAccessor = alias.MountAccessor customMetadata = alias.CustomMetadata @@ -192,20 +185,16 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { case mountAccessor == "": // No change to mount accessor mountAccessor = alias.MountAccessor - q.Q("before name ") case name == "": // No change to mount name name = alias.Name - - case customMetadata == nil: + case len(customMetadata) == 0: // No change to custom metadata customMetadata = alias.CustomMetadata default: // mountAccessor,name and customMetadata provided } - q.Q("here 1") - q.Q(name) return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias, customMetadata) } } @@ -243,8 +232,6 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { } func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, customMetadata map[string]string) (*logical.Response, error) { - - q.Q("alias creation") ns, err := namespace.FromContext(ctx) if err != nil { return nil, err @@ -255,8 +242,7 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ Name: name, CustomMetadata: customMetadata, } - q.Q("alias") - q.Q(alias) + entity := &identity.Entity{} // If a canonical ID is provided pull up the entity and make sure we're in @@ -310,13 +296,6 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ } func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias, customMetadata map[string]string) (*logical.Response, error) { - q.Q("alias update") - - q.Q(req) - q.Q(canonicalID) - q.Q(name) - q.Q(mountAccessor) - q.Q(alias) if name == alias.Name && mountAccessor == alias.MountAccessor && (canonicalID == alias.CanonicalID || canonicalID == "") && (reflect.DeepEqual(customMetadata, alias.CustomMetadata)) { @@ -329,7 +308,6 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ // If we're changing one or the other or both of these, make sure that // there isn't a matching alias already, and make sure it's in the same // namespace. - q.Q("1") if name != alias.Name || mountAccessor != alias.MountAccessor || !reflect.DeepEqual(customMetadata, alias.CustomMetadata) { // Check here to see if such an alias already exists, if so bail mountEntry := i.router.MatchingMountByAccessor(mountAccessor) @@ -342,11 +320,9 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ if mountEntry.NamespaceID != alias.NamespaceID { return logical.ErrorResponse("given mount accessor is not in the same namespace as the existing alias"), logical.ErrPermissionDenied } - q.Q("2") existingAlias, err := i.MemDBAliasByFactors(mountAccessor, name, false, false) if err != nil { - q.Q(err.Error()) return nil, err } @@ -360,14 +336,12 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ alias.MountAccessor = mountAccessor alias.CustomMetadata = customMetadata } - q.Q("3") // Get our current entity, which may be the same as the new one if the // canonical ID hasn't changed currentEntity, err := i.MemDBEntityByAliasID(alias.ID, true) if err != nil { return nil, err } - q.Q(currentEntity) if currentEntity == nil { return logical.ErrorResponse("given alias is not associated with an entity"), nil } diff --git a/vault/identity_store_aliases_test.go b/vault/identity_store_aliases_test.go index 406541cac7f18..a0779c68adc0f 100644 --- a/vault/identity_store_aliases_test.go +++ b/vault/identity_store_aliases_test.go @@ -1,7 +1,6 @@ package vault import ( - "q" "reflect" "strings" "testing" @@ -39,8 +38,6 @@ func TestIdentityStore_DuplicateAliases(t *testing.T) { } aliasID := resp.Data["id"].(string) - q.Q(aliasID) - // Create another entity without an alias resp, err = c.identityStore.HandleRequest(namespace.RootContext(nil), &logical.Request{ Path: "entity", From 8d96cd217d419d0c9976bded15a29738e220571d Mon Sep 17 00:00:00 2001 From: akshya96 Date: Thu, 9 Sep 2021 16:56:03 -0700 Subject: [PATCH 07/14] adding changes --- helper/identity/identity.go | 13 +++++---- sdk/helper/identitytpl/templating.go | 11 +++++++- sdk/logical/identity.pb.go | 42 ++++++++++++++++++++-------- sdk/logical/identity.proto | 3 ++ 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/helper/identity/identity.go b/helper/identity/identity.go index c50dec2686aa4..4f8eb6d4257c3 100644 --- a/helper/identity/identity.go +++ b/helper/identity/identity.go @@ -75,12 +75,13 @@ func ToSDKAlias(a *Alias) *logical.Alias { } return &logical.Alias{ - Name: a.Name, - ID: a.ID, - MountAccessor: a.MountAccessor, - MountType: a.MountType, - Metadata: metadata, - NamespaceID: a.NamespaceID, + Name: a.Name, + ID: a.ID, + MountAccessor: a.MountAccessor, + MountType: a.MountType, + Metadata: metadata, + NamespaceID: a.NamespaceID, + CustomMetadata: a.CustomMetadata, } } diff --git a/sdk/helper/identitytpl/templating.go b/sdk/helper/identitytpl/templating.go index 85166bf4f28e5..6d84df8241ded 100644 --- a/sdk/helper/identitytpl/templating.go +++ b/sdk/helper/identitytpl/templating.go @@ -178,6 +178,15 @@ func performTemplating(input string, p *PopulateStringInput) (string, error) { case strings.HasPrefix(trimmed, "metadata."): split := strings.SplitN(trimmed, ".", 2) return p.templateHandler(alias.Metadata, split[1]) + + case trimmed == "custom_metadata": + return p.templateHandler(alias.CustomMetadata) + + case strings.HasPrefix(trimmed, "custom_metadata."): + + split := strings.SplitN(trimmed, ".", 2) + return p.templateHandler(alias.CustomMetadata, split[1]) + } return "", ErrTemplateValueNotFound @@ -222,7 +231,7 @@ func performTemplating(input string, p *PopulateStringInput) (string, error) { } // An empty alias is sufficient for generating defaults - alias = &logical.Alias{Metadata: make(map[string]string)} + alias = &logical.Alias{Metadata: make(map[string]string), CustomMetadata: make(map[string]string)} } return performAliasTemplating(split[1], alias) } diff --git a/sdk/logical/identity.pb.go b/sdk/logical/identity.pb.go index f66ad7a304f45..b7cb9602cc9ae 100644 --- a/sdk/logical/identity.pb.go +++ b/sdk/logical/identity.pb.go @@ -138,6 +138,8 @@ type Alias struct { // NamespaceID is the identifier of the namespace to which this alias // belongs. NamespaceID string `sentinel:"" protobuf:"bytes,6,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty"` + // Custom Metadata represents the custom data tied to this entity + CustomMetadata map[string]string `sentinel:"" protobuf:"bytes,7,rep,name=custom_metadata,json=customMetadata,proto3" json:"custom_metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Alias) Reset() { @@ -214,6 +216,13 @@ func (x *Alias) GetNamespaceID() string { return "" } +func (x *Alias) GetCustomMetadata() map[string]string { + if x != nil { + return x.CustomMetadata + } + return nil +} + type Group struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -312,7 +321,7 @@ var file_sdk_logical_identity_proto_rawDesc = []byte{ 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, 0x22, 0x8b, 0x02, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9b, 0x03, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, @@ -325,7 +334,16 @@ var file_sdk_logical_identity_proto_rawDesc = []byte{ 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 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, + 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x2e, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 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, + 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 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, @@ -359,25 +377,27 @@ 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, 6) +var file_sdk_logical_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_sdk_logical_identity_proto_goTypes = []interface{}{ (*Entity)(nil), // 0: logical.Entity (*Alias)(nil), // 1: logical.Alias (*Group)(nil), // 2: logical.Group nil, // 3: logical.Entity.MetadataEntry nil, // 4: logical.Alias.MetadataEntry - nil, // 5: logical.Group.MetadataEntry + nil, // 5: logical.Alias.CustomMetadataEntry + nil, // 6: logical.Group.MetadataEntry } var file_sdk_logical_identity_proto_depIDxs = []int32{ 1, // 0: logical.Entity.aliases:type_name -> logical.Alias 3, // 1: logical.Entity.metadata:type_name -> logical.Entity.MetadataEntry 4, // 2: logical.Alias.metadata:type_name -> logical.Alias.MetadataEntry - 5, // 3: logical.Group.metadata:type_name -> logical.Group.MetadataEntry - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 5, // 3: logical.Alias.custom_metadata:type_name -> logical.Alias.CustomMetadataEntry + 6, // 4: logical.Group.metadata:type_name -> logical.Group.MetadataEntry + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_sdk_logical_identity_proto_init() } @@ -429,7 +449,7 @@ func file_sdk_logical_identity_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_sdk_logical_identity_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/sdk/logical/identity.proto b/sdk/logical/identity.proto index 78c3758f8510f..1b31b6379927c 100644 --- a/sdk/logical/identity.proto +++ b/sdk/logical/identity.proto @@ -50,6 +50,9 @@ message Alias { // NamespaceID is the identifier of the namespace to which this alias // belongs. string namespace_id = 6; + + // Custom Metadata represents the custom data tied to this entity + map custom_metadata = 7; } message Group { From dbd9dc0111d21d01211d6a4ec34380a3bbd99205 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 14 Sep 2021 11:43:23 -0700 Subject: [PATCH 08/14] added requested changes --- helper/identity/types.proto | 2 -- vault/identity_store_aliases.go | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/helper/identity/types.proto b/helper/identity/types.proto index ad43b054497ad..a165a0b1abde3 100644 --- a/helper/identity/types.proto +++ b/helper/identity/types.proto @@ -175,8 +175,6 @@ message Alias { // Custom Metadata map customMetadata = 12; - - } // Deprecated. Retained for backwards compatibility. diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index a1fc4511d0199..9b01c3b94a425 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -54,7 +54,7 @@ This field is deprecated, use canonical_id.`, }, "custom_metadata": { Type: framework.TypeKVPairs, - Description: "User-provided key-value pairs", + Description: "User provided key-value pairs", }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -91,7 +91,7 @@ This field is deprecated, use canonical_id.`, }, "custom_metadata": { Type: framework.TypeKVPairs, - Description: "User-provided key-value pairs", + Description: "User provided key-value pairs", }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -193,7 +193,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { customMetadata = alias.CustomMetadata default: - // mountAccessor,name and customMetadata provided + // mountAccessor, name and customMetadata provided } return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias, customMetadata) } @@ -403,7 +403,6 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ }, nil } -//TODO: ask if we can use the same validation code from kv secrets plugin func validateCustomMetadata(customMetadata map[string]string) error { var errs *multierror.Error From 60199b2418c0204b39f20f111f51247ec402a28e Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 14 Sep 2021 13:30:24 -0700 Subject: [PATCH 09/14] added requested changes --- helper/identity/types.proto | 2 -- vault/identity_store_aliases.go | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/helper/identity/types.proto b/helper/identity/types.proto index ad43b054497ad..a165a0b1abde3 100644 --- a/helper/identity/types.proto +++ b/helper/identity/types.proto @@ -175,8 +175,6 @@ message Alias { // Custom Metadata map customMetadata = 12; - - } // Deprecated. Retained for backwards compatibility. diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index a1fc4511d0199..9b01c3b94a425 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -54,7 +54,7 @@ This field is deprecated, use canonical_id.`, }, "custom_metadata": { Type: framework.TypeKVPairs, - Description: "User-provided key-value pairs", + Description: "User provided key-value pairs", }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -91,7 +91,7 @@ This field is deprecated, use canonical_id.`, }, "custom_metadata": { Type: framework.TypeKVPairs, - Description: "User-provided key-value pairs", + Description: "User provided key-value pairs", }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -193,7 +193,7 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { customMetadata = alias.CustomMetadata default: - // mountAccessor,name and customMetadata provided + // mountAccessor, name and customMetadata provided } return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias, customMetadata) } @@ -403,7 +403,6 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ }, nil } -//TODO: ask if we can use the same validation code from kv secrets plugin func validateCustomMetadata(customMetadata map[string]string) error { var errs *multierror.Error From ba34d50fefe52f2ac76807c174b79a6a03911552 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Tue, 14 Sep 2021 14:09:54 -0700 Subject: [PATCH 10/14] added policy templating changes and fixed tests --- changelog/12502.txt | 3 +++ vault/identity_store_aliases.go | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 changelog/12502.txt diff --git a/changelog/12502.txt b/changelog/12502.txt new file mode 100644 index 0000000000000..4d24e7af5a80c --- /dev/null +++ b/changelog/12502.txt @@ -0,0 +1,3 @@ +```release-note:feature +core: adds custom_metadata field for aliases +``` \ No newline at end of file diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 9b01c3b94a425..1db2d95238569 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/vault/helper/storagepacker" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" + "github.com/mitchellh/mapstructure" ) const maxCustomMetadataKeys = 64 @@ -135,7 +136,14 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc { id := d.Get("id").(string) // Get custom metadata, if any - customMetadata := d.Get("custom_metadata").(map[string]string) + customMetadata := make(map[string]string) + data, customMetadataExists := d.GetOk("custom_metadata") + if customMetadataExists { + err = mapstructure.Decode(data, &customMetadata) + if err != nil { + return nil, err + } + } // Get entity id canonicalID := d.Get("canonical_id").(string) From a21f7b1d61e1551dc4d255c58ee9cb135264b4da Mon Sep 17 00:00:00 2001 From: akshya96 Date: Wed, 15 Sep 2021 09:51:01 -0700 Subject: [PATCH 11/14] adding proto changes --- helper/identity/types.pb.go | 2 +- helper/identity/types.proto | 2 +- sdk/logical/identity.pb.go | 2 +- sdk/logical/identity.proto | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helper/identity/types.pb.go b/helper/identity/types.pb.go index bedcd48089017..ce8431c01a724 100644 --- a/helper/identity/types.pb.go +++ b/helper/identity/types.pb.go @@ -405,7 +405,7 @@ type Alias struct { // NamespaceID is the identifier of the namespace to which this alias // belongs. NamespaceID string `sentinel:"" protobuf:"bytes,11,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty"` - // Custom Metadata + // Custom Metadata represents the custom data tied to this alias CustomMetadata map[string]string `sentinel:"" protobuf:"bytes,12,rep,name=customMetadata,proto3" json:"customMetadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } diff --git a/helper/identity/types.proto b/helper/identity/types.proto index a165a0b1abde3..d48b776e947c7 100644 --- a/helper/identity/types.proto +++ b/helper/identity/types.proto @@ -173,7 +173,7 @@ message Alias { // belongs. string namespace_id = 11; - // Custom Metadata + // Custom Metadata represents the custom data tied to this alias map customMetadata = 12; } diff --git a/sdk/logical/identity.pb.go b/sdk/logical/identity.pb.go index b7cb9602cc9ae..3d1adc90a6840 100644 --- a/sdk/logical/identity.pb.go +++ b/sdk/logical/identity.pb.go @@ -138,7 +138,7 @@ type Alias struct { // NamespaceID is the identifier of the namespace to which this alias // belongs. NamespaceID string `sentinel:"" protobuf:"bytes,6,opt,name=namespace_id,json=namespaceID,proto3" json:"namespace_id,omitempty"` - // Custom Metadata represents the custom data tied to this entity + // Custom Metadata represents the custom data tied to this alias CustomMetadata map[string]string `sentinel:"" protobuf:"bytes,7,rep,name=custom_metadata,json=customMetadata,proto3" json:"custom_metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } diff --git a/sdk/logical/identity.proto b/sdk/logical/identity.proto index 1b31b6379927c..9e07bd6480205 100644 --- a/sdk/logical/identity.proto +++ b/sdk/logical/identity.proto @@ -51,7 +51,7 @@ message Alias { // belongs. string namespace_id = 6; - // Custom Metadata represents the custom data tied to this entity + // Custom Metadata represents the custom data tied to this alias map custom_metadata = 7; } From c90d149c28d5406b4faf1ae51f2c7b1399ae9633 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Wed, 15 Sep 2021 11:36:15 -0700 Subject: [PATCH 12/14] making changes --- vault/identity_store_aliases.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 1db2d95238569..e27973a59bea4 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -334,8 +334,8 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ return nil, err } - // Bail unless it's just a case change or no custom meta data change - if existingAlias != nil && !strings.EqualFold(existingAlias.Name, name) && reflect.DeepEqual(customMetadata, alias.CustomMetadata) { + // Bail unless it's just a case change + if existingAlias != nil && !strings.EqualFold(existingAlias.Name, name) { return logical.ErrorResponse("alias with combination of mount accessor and name already exists"), nil } From dd02e47db283441e0f9fbb92798269bfa60d7ce2 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Wed, 15 Sep 2021 14:58:07 -0700 Subject: [PATCH 13/14] adding unit tests --- sdk/helper/identitytpl/templating_test.go | 107 +++++++++++++++++----- vault/identity_store_aliases_test.go | 31 +++++-- 2 files changed, 107 insertions(+), 31 deletions(-) diff --git a/sdk/helper/identitytpl/templating_test.go b/sdk/helper/identitytpl/templating_test.go index 41362da9e411a..15bfc812387c6 100644 --- a/sdk/helper/identitytpl/templating_test.go +++ b/sdk/helper/identitytpl/templating_test.go @@ -17,23 +17,24 @@ var testNow = time.Now().Add(100 * time.Hour) func TestPopulate_Basic(t *testing.T) { tests := []struct { - mode int - name string - input string - output string - err error - entityName string - metadata map[string]string - aliasAccessor string - aliasID string - aliasName string - nilEntity bool - validityCheckOnly bool - aliasMetadata map[string]string - groupName string - groupMetadata map[string]string - groupMemberships []string - now time.Time + mode int + name string + input string + output string + err error + entityName string + metadata map[string]string + aliasAccessor string + aliasID string + aliasName string + nilEntity bool + validityCheckOnly bool + aliasMetadata map[string]string + aliasCustomMetadata map[string]string + groupName string + groupMetadata map[string]string + groupMemberships []string + now time.Time }{ // time.* tests. Keep tests with time.Now() at the front to avoid false // positives due to the second changing during the test @@ -329,6 +330,53 @@ func TestPopulate_Basic(t *testing.T) { aliasMetadata: map[string]string{"foo": "bar", "color": "green"}, output: `{}`, }, + { + mode: JSONTemplating, + name: "one alias custom metadata key", + input: "{{identity.entity.aliases.aws_123.custom_metadata.foo}}", + aliasAccessor: "aws_123", + aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"}, + output: `"abc"`, + }, + { + mode: JSONTemplating, + name: "one alias custom metadata key not found", + input: "{{identity.entity.aliases.aws_123.custom_metadata.size}}", + aliasAccessor: "aws_123", + aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"}, + output: `""`, + }, + { + mode: JSONTemplating, + name: "one alias custom metadata, accessor not found", + input: "{{identity.entity.aliases.aws_123.custom_metadata.size}}", + aliasAccessor: "not_gonna_match", + aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"}, + output: `""`, + }, + { + mode: JSONTemplating, + name: "all alias custom metadata", + input: "{{identity.entity.aliases.aws_123.custom_metadata}}", + aliasAccessor: "aws_123", + aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"}, + output: `{"bar":"123","foo":"abc"}`, + }, + { + mode: JSONTemplating, + name: "null alias custom metadata", + input: "{{identity.entity.aliases.aws_123.custom_metadata}}", + aliasAccessor: "aws_123", + output: `{}`, + }, + { + mode: JSONTemplating, + name: "all alias custom metadata, accessor not found", + input: "{{identity.entity.aliases.aws_123.custom_metadata}}", + aliasAccessor: "not_gonna_match", + aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"}, + output: `{}`, + }, } for _, test := range tests { @@ -343,10 +391,11 @@ func TestPopulate_Basic(t *testing.T) { if test.aliasAccessor != "" { entity.Aliases = []*logical.Alias{ { - MountAccessor: test.aliasAccessor, - ID: test.aliasID, - Name: test.aliasName, - Metadata: test.aliasMetadata, + MountAccessor: test.aliasAccessor, + ID: test.aliasID, + Name: test.aliasName, + Metadata: test.aliasMetadata, + CustomMetadata: test.aliasCustomMetadata, }, } } @@ -436,6 +485,10 @@ func TestPopulate_FullObject(t *testing.T) { "service": "ec2", "region": "west", }, + CustomMetadata: map[string]string{ + "foo": "abc", + "bar": "123", + }, }, }, } @@ -458,7 +511,11 @@ func TestPopulate_FullObject(t *testing.T) { "one not found alias metadata key": {{identity.entity.aliases.blahblah.metadata.service}}, "group names": {{identity.entity.groups.names}}, "group ids": {{identity.entity.groups.ids}}, - "repeated and": {"nested element": {{identity.entity.name}}} + "repeated and": {"nested element": {{identity.entity.name}}}, + "alias custom metadata": {{identity.entity.aliases.aws_123.custom_metadata}}, + "alias not found custom metadata": {{identity.entity.aliases.blahblah.custom_metadata}}, + "one alias custom metadata key": {{identity.entity.aliases.aws_123.custom_metadata.foo}}, + "one not found alias custom metadata key": {{identity.entity.aliases.blahblah.custom_metadata.foo}}, }` expected := ` @@ -474,7 +531,11 @@ func TestPopulate_FullObject(t *testing.T) { "one not found alias metadata key": "", "group names": ["g1","g2"], "group ids": ["a08b0c02","239bef91"], - "repeated and": {"nested element": "Entity Name"} + "repeated and": {"nested element": "Entity Name"}, + "alias custom metadata": {"bar":"123","foo":"abc"}, + "alias not found custom metadata": {}, + "one alias custom metadata key": "abc", + "one not found alias custom metadata key": "", }` input := PopulateStringInput{ diff --git a/vault/identity_store_aliases_test.go b/vault/identity_store_aliases_test.go index a0779c68adc0f..bf70e4010adbb 100644 --- a/vault/identity_store_aliases_test.go +++ b/vault/identity_store_aliases_test.go @@ -375,10 +375,13 @@ func TestIdentityStore_AliasUpdate(t *testing.T) { t.Fatalf("err:%v resp:%#v", err, resp) } aliasID := resp.Data["id"].(string) + customMetadata := make(map[string]string) + customMetadata["foo"] = "abc" updateData := map[string]interface{}{ - "name": "updatedaliasname", - "mount_accessor": githubAccessor, + "name": "updatedaliasname", + "mount_accessor": githubAccessor, + "custom_metadata": customMetadata, } aliasReq.Data = updateData @@ -397,6 +400,9 @@ func TestIdentityStore_AliasUpdate(t *testing.T) { if resp.Data["name"] != "updatedaliasname" { t.Fatalf("failed to update alias information; \n response data: %#v\n", resp.Data) } + if !reflect.DeepEqual(resp.Data["custom_metadata"], customMetadata) { + t.Fatalf("failed to update alias information; \n response data: %#v\n", resp.Data) + } } func TestIdentityStore_AliasUpdate_ByID(t *testing.T) { @@ -425,9 +431,12 @@ func TestIdentityStore_AliasUpdate_ByID(t *testing.T) { t.Fatalf("expected an error due to invalid alias id") } + customMetadata := make(map[string]string) + customMetadata["foo"] = "abc" registerData := map[string]interface{}{ - "name": "testaliasname", - "mount_accessor": githubAccessor, + "name": "testaliasname", + "mount_accessor": githubAccessor, + "custom_metadata": customMetadata, } registerReq := &logical.Request{ @@ -468,6 +477,9 @@ func TestIdentityStore_AliasUpdate_ByID(t *testing.T) { if resp.Data["name"] != "updatedaliasname" { t.Fatalf("failed to update alias information; \n response data: %#v\n", resp.Data) } + if !reflect.DeepEqual(resp.Data["custom_metadata"], customMetadata) { + t.Fatalf("failed to update alias information; \n response data: %#v\n", resp.Data) + } delete(registerReq.Data, "name") @@ -498,10 +510,13 @@ func TestIdentityStore_AliasReadDelete(t *testing.T) { ctx := namespace.RootContext(nil) is, githubAccessor, _ := testIdentityStoreWithGithubAuth(ctx, t) + customMetadata := make(map[string]string) + customMetadata["foo"] = "abc" registerData := map[string]interface{}{ - "name": "testaliasname", - "mount_accessor": githubAccessor, - "metadata": []string{"organization=hashicorp", "team=vault"}, + "name": "testaliasname", + "mount_accessor": githubAccessor, + "metadata": []string{"organization=hashicorp", "team=vault"}, + "custom_metadata": customMetadata, } registerReq := &logical.Request{ @@ -537,7 +552,7 @@ func TestIdentityStore_AliasReadDelete(t *testing.T) { if resp.Data["id"].(string) == "" || resp.Data["canonical_id"].(string) == "" || resp.Data["name"].(string) != registerData["name"] || - resp.Data["mount_type"].(string) != "github" { + resp.Data["mount_type"].(string) != "github" || !reflect.DeepEqual(resp.Data["custom_metadata"], customMetadata) { t.Fatalf("bad: alias read response; \nexpected: %#v \nactual: %#v\n", registerData, resp.Data) } From 3db9568a58946829c2150ef238262ec69ac9b897 Mon Sep 17 00:00:00 2001 From: akshya96 Date: Thu, 16 Sep 2021 10:04:17 -0700 Subject: [PATCH 14/14] using suggested function --- vault/identity_store_aliases.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index e27973a59bea4..db827a33c4ac6 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -3,7 +3,6 @@ package vault import ( "context" "fmt" - "reflect" "strings" "github.com/golang/protobuf/ptypes" @@ -306,7 +305,7 @@ func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Requ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias, customMetadata map[string]string) (*logical.Response, error) { if name == alias.Name && mountAccessor == alias.MountAccessor && - (canonicalID == alias.CanonicalID || canonicalID == "") && (reflect.DeepEqual(customMetadata, alias.CustomMetadata)) { + (canonicalID == alias.CanonicalID || canonicalID == "") && (strutil.EqualStringMaps(customMetadata, alias.CustomMetadata)) { // Nothing to do; return nil to be idempotent return nil, nil } @@ -316,7 +315,7 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ // If we're changing one or the other or both of these, make sure that // there isn't a matching alias already, and make sure it's in the same // namespace. - if name != alias.Name || mountAccessor != alias.MountAccessor || !reflect.DeepEqual(customMetadata, alias.CustomMetadata) { + if name != alias.Name || mountAccessor != alias.MountAccessor || !strutil.EqualStringMaps(customMetadata, alias.CustomMetadata) { // Check here to see if such an alias already exists, if so bail mountEntry := i.router.MatchingMountByAccessor(mountAccessor) if mountEntry == nil {