feat(handlers): CRUDL support for vault-generic Username-Password-Domain credentials (#1527)
--------- Co-authored-by: April-May <18632637+AprilMay0@users.noreply.github.com>
This commit is contained in:
1 parent
0111123cac
commit
0824dd7d16
4 files changed
+618
No files matched your search
@@ -363,6 +363,7 @@ type listLookupLibrary struct {
|
||||
CredentialType string
|
||||
UsernameAttribute string
|
||||
PasswordAttribute string
|
||||
DomainAttribute string
|
||||
PrivateKeyAttribute string
|
||||
PrivateKeyPassphraseAttribute string
|
||||
}
|
||||
@@ -395,6 +396,16 @@ func (pl *listLookupLibrary) toCredentialLibrary() *CredentialLibrary {
|
||||
up.sanitize()
|
||||
cl.MappingOverride = up
|
||||
}
|
||||
case string(globals.UsernamePasswordDomainCredentialType):
|
||||
if pl.UsernameAttribute != "" || pl.PasswordAttribute != "" || pl.DomainAttribute != "" {
|
||||
upd := allocUsernamePasswordDomainOverride()
|
||||
upd.LibraryId = pl.PublicId
|
||||
upd.UsernameAttribute = pl.UsernameAttribute
|
||||
upd.PasswordAttribute = pl.PasswordAttribute
|
||||
upd.DomainAttribute = pl.DomainAttribute
|
||||
upd.sanitize()
|
||||
cl.MappingOverride = upd
|
||||
}
|
||||
case string(globals.SshPrivateKeyCredentialType):
|
||||
if pl.UsernameAttribute != "" || pl.PrivateKeyAttribute != "" || pl.PrivateKeyPassphraseAttribute != "" {
|
||||
pk := allocSshPrivateKeyOverride()
|
||||
|
||||
@@ -52,6 +52,7 @@ const (
|
||||
const (
|
||||
usernameAttribute string = "username_attribute"
|
||||
passwordAttribute string = "password_attribute"
|
||||
domainAttribute string = "domain_attribute"
|
||||
privateKeyAttribute string = "private_key_attribute"
|
||||
pkPassphraseAttribute string = "private_key_passphrase_attribute"
|
||||
)
|
||||
@@ -80,6 +81,7 @@ var (
|
||||
globals.UsernamePasswordCredentialType,
|
||||
globals.SshPrivateKeyCredentialType,
|
||||
globals.UnspecifiedCredentialType,
|
||||
globals.UsernamePasswordDomainCredentialType,
|
||||
}
|
||||
|
||||
validKeyTypes = []string{
|
||||
@@ -760,6 +762,17 @@ func toProto(ctx context.Context, in credential.Library, opt ...handlers.Option)
|
||||
m[passwordAttribute] = mapping.PasswordAttribute
|
||||
}
|
||||
|
||||
case *vault.UsernamePasswordDomainOverride:
|
||||
if mapping.UsernameAttribute != "" {
|
||||
m[usernameAttribute] = mapping.UsernameAttribute
|
||||
}
|
||||
if mapping.PasswordAttribute != "" {
|
||||
m[passwordAttribute] = mapping.PasswordAttribute
|
||||
}
|
||||
if mapping.DomainAttribute != "" {
|
||||
m[domainAttribute] = mapping.DomainAttribute
|
||||
}
|
||||
|
||||
case *vault.SshPrivateKeyOverride:
|
||||
if mapping.UsernameAttribute != "" {
|
||||
m[usernameAttribute] = mapping.UsernameAttribute
|
||||
@@ -884,6 +897,23 @@ func toStorageVaultLibrary(ctx context.Context, storeId string, in *pb.Credentia
|
||||
opts = append(opts, vault.WithMappingOverride(vault.NewUsernamePasswordOverride(mapOpts...)))
|
||||
}
|
||||
|
||||
case globals.UsernamePasswordDomainCredentialType:
|
||||
opts = append(opts, vault.WithCredentialType(credentialType))
|
||||
overrides := in.CredentialMappingOverrides.AsMap()
|
||||
var mapOpts []vault.Option
|
||||
if username := overrides[usernameAttribute]; username != nil {
|
||||
mapOpts = append(mapOpts, vault.WithOverrideUsernameAttribute(username.(string)))
|
||||
}
|
||||
if password := overrides[passwordAttribute]; password != nil {
|
||||
mapOpts = append(mapOpts, vault.WithOverridePasswordAttribute(password.(string)))
|
||||
}
|
||||
if domain := overrides[domainAttribute]; domain != nil {
|
||||
mapOpts = append(mapOpts, vault.WithOverrideDomainAttribute(domain.(string)))
|
||||
}
|
||||
if len(mapOpts) > 0 {
|
||||
opts = append(opts, vault.WithMappingOverride(vault.NewUsernamePasswordDomainOverride(mapOpts...)))
|
||||
}
|
||||
|
||||
case globals.SshPrivateKeyCredentialType:
|
||||
opts = append(opts, vault.WithCredentialType(credentialType))
|
||||
overrides := in.CredentialMappingOverrides.AsMap()
|
||||
@@ -1183,6 +1213,10 @@ func validateMapping(badFields map[string]string, credentialType globals.Credent
|
||||
validFields[usernameAttribute] = true
|
||||
validFields[privateKeyAttribute] = true
|
||||
validFields[pkPassphraseAttribute] = true
|
||||
case globals.UsernamePasswordDomainCredentialType:
|
||||
validFields[usernameAttribute] = true
|
||||
validFields[passwordAttribute] = true
|
||||
validFields[domainAttribute] = true
|
||||
default:
|
||||
badFields[globals.CredentialTypeField] = fmt.Sprintf("Unknown credential type %q", credentialType)
|
||||
return
|
||||
@@ -1272,7 +1306,34 @@ func getMappingUpdates(credentialType globals.CredentialType, current vault.Mapp
|
||||
default:
|
||||
ret[passwordAttribute] = currentPass
|
||||
}
|
||||
case globals.UsernamePasswordDomainCredentialType:
|
||||
var currentUser, currentPass, currentDomain any
|
||||
if overrides, ok := current.(*vault.UsernamePasswordDomainOverride); ok {
|
||||
currentUser = overrides.UsernameAttribute
|
||||
currentPass = overrides.PasswordAttribute
|
||||
currentDomain = overrides.DomainAttribute
|
||||
}
|
||||
|
||||
switch {
|
||||
case masks[usernameAttribute]:
|
||||
ret[usernameAttribute] = new[usernameAttribute]
|
||||
default:
|
||||
ret[usernameAttribute] = currentUser
|
||||
}
|
||||
|
||||
switch {
|
||||
case masks[passwordAttribute]:
|
||||
ret[passwordAttribute] = new[passwordAttribute]
|
||||
default:
|
||||
ret[passwordAttribute] = currentPass
|
||||
}
|
||||
|
||||
switch {
|
||||
case masks[domainAttribute]:
|
||||
ret[domainAttribute] = new[domainAttribute]
|
||||
default:
|
||||
ret[domainAttribute] = currentDomain
|
||||
}
|
||||
case globals.SshPrivateKeyCredentialType:
|
||||
var currentUser, currentpPass, currentPk any
|
||||
if overrides, ok := current.(*vault.SshPrivateKeyOverride); ok {
|
||||
|
||||
+533
@@ -561,6 +561,31 @@ func TestCreate(t *testing.T) {
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Invalid username_password_domain mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
domainAttribute: "domain-test",
|
||||
"invalid": "invalid-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Using POST method",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
@@ -768,6 +793,196 @@ func TestCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary username_password_domain type",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
}},
|
||||
idPrefix: globals.VaultCredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultCredentialLibraryPrefix),
|
||||
Item: &pb.CredentialLibrary{
|
||||
Id: store.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: store.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: store.GetUpdateTime().GetTimestamp(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary username_password_domain type with username mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
}},
|
||||
idPrefix: globals.VaultCredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultCredentialLibraryPrefix),
|
||||
Item: &pb.CredentialLibrary{
|
||||
Id: store.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: store.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: store.GetUpdateTime().GetTimestamp(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary username_password type with username/password mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
passwordAttribute: "pass-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
}},
|
||||
idPrefix: globals.VaultCredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultCredentialLibraryPrefix),
|
||||
Item: &pb.CredentialLibrary{
|
||||
Id: store.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: store.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: store.GetUpdateTime().GetTimestamp(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
passwordAttribute: "pass-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary username_password_domain type with username/password/domain mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
passwordAttribute: "pass-test",
|
||||
domainAttribute: "domain-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
}},
|
||||
idPrefix: globals.VaultCredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultCredentialLibraryPrefix),
|
||||
Item: &pb.CredentialLibrary{
|
||||
Id: store.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: store.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: store.GetUpdateTime().GetTimestamp(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String("something"),
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(globals.UsernamePasswordDomainCredentialType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user-test",
|
||||
passwordAttribute: "pass-test",
|
||||
domainAttribute: "domain-test",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary ssh_private_key type",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
@@ -967,10 +1182,24 @@ func TestGet(t *testing.T) {
|
||||
vault.WithOverrideUsernameAttribute("user"),
|
||||
vault.WithOverridePasswordAttribute("pass"),
|
||||
)))
|
||||
|
||||
require.NoError(t, err)
|
||||
userPassLib, err := repo.CreateCredentialLibrary(context.Background(), prj.GetPublicId(), lib)
|
||||
require.NoError(t, err)
|
||||
|
||||
libDomain, err := vault.NewCredentialLibrary(store.GetPublicId(), "vault/path",
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("user"),
|
||||
vault.WithOverridePasswordAttribute("pass"),
|
||||
vault.WithOverrideDomainAttribute("domain"),
|
||||
)))
|
||||
|
||||
require.NoError(t, err)
|
||||
userPassDomainLib, err := repo.CreateCredentialLibrary(context.Background(), prj.GetPublicId(), libDomain)
|
||||
require.NoError(t, err)
|
||||
|
||||
lib1, err := vault.NewCredentialLibrary(store.GetPublicId(), "vault/path/ssh",
|
||||
vault.WithCredentialType("ssh_private_key"),
|
||||
vault.WithMappingOverride(
|
||||
@@ -1048,6 +1277,39 @@ func TestGet(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success-UsernamePasswordDomain",
|
||||
id: userPassDomainLib.GetPublicId(),
|
||||
res: &pbs.GetCredentialLibraryResponse{
|
||||
Item: &pb.CredentialLibrary{
|
||||
Id: userPassDomainLib.GetPublicId(),
|
||||
CredentialStoreId: userPassDomainLib.GetStoreId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: store.GetProjectId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Type: vault.GenericLibrarySubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
CreatedTime: userPassDomainLib.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: userPassDomainLib.UpdateTime.GetTimestamp(),
|
||||
Version: 1,
|
||||
Attrs: &pb.CredentialLibrary_VaultGenericCredentialLibraryAttributes{
|
||||
VaultGenericCredentialLibraryAttributes: &pb.VaultCredentialLibraryAttributes{
|
||||
Path: wrapperspb.String(userPassDomainLib.GetVaultPath()),
|
||||
HttpMethod: wrapperspb.String(userPassDomainLib.GetHttpMethod()),
|
||||
},
|
||||
},
|
||||
CredentialType: "username_password_domain",
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "user",
|
||||
passwordAttribute: "pass",
|
||||
domainAttribute: "domain",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success-ssh-private-key",
|
||||
id: sshPkLib.GetPublicId(),
|
||||
@@ -1260,6 +1522,7 @@ func TestUpdate(t *testing.T) {
|
||||
|
||||
usernameAttrField := fmt.Sprintf("%v.%v", credentialMappingPathField, usernameAttribute)
|
||||
passwordAttrField := fmt.Sprintf("%v.%v", credentialMappingPathField, passwordAttribute)
|
||||
domainAttrField := fmt.Sprintf("%v.%v", credentialMappingPathField, domainAttribute)
|
||||
privateKeyAttrField := fmt.Sprintf("%v.%v", credentialMappingPathField, privateKeyAttribute)
|
||||
passphraseAttrField := fmt.Sprintf("%v.%v", credentialMappingPathField, pkPassphraseAttribute)
|
||||
|
||||
@@ -1485,6 +1748,218 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-change-username-attribute",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(usernameAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "changed-user",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides.Fields[usernameAttribute] = structpb.NewStringValue("changed-user")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-change-password-attribute",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
passwordAttribute: "changed-pass",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides.Fields[passwordAttribute] = structpb.NewStringValue("changed-pass")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-change-domain-attribute",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(domainAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
domainAttribute: "changed-domain",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides.Fields[domainAttribute] = structpb.NewStringValue("changed-domain")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-change-username-and-password-attributes",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "changed-user",
|
||||
passwordAttribute: "changed-pass",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides.Fields[usernameAttribute] = structpb.NewStringValue("changed-user")
|
||||
out.CredentialMappingOverrides.Fields[passwordAttribute] = structpb.NewStringValue("changed-pass")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-change-username-password-and-domain-attributes",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField, domainAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "changed-user",
|
||||
passwordAttribute: "changed-pass",
|
||||
domainAttribute: "changed-domain",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides.Fields[usernameAttribute] = structpb.NewStringValue("changed-user")
|
||||
out.CredentialMappingOverrides.Fields[passwordAttribute] = structpb.NewStringValue("changed-pass")
|
||||
out.CredentialMappingOverrides.Fields[domainAttribute] = structpb.NewStringValue("changed-domain")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-mapping-override-change-username-password-and-domain-attributes",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField, domainAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: "new-user",
|
||||
passwordAttribute: "new-pass",
|
||||
domainAttribute: "new-domain",
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
v := map[string]any{
|
||||
usernameAttribute: "new-user",
|
||||
passwordAttribute: "new-pass",
|
||||
domainAttribute: "new-domain",
|
||||
}
|
||||
var err error
|
||||
out.CredentialMappingOverrides, err = structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-domain-attributes-delete-mapping-override",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(credentialMappingPathField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: nil,
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides = nil
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-mapping-override-delete-mapping-override",
|
||||
opts: []vault.Option{
|
||||
@@ -1532,6 +2007,38 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "username-password-attributes-delete-mapping-override-field-specific",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUsernamePasswordDomainOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
vault.WithOverridePasswordAttribute("orig-pass"),
|
||||
vault.WithOverrideDomainAttribute("orig-domain"),
|
||||
)),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField, domainAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: nil,
|
||||
passwordAttribute: nil,
|
||||
domainAttribute: nil,
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides = nil
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-mapping-override-delete-mapping-override-field-specific",
|
||||
opts: []vault.Option{
|
||||
@@ -1557,6 +2064,32 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-mapping-override-delete-mapping-override-field-specific",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("username_password_domain"),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField, domainAttrField),
|
||||
Item: &pb.CredentialLibrary{
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]any{
|
||||
usernameAttribute: nil,
|
||||
passwordAttribute: nil,
|
||||
domainAttribute: nil,
|
||||
}
|
||||
ret, err := structpb.NewStruct(v)
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialLibrary) *pb.CredentialLibrary {
|
||||
out := proto.Clone(in).(*pb.CredentialLibrary)
|
||||
out.CredentialMappingOverrides = nil
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ssh-private-key-attributes-change-username-attribute",
|
||||
opts: []vault.Option{
|
||||
|
||||
@@ -102,6 +102,19 @@ func dynamicToSessionCredential(ctx context.Context, cred credential.Dynamic) (*
|
||||
credType = string(l.CredentialType())
|
||||
|
||||
switch c := cred.(type) {
|
||||
case credential.UsernamePasswordDomain:
|
||||
credData, err = handlers.ProtoToStruct(
|
||||
ctx,
|
||||
&pb.UsernamePasswordDomainCredential{
|
||||
Username: c.Username(),
|
||||
Password: string(c.Password()),
|
||||
Domain: c.Domain(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for credential"))
|
||||
}
|
||||
|
||||
case credential.UsernamePassword:
|
||||
credData, err = handlers.ProtoToStruct(
|
||||
ctx,
|
||||
|
||||
Reference in new issue
Block a user