feat(handlers): CRUDL support for vault-generic Username-Password-Domain credentials (#1527)

---------

Co-authored-by: April-May <18632637+AprilMay0@users.noreply.github.com>
pull/6010/head
Andrew Gaffney 1 year ago committed by irenarindos
parent 0111123cac
commit 0824dd7d16

@ -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 {

@ -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,

Loading…
Cancel
Save