Add Custom metadata field to alias (#12502)
* adding changes * removing q.Q * removing empty lines * testing * checking tests * fixing tests * adding changes * added requested changes * added requested changes * added policy templating changes and fixed tests * adding proto changes * making changes * adding unit tests * using suggested function
This commit is contained in:
parent
105786cc27
commit
c643dc1d53
|
@ -0,0 +1,3 @@
|
|||
```release-note:feature
|
||||
core: adds custom_metadata field for aliases
|
||||
```
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 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"`
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
|
|
|
@ -172,6 +172,9 @@ message Alias {
|
|||
// NamespaceID is the identifier of the namespace to which this alias
|
||||
// belongs.
|
||||
string namespace_id = 11;
|
||||
|
||||
// Custom Metadata represents the custom data tied to this alias
|
||||
map<string, string> customMetadata = 12;
|
||||
}
|
||||
|
||||
// Deprecated. Retained for backwards compatibility.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -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 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"`
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
|
|
|
@ -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 alias
|
||||
map<string, string> custom_metadata = 7;
|
||||
}
|
||||
|
||||
message Group {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -6,13 +6,21 @@ import (
|
|||
"strings"
|
||||
|
||||
"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"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
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 +52,10 @@ This field is deprecated, use canonical_id.`,
|
|||
Type: framework.TypeString,
|
||||
Description: "Name of the alias; unused for a modify",
|
||||
},
|
||||
"custom_metadata": {
|
||||
Type: framework.TypeKVPairs,
|
||||
Description: "User provided key-value pairs",
|
||||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
|
@ -77,6 +89,10 @@ This field is deprecated, use canonical_id.`,
|
|||
Type: framework.TypeString,
|
||||
Description: "(Unused)",
|
||||
},
|
||||
"custom_metadata": {
|
||||
Type: framework.TypeKVPairs,
|
||||
Description: "User provided key-value pairs",
|
||||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
|
@ -118,6 +134,16 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc {
|
|||
// Get ID, if any
|
||||
id := d.Get("id").(string)
|
||||
|
||||
// Get custom metadata, if any
|
||||
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)
|
||||
if canonicalID == "" {
|
||||
|
@ -125,6 +151,15 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc {
|
|||
canonicalID = d.Get("entity_id").(string)
|
||||
}
|
||||
|
||||
//validate customMetadata if provided
|
||||
if len(customMetadata) != 0 {
|
||||
|
||||
err := validateCustomMetadata(customMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
i.lock.Lock()
|
||||
defer i.lock.Unlock()
|
||||
|
||||
|
@ -143,31 +178,31 @@ func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc {
|
|||
if alias.NamespaceID != ns.ID {
|
||||
return logical.ErrorResponse("cannot modify aliases across namespaces"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
switch {
|
||||
case mountAccessor == "" && name == "":
|
||||
case mountAccessor == "" && name == "" && len(customMetadata) == 0:
|
||||
// Just a canonical ID update, maybe
|
||||
if canonicalID == "" {
|
||||
// Nothing to do, so be idempotent
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
name = alias.Name
|
||||
mountAccessor = alias.MountAccessor
|
||||
customMetadata = alias.CustomMetadata
|
||||
|
||||
case mountAccessor == "":
|
||||
// No change to mount accessor
|
||||
mountAccessor = alias.MountAccessor
|
||||
|
||||
case name == "":
|
||||
// No change to mount name
|
||||
name = alias.Name
|
||||
case len(customMetadata) == 0:
|
||||
// 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,24 +231,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) {
|
||||
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{}
|
||||
|
||||
// If a canonical ID is provided pull up the entity and make sure we're in
|
||||
|
@ -266,10 +302,10 @@ 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) {
|
||||
if name == alias.Name &&
|
||||
mountAccessor == alias.MountAccessor &&
|
||||
(canonicalID == alias.CanonicalID || canonicalID == "") {
|
||||
(canonicalID == alias.CanonicalID || canonicalID == "") && (strutil.EqualStringMaps(customMetadata, alias.CustomMetadata)) {
|
||||
// Nothing to do; return nil to be idempotent
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -279,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 {
|
||||
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 {
|
||||
|
@ -296,6 +332,7 @@ 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) {
|
||||
return logical.ErrorResponse("alias with combination of mount accessor and name already exists"), nil
|
||||
|
@ -304,8 +341,8 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ
|
|||
// 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
|
||||
// canonical ID hasn't changed
|
||||
currentEntity, err := i.MemDBEntityByAliasID(alias.ID, true)
|
||||
|
@ -373,6 +410,55 @@ func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Requ
|
|||
}, nil
|
||||
}
|
||||
|
||||
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 +495,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["custom_metadata"] = alias.CustomMetadata
|
||||
respData["name"] = alias.Name
|
||||
respData["merged_from_canonical_ids"] = alias.MergedFromCanonicalIDs
|
||||
respData["namespace_id"] = alias.NamespaceID
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue