feat(handlers): CRUDL support for static Username-Password-Domain credentials
This commit is contained in:
1 parent
e4dfa76c8e
commit
f265ec4e5b
7 files changed
+724
-52
No files matched your search
@@ -37,6 +37,7 @@ import (
|
||||
const (
|
||||
usernameField = "attributes.username"
|
||||
passwordField = "attributes.password"
|
||||
domainField = "attributes.domain"
|
||||
privateKeyField = "attributes.private_key"
|
||||
privateKeyPassphraseField = "attributes.private_key_passphrase"
|
||||
objectField = "attributes.object"
|
||||
@@ -44,6 +45,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
updMaskManager handlers.MaskManager
|
||||
upMaskManager handlers.MaskManager
|
||||
spkMaskManager handlers.MaskManager
|
||||
jsonMaskManager handlers.MaskManager
|
||||
@@ -88,6 +90,13 @@ func init() {
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if updMaskManager, err = handlers.NewMaskManager(
|
||||
context.Background(),
|
||||
handlers.MaskDestination{&store.UsernamePasswordDomainCredential{}},
|
||||
handlers.MaskSource{&pb.Credential{}, &pb.UsernamePasswordDomainAttributes{}},
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// TODO: refactor to remove IdActionsMap and CollectionActions package variables
|
||||
action.RegisterResource(resource.Credential, IdActions, CollectionActions)
|
||||
@@ -428,6 +437,23 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Cred
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential but no error returned from repository.")
|
||||
}
|
||||
return out, nil
|
||||
case credential.UsernamePasswordDomainSubtype.String():
|
||||
cred, err := toUsernamePasswordDomainStorageCredential(ctx, item.GetCredentialStoreId(), item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, err := repo.CreateUsernamePasswordDomainCredential(ctx, scopeId, cred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential"))
|
||||
}
|
||||
if out == nil {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential but no error returned from repository.")
|
||||
}
|
||||
return out, nil
|
||||
case credential.SshPrivateKeySubtype.String():
|
||||
cred, err := toSshPrivateKeyStorageCredential(ctx, item.GetCredentialStoreId(), item)
|
||||
if err != nil {
|
||||
@@ -502,6 +528,29 @@ func (s Service) updateInRepo(
|
||||
return nil, handlers.NotFoundErrorf("Credential %q doesn't exist or incorrect version provided.", id)
|
||||
}
|
||||
return out, nil
|
||||
case credential.UsernamePasswordDomainSubtype:
|
||||
dbMasks = append(dbMasks, updMaskManager.Translate(masks)...)
|
||||
if len(dbMasks) == 0 {
|
||||
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."})
|
||||
}
|
||||
|
||||
cred, err := toUsernamePasswordDomainStorageCredential(ctx, storeId, in)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to convert to username/password/domain storage credential"))
|
||||
}
|
||||
cred.PublicId = id
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, rowsUpdated, err := repo.UpdateUsernamePasswordDomainCredential(ctx, scopeId, cred, item.GetVersion(), dbMasks)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential"))
|
||||
}
|
||||
if rowsUpdated == 0 {
|
||||
return nil, handlers.NotFoundErrorf("Credential %q doesn't exist or incorrect version provided.", id)
|
||||
}
|
||||
return out, nil
|
||||
|
||||
case credential.SshPrivateKeySubtype:
|
||||
dbMasks = append(dbMasks, spkMaskManager.Translate(masks)...)
|
||||
@@ -680,6 +729,8 @@ func toProto(in credential.Static, opt ...handlers.Option) (*pb.Credential, erro
|
||||
switch in.(type) {
|
||||
case *static.UsernamePasswordCredential:
|
||||
out.Type = credential.UsernamePasswordSubtype.String()
|
||||
case *static.UsernamePasswordDomainCredential:
|
||||
out.Type = credential.UsernamePasswordDomainSubtype.String()
|
||||
case *static.SshPrivateKeyCredential:
|
||||
out.Type = credential.SshPrivateKeySubtype.String()
|
||||
case *static.JsonCredential:
|
||||
@@ -718,6 +769,16 @@ func toProto(in credential.Static, opt ...handlers.Option) (*pb.Credential, erro
|
||||
},
|
||||
}
|
||||
}
|
||||
case *static.UsernamePasswordDomainCredential:
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
out.Attrs = &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String(cred.GetUsername()),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString(cred.GetPasswordHmac()),
|
||||
Domain: wrapperspb.String(cred.GetDomain()),
|
||||
},
|
||||
}
|
||||
}
|
||||
case *static.SshPrivateKeyCredential:
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
out.Attrs = &pb.Credential_SshPrivateKeyAttributes{
|
||||
@@ -763,6 +824,30 @@ func toUsernamePasswordStorageCredential(ctx context.Context, storeId string, in
|
||||
return cs, err
|
||||
}
|
||||
|
||||
func toUsernamePasswordDomainStorageCredential(ctx context.Context, storeId string, in *pb.Credential) (out *static.UsernamePasswordDomainCredential, err error) {
|
||||
const op = "credentials.toUsernamePasswordDomainStorageCredential"
|
||||
var opts []static.Option
|
||||
if in.GetName() != nil {
|
||||
opts = append(opts, static.WithName(in.GetName().GetValue()))
|
||||
}
|
||||
if in.GetDescription() != nil {
|
||||
opts = append(opts, static.WithDescription(in.GetDescription().GetValue()))
|
||||
}
|
||||
|
||||
attrs := in.GetUsernamePasswordDomainAttributes()
|
||||
cs, err := static.NewUsernamePasswordDomainCredential(
|
||||
storeId,
|
||||
attrs.GetUsername().GetValue(),
|
||||
credential.Password(attrs.GetPassword().GetValue()),
|
||||
attrs.GetDomain().GetValue(),
|
||||
opts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to build credential"))
|
||||
}
|
||||
|
||||
return cs, err
|
||||
}
|
||||
|
||||
func toSshPrivateKeyStorageCredential(ctx context.Context, storeId string, in *pb.Credential) (out *static.SshPrivateKeyCredential, err error) {
|
||||
const op = "credentials.toSshPrivateKeyStorageCredential"
|
||||
var opts []static.Option
|
||||
@@ -833,6 +918,7 @@ func validateGetRequest(req *pbs.GetCredentialRequest) error {
|
||||
req,
|
||||
globals.UsernamePasswordCredentialPrefix,
|
||||
globals.UsernamePasswordCredentialPreviousPrefix,
|
||||
globals.UsernamePasswordDomainCredentialPrefix,
|
||||
globals.SshPrivateKeyCredentialPrefix,
|
||||
globals.JsonCredentialPrefix,
|
||||
)
|
||||
@@ -853,7 +939,16 @@ func validateCreateRequest(req *pbs.CreateCredentialRequest) error {
|
||||
if req.Item.GetUsernamePasswordAttributes().GetPassword().GetValue() == "" {
|
||||
badFields[passwordField] = "Field required for creating a username-password credential."
|
||||
}
|
||||
|
||||
case credential.UsernamePasswordDomainSubtype.String():
|
||||
if req.Item.GetUsernamePasswordDomainAttributes().GetUsername().GetValue() == "" {
|
||||
badFields[usernameField] = "Field required for creating a username-password-domain credential."
|
||||
}
|
||||
if req.Item.GetUsernamePasswordDomainAttributes().GetPassword().GetValue() == "" {
|
||||
badFields[passwordField] = "Field required for creating a username-password-domain credential."
|
||||
}
|
||||
if req.Item.GetUsernamePasswordDomainAttributes().GetDomain().GetValue() == "" {
|
||||
badFields[domainField] = "Field required for creating a username-password-domain credential."
|
||||
}
|
||||
case credential.SshPrivateKeySubtype.String():
|
||||
if req.Item.GetSshPrivateKeyAttributes().GetUsername().GetValue() == "" {
|
||||
badFields[usernameField] = "Field required for creating an SSH private key credential."
|
||||
@@ -912,6 +1007,18 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error {
|
||||
badFields[passwordField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
|
||||
case credential.UsernamePasswordDomainSubtype:
|
||||
attrs := req.GetItem().GetUsernamePasswordDomainAttributes()
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), usernameField) && attrs.GetUsername().GetValue() == "" {
|
||||
badFields[usernameField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), passwordField) && attrs.GetPassword().GetValue() == "" {
|
||||
badFields[passwordField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), domainField) && attrs.GetDomain().GetValue() == "" {
|
||||
badFields[domainField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
|
||||
case credential.SshPrivateKeySubtype:
|
||||
attrs := req.GetItem().GetSshPrivateKeyAttributes()
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), usernameField) && attrs.GetUsername().GetValue() == "" {
|
||||
@@ -962,6 +1069,7 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error {
|
||||
},
|
||||
globals.UsernamePasswordCredentialPrefix,
|
||||
globals.UsernamePasswordCredentialPreviousPrefix,
|
||||
globals.UsernamePasswordDomainCredentialPrefix,
|
||||
globals.SshPrivateKeyCredentialPrefix,
|
||||
globals.JsonCredentialPrefix,
|
||||
)
|
||||
@@ -973,6 +1081,7 @@ func validateDeleteRequest(req *pbs.DeleteCredentialRequest) error {
|
||||
req,
|
||||
globals.UsernamePasswordCredentialPrefix,
|
||||
globals.UsernamePasswordCredentialPreviousPrefix,
|
||||
globals.UsernamePasswordDomainCredentialPrefix,
|
||||
globals.SshPrivateKeyCredentialPrefix,
|
||||
globals.JsonCredentialPrefix,
|
||||
)
|
||||
|
||||
@@ -87,6 +87,26 @@ func staticPasswordCredentialToProto(cred *static.UsernamePasswordCredential, pr
|
||||
}
|
||||
}
|
||||
|
||||
func staticPasswordDomainCredentialToProto(cred *static.UsernamePasswordDomainCredential, prj *iam.Scope, hmac string) *pb.Credential {
|
||||
return &pb.Credential{
|
||||
Id: cred.GetPublicId(),
|
||||
CredentialStoreId: cred.GetStoreId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
CreatedTime: cred.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: cred.GetUpdateTime().GetTimestamp(),
|
||||
Version: cred.GetVersion(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String(cred.GetUsername()),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString([]byte(hmac)),
|
||||
Domain: wrapperspb.String(cred.GetDomain()),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func staticSshCredentialToProto(cred *static.SshPrivateKeyCredential, prj *iam.Scope, hmac string) *pb.Credential {
|
||||
return &pb.Credential{
|
||||
Id: cred.GetPublicId(),
|
||||
@@ -137,6 +157,12 @@ func TestList(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
wantCreds = append(wantCreds, staticPasswordCredentialToProto(c, prj, hm))
|
||||
|
||||
domain := fmt.Sprintf("domain-%d", i)
|
||||
upd := static.TestUsernamePasswordDomainCredential(t, conn, wrapper, user, pass, domain, store.GetPublicId(), prj.GetPublicId())
|
||||
hm, err = crypto.HmacSha256(ctx, []byte(pass), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
wantCreds = append(wantCreds, staticPasswordDomainCredentialToProto(upd, prj, hm))
|
||||
|
||||
spk := static.TestSshPrivateKeyCredential(t, conn, wrapper, user, static.TestSshPrivateKeyPem, store.GetPublicId(), prj.GetPublicId())
|
||||
hm, err = crypto.HmacSha256(ctx, []byte(static.TestSshPrivateKeyPem), databaseWrapper, []byte(store.GetPublicId()), nil)
|
||||
require.NoError(t, err)
|
||||
@@ -167,7 +193,7 @@ func TestList(t *testing.T) {
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 30,
|
||||
EstItemCount: 40,
|
||||
},
|
||||
anonRes: &pbs.ListCredentialsResponse{
|
||||
Items: wantCreds,
|
||||
@@ -221,15 +247,15 @@ func TestList(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Filter on Attribute",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: fmt.Sprintf(`"/item/attributes/username"==%q`, wantCreds[3].GetUsernamePasswordAttributes().GetUsername().Value)},
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: fmt.Sprintf(`"/item/attributes/username"==%q`, wantCreds[4].GetUsernamePasswordAttributes().GetUsername().Value)},
|
||||
res: &pbs.ListCredentialsResponse{
|
||||
Items: wantCreds[3:5],
|
||||
Items: wantCreds[4:7],
|
||||
ResponseType: "complete",
|
||||
ListToken: "",
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 2,
|
||||
EstItemCount: 3,
|
||||
},
|
||||
anonRes: &pbs.ListCredentialsResponse{
|
||||
ResponseType: "complete",
|
||||
@@ -333,6 +359,10 @@ func TestGet(t *testing.T) {
|
||||
upHm, err := crypto.HmacSha256(context.Background(), []byte("pass"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
|
||||
updCred := static.TestUsernamePasswordDomainCredential(t, conn, wrapper, "user", "pass", "domain", store.GetPublicId(), prj.GetPublicId())
|
||||
updHm, err := crypto.HmacSha256(context.Background(), []byte("pass"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
|
||||
spkCred := static.TestSshPrivateKeyCredential(t, conn, wrapper, "user", static.TestSshPrivateKeyPem, store.GetPublicId(), prj.GetPublicId())
|
||||
spkHm, err := crypto.HmacSha256(context.Background(), []byte(static.TestSshPrivateKeyPem), databaseWrapper, []byte(store.GetPublicId()), nil)
|
||||
require.NoError(t, err)
|
||||
@@ -402,6 +432,30 @@ func TestGet(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success-upd",
|
||||
id: updCred.GetPublicId(),
|
||||
res: &pbs.GetCredentialResponse{
|
||||
Item: &pb.Credential{
|
||||
Id: updCred.GetPublicId(),
|
||||
CredentialStoreId: updCred.GetStoreId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: store.GetProjectId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
CreatedTime: updCred.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: updCred.UpdateTime.GetTimestamp(),
|
||||
Version: 1,
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("user"),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString([]byte(updHm)),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "success-spk",
|
||||
id: spkCred.GetPublicId(),
|
||||
@@ -534,6 +588,7 @@ func TestDelete(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
upCred := static.TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId())
|
||||
updCred := static.TestUsernamePasswordDomainCredential(t, conn, wrapper, "user", "pass", "domain", store.GetPublicId(), prj.GetPublicId())
|
||||
spkCred := static.TestSshPrivateKeyCredential(t, conn, wrapper, "user", static.TestSshPrivateKeyPem, store.GetPublicId(), prj.GetPublicId())
|
||||
|
||||
obj, _ := static.TestJsonObject(t)
|
||||
@@ -550,6 +605,10 @@ func TestDelete(t *testing.T) {
|
||||
name: "success-up",
|
||||
id: upCred.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "success-upd",
|
||||
id: updCred.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "success-spk",
|
||||
id: spkCred.GetPublicId(),
|
||||
@@ -654,6 +713,7 @@ func TestCreate(t *testing.T) {
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -718,6 +778,134 @@ func TestCreate(t *testing.T) {
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Id UPD",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Id: globals.UsernamePasswordDomainCredentialPrefix + "_notallowed",
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Invalid Credential Store Id UPD",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: "p_invalidid",
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Created Time",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: timestamppb.Now(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Updated Time",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide type",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide username",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Password: wrapperspb.String("password"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide password",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Domain: wrapperspb.String("domain"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Must provide domain",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: credential.UsernamePasswordDomainSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide private key",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
@@ -995,6 +1183,16 @@ func TestUpdate(t *testing.T) {
|
||||
return cred, clean
|
||||
}
|
||||
|
||||
freshCredUpd := func(user, pass, domain string) (*static.UsernamePasswordDomainCredential, func()) {
|
||||
t.Helper()
|
||||
cred := static.TestUsernamePasswordDomainCredential(t, conn, wrapper, user, pass, domain, store.GetPublicId(), prj.GetPublicId())
|
||||
clean := func() {
|
||||
_, err := s.DeleteCredential(ctx, &pbs.DeleteCredentialRequest{Id: cred.GetPublicId()})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
return cred, clean
|
||||
}
|
||||
|
||||
freshCredSpk := func(user string) (*static.SshPrivateKeyCredential, func()) {
|
||||
t.Helper()
|
||||
cred := static.TestSshPrivateKeyCredential(t, conn, wrapper, user, static.TestSshPrivateKeyPem, store.GetPublicId(), prj.GetPublicId())
|
||||
@@ -1113,6 +1311,24 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-domainupd",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.username"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("new-user-name"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.GetUsernamePasswordDomainAttributes().Username = wrapperspb.String("new-user-name")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-spk",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
@@ -1151,6 +1367,44 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-password-domainupd",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.password"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Password: wrapperspb.String("new-password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("new-password"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
out.GetUsernamePasswordDomainAttributes().PasswordHmac = base64.RawURLEncoding.EncodeToString([]byte(hm))
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-domain-domainupd",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.domain"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Domain: wrapperspb.String("new-domain"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.GetUsernamePasswordDomainAttributes().Domain = wrapperspb.String("new-domain")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-spk",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
@@ -1195,6 +1449,56 @@ func TestUpdate(t *testing.T) {
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-password-domainupd",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.username", "attributes.password"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("new-username"),
|
||||
Password: wrapperspb.String("new-password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
|
||||
out.GetUsernamePasswordDomainAttributes().Username = wrapperspb.String("new-username")
|
||||
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("new-password"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
out.GetUsernamePasswordDomainAttributes().PasswordHmac = base64.RawURLEncoding.EncodeToString([]byte(hm))
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-password-and-domain-domainupd",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.username", "attributes.password", "attributes.domain"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordDomainAttributes{
|
||||
UsernamePasswordDomainAttributes: &pb.UsernamePasswordDomainAttributes{
|
||||
Username: wrapperspb.String("new-username"),
|
||||
Password: wrapperspb.String("new-password"),
|
||||
Domain: wrapperspb.String("new-domain"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
|
||||
out.GetUsernamePasswordDomainAttributes().Username = wrapperspb.String("new-username")
|
||||
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("new-password"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
out.GetUsernamePasswordDomainAttributes().Domain = wrapperspb.String("new-domain")
|
||||
out.GetUsernamePasswordDomainAttributes().PasswordHmac = base64.RawURLEncoding.EncodeToString([]byte(hm))
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-and-spk",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
@@ -1357,6 +1661,8 @@ func TestUpdate(t *testing.T) {
|
||||
cred, cleanup = freshCredSpk("user")
|
||||
} else if strings.Contains(tc.name, "json") {
|
||||
cred, cleanup = freshCredJson()
|
||||
} else if strings.Contains(tc.name, "domainupd") {
|
||||
cred, cleanup = freshCredUpd("user", "pass", "domain")
|
||||
} else {
|
||||
cred, cleanup = freshCredUp("user", "pass")
|
||||
}
|
||||
@@ -1532,6 +1838,11 @@ func TestListPagination(t *testing.T) {
|
||||
require.NoError(err)
|
||||
allCredentials = append(allCredentials, staticSshCredentialToProto(l, prj, hm))
|
||||
}
|
||||
for _, l := range static.TestUsernamePasswordDomainCredentials(t, conn, wrapper, "username", "password", "domain", credStore.GetPublicId(), prj.PublicId, 5) {
|
||||
hm, err := crypto.HmacSha256(ctx, []byte("password"), databaseWrapper, []byte(credStore.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
allCredentials = append(allCredentials, staticPasswordDomainCredentialToProto(l, prj, hm))
|
||||
}
|
||||
for _, l := range static.TestUsernamePasswordCredentials(t, conn, wrapper, "username", "password", credStore.GetPublicId(), prj.PublicId, 5) {
|
||||
hm, err := crypto.HmacSha256(ctx, []byte("password"), databaseWrapper, []byte(credStore.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
@@ -1592,7 +1903,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1618,7 +1929,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1630,10 +1941,10 @@ func TestListPagination(t *testing.T) {
|
||||
|
||||
// Request rest of results
|
||||
req.ListToken = got.ListToken
|
||||
req.PageSize = 15
|
||||
req.PageSize = 16
|
||||
got, err = s.ListCredentials(ctx, req)
|
||||
require.NoError(err)
|
||||
require.Len(got.GetItems(), 11)
|
||||
require.Len(got.GetItems(), 16)
|
||||
// Compare without comparing the list token
|
||||
assert.Empty(
|
||||
cmp.Diff(
|
||||
@@ -1645,7 +1956,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1714,7 +2025,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortDir: "desc",
|
||||
// Should contain the deleted credential
|
||||
RemovedIds: []string{deletedCred.Id},
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1738,7 +2049,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortBy: "updated_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1767,7 +2078,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortDir: "desc",
|
||||
// Should be empty again
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
@@ -1791,7 +2102,7 @@ func TestListPagination(t *testing.T) {
|
||||
SortBy: "created_time",
|
||||
SortDir: "desc",
|
||||
RemovedIds: nil,
|
||||
EstItemCount: 15,
|
||||
EstItemCount: 20,
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b string) bool {
|
||||
return a < b
|
||||
|
||||
Reference in new issue
Block a user