Skip to content

Commit 11c4fd7

Browse files
committed
feat(handlers): CRUDL support for static password credential (#6181)
1 parent ec74509 commit 11c4fd7

File tree

10 files changed

+623
-35
lines changed

10 files changed

+623
-35
lines changed

api/credentials/option.gen.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/credentials/password_attributes.gen.go

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/api/genapi/input.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,22 @@ var inputStructs = []*structInfo{
736736
mapstructureConversionTemplate,
737737
},
738738
},
739+
{
740+
inProto: &credentials.PasswordAttributes{},
741+
outFile: "credentials/password_attributes.gen.go",
742+
subtypeName: "PasswordCredential",
743+
subtype: "password",
744+
fieldOverrides: []fieldInfo{
745+
{
746+
Name: "Password",
747+
SkipDefault: true,
748+
},
749+
},
750+
parentTypeName: "Credential",
751+
templates: []*template.Template{
752+
mapstructureConversionTemplate,
753+
},
754+
},
739755
{
740756
inProto: &credentials.SshPrivateKeyAttributes{},
741757
outFile: "credentials/ssh_private_key_attributes.gen.go",

internal/daemon/controller/handlers/credentials/credential_service.go

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ var (
4949
upMaskManager handlers.MaskManager
5050
spkMaskManager handlers.MaskManager
5151
jsonMaskManager handlers.MaskManager
52+
pMaskmanager handlers.MaskManager
5253

5354
// IdActions contains the set of actions that can be performed on
5455
// individual resources
@@ -97,6 +98,13 @@ func init() {
9798
); err != nil {
9899
panic(err)
99100
}
101+
if pMaskmanager, err = handlers.NewMaskManager(
102+
context.Background(),
103+
handlers.MaskDestination{&store.PasswordCredential{}},
104+
handlers.MaskSource{&pb.Credential{}, &pb.PasswordAttributes{}},
105+
); err != nil {
106+
panic(err)
107+
}
100108

101109
// TODO: refactor to remove IdActionsMap and CollectionActions package variables
102110
action.RegisterResource(resource.Credential, IdActions, CollectionActions)
@@ -454,6 +462,23 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Cred
454462
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential but no error returned from repository.")
455463
}
456464
return out, nil
465+
case credential.PasswordSubtype.String():
466+
cred, err := toPasswordStorageCredential(ctx, item.GetCredentialStoreId(), item)
467+
if err != nil {
468+
return nil, errors.Wrap(ctx, err, op)
469+
}
470+
repo, err := s.repoFn()
471+
if err != nil {
472+
return nil, errors.Wrap(ctx, err, op)
473+
}
474+
out, err := repo.CreatePasswordCredential(ctx, scopeId, cred)
475+
if err != nil {
476+
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential"))
477+
}
478+
if out == nil {
479+
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential but no error returned from repository.")
480+
}
481+
return out, nil
457482
case credential.SshPrivateKeySubtype.String():
458483
cred, err := toSshPrivateKeyStorageCredential(ctx, item.GetCredentialStoreId(), item)
459484
if err != nil {
@@ -551,6 +576,29 @@ func (s Service) updateInRepo(
551576
return nil, handlers.NotFoundErrorf("Credential %q doesn't exist or incorrect version provided.", id)
552577
}
553578
return out, nil
579+
case credential.PasswordSubtype:
580+
dbMasks = append(dbMasks, pMaskmanager.Translate(masks)...)
581+
if len(dbMasks) == 0 {
582+
return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
583+
}
584+
585+
cred, err := toPasswordStorageCredential(ctx, storeId, in)
586+
if err != nil {
587+
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to convert to password storage credential"))
588+
}
589+
cred.PublicId = id
590+
repo, err := s.repoFn()
591+
if err != nil {
592+
return nil, errors.Wrap(ctx, err, op)
593+
}
594+
out, rowsUpdated, err := repo.UpdatePasswordCredential(ctx, scopeId, cred, item.GetVersion(), dbMasks)
595+
if err != nil {
596+
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential"))
597+
}
598+
if rowsUpdated == 0 {
599+
return nil, handlers.NotFoundErrorf("Credential %q doesn't exist or incorrect version provided.", id)
600+
}
601+
return out, nil
554602

555603
case credential.SshPrivateKeySubtype:
556604
dbMasks = append(dbMasks, spkMaskManager.Translate(masks)...)
@@ -731,6 +779,8 @@ func toProto(in credential.Static, opt ...handlers.Option) (*pb.Credential, erro
731779
out.Type = credential.UsernamePasswordSubtype.String()
732780
case *static.UsernamePasswordDomainCredential:
733781
out.Type = credential.UsernamePasswordDomainSubtype.String()
782+
case *static.PasswordCredential:
783+
out.Type = credential.PasswordSubtype.String()
734784
case *static.SshPrivateKeyCredential:
735785
out.Type = credential.SshPrivateKeySubtype.String()
736786
case *static.JsonCredential:
@@ -779,6 +829,14 @@ func toProto(in credential.Static, opt ...handlers.Option) (*pb.Credential, erro
779829
},
780830
}
781831
}
832+
case *static.PasswordCredential:
833+
if outputFields.Has(globals.AttributesField) {
834+
out.Attrs = &pb.Credential_PasswordAttributes{
835+
PasswordAttributes: &pb.PasswordAttributes{
836+
PasswordHmac: base64.RawURLEncoding.EncodeToString(cred.GetPasswordHmac()),
837+
},
838+
}
839+
}
782840
case *static.SshPrivateKeyCredential:
783841
if outputFields.Has(globals.AttributesField) {
784842
out.Attrs = &pb.Credential_SshPrivateKeyAttributes{
@@ -848,6 +906,28 @@ func toUsernamePasswordDomainStorageCredential(ctx context.Context, storeId stri
848906
return cs, err
849907
}
850908

909+
func toPasswordStorageCredential(ctx context.Context, storeId string, in *pb.Credential) (out *static.PasswordCredential, err error) {
910+
const op = "credentials.toPasswordStorageCredential"
911+
var opts []static.Option
912+
if in.GetName() != nil {
913+
opts = append(opts, static.WithName(in.GetName().GetValue()))
914+
}
915+
if in.GetDescription() != nil {
916+
opts = append(opts, static.WithDescription(in.GetDescription().GetValue()))
917+
}
918+
919+
attrs := in.GetPasswordAttributes()
920+
cs, err := static.NewPasswordCredential(
921+
storeId,
922+
credential.Password(attrs.GetPassword().GetValue()),
923+
opts...)
924+
if err != nil {
925+
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to build credential"))
926+
}
927+
928+
return cs, err
929+
}
930+
851931
func toSshPrivateKeyStorageCredential(ctx context.Context, storeId string, in *pb.Credential) (out *static.SshPrivateKeyCredential, err error) {
852932
const op = "credentials.toSshPrivateKeyStorageCredential"
853933
var opts []static.Option
@@ -919,6 +999,7 @@ func validateGetRequest(req *pbs.GetCredentialRequest) error {
919999
globals.UsernamePasswordCredentialPrefix,
9201000
globals.UsernamePasswordCredentialPreviousPrefix,
9211001
globals.UsernamePasswordDomainCredentialPrefix,
1002+
globals.PasswordCredentialPrefix,
9221003
globals.SshPrivateKeyCredentialPrefix,
9231004
globals.JsonCredentialPrefix,
9241005
)
@@ -949,6 +1030,10 @@ func validateCreateRequest(req *pbs.CreateCredentialRequest) error {
9491030
if req.Item.GetUsernamePasswordDomainAttributes().GetDomain().GetValue() == "" {
9501031
badFields[domainField] = "Field required for creating a username-password-domain credential."
9511032
}
1033+
case credential.PasswordSubtype.String():
1034+
if req.Item.GetPasswordAttributes().GetPassword().GetValue() == "" {
1035+
badFields[passwordField] = "Field required for creating a password credential."
1036+
}
9521037
case credential.SshPrivateKeySubtype.String():
9531038
if req.Item.GetSshPrivateKeyAttributes().GetUsername().GetValue() == "" {
9541039
badFields[usernameField] = "Field required for creating an SSH private key credential."
@@ -1018,7 +1103,11 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error {
10181103
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), domainField) && attrs.GetDomain().GetValue() == "" {
10191104
badFields[domainField] = "This is a required field and cannot be set to empty."
10201105
}
1021-
1106+
case credential.PasswordSubtype:
1107+
attrs := req.GetItem().GetPasswordAttributes()
1108+
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), passwordField) && attrs.GetPassword().GetValue() == "" {
1109+
badFields[passwordField] = "This is a required field and cannot be set to empty."
1110+
}
10221111
case credential.SshPrivateKeySubtype:
10231112
attrs := req.GetItem().GetSshPrivateKeyAttributes()
10241113
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), usernameField) && attrs.GetUsername().GetValue() == "" {
@@ -1070,6 +1159,7 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error {
10701159
globals.UsernamePasswordCredentialPrefix,
10711160
globals.UsernamePasswordCredentialPreviousPrefix,
10721161
globals.UsernamePasswordDomainCredentialPrefix,
1162+
globals.PasswordCredentialPrefix,
10731163
globals.SshPrivateKeyCredentialPrefix,
10741164
globals.JsonCredentialPrefix,
10751165
)
@@ -1082,6 +1172,7 @@ func validateDeleteRequest(req *pbs.DeleteCredentialRequest) error {
10821172
globals.UsernamePasswordCredentialPrefix,
10831173
globals.UsernamePasswordCredentialPreviousPrefix,
10841174
globals.UsernamePasswordDomainCredentialPrefix,
1175+
globals.PasswordCredentialPrefix,
10851176
globals.SshPrivateKeyCredentialPrefix,
10861177
globals.JsonCredentialPrefix,
10871178
)

0 commit comments

Comments
 (0)