diff --git a/api/credentials/option.gen.go b/api/credentials/option.gen.go index c6508253cf..9b3d795902 100644 --- a/api/credentials/option.gen.go +++ b/api/credentials/option.gen.go @@ -143,6 +143,18 @@ func DefaultDescription() Option { } } +func WithUsernamePasswordDomainCredentialDomain(inDomain string) Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = any(map[string]any{}) + } + val := raw.(map[string]any) + val["domain"] = inDomain + o.postMap["attributes"] = val + } +} + func WithName(inName string) Option { return func(o *options) { o.postMap["name"] = inName @@ -179,6 +191,18 @@ func WithUsernamePasswordCredentialPassword(inPassword string) Option { } } +func WithUsernamePasswordDomainCredentialPassword(inPassword string) Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = any(map[string]any{}) + } + val := raw.(map[string]any) + val["password"] = inPassword + o.postMap["attributes"] = val + } +} + func WithSshPrivateKeyCredentialPrivateKey(inPrivateKey string) Option { return func(o *options) { raw, ok := o.postMap["attributes"] @@ -238,3 +262,15 @@ func WithUsernamePasswordCredentialUsername(inUsername string) Option { o.postMap["attributes"] = val } } + +func WithUsernamePasswordDomainCredentialUsername(inUsername string) Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = any(map[string]any{}) + } + val := raw.(map[string]any) + val["username"] = inUsername + o.postMap["attributes"] = val + } +} diff --git a/api/credentials/username_password_domain_attributes.gen.go b/api/credentials/username_password_domain_attributes.gen.go new file mode 100644 index 0000000000..87cb2f11bc --- /dev/null +++ b/api/credentials/username_password_domain_attributes.gen.go @@ -0,0 +1,43 @@ +// Code generated by "make api"; DO NOT EDIT. +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package credentials + +import ( + "fmt" + + "github.com/mitchellh/mapstructure" +) + +type UsernamePasswordDomainAttributes struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + PasswordHmac string `json:"password_hmac,omitempty"` + Domain string `json:"domain,omitempty"` +} + +func AttributesMapToUsernamePasswordDomainAttributes(in map[string]any) (*UsernamePasswordDomainAttributes, error) { + if in == nil { + return nil, fmt.Errorf("nil input map") + } + var out UsernamePasswordDomainAttributes + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + Result: &out, + TagName: "json", + }) + if err != nil { + return nil, fmt.Errorf("error creating mapstructure decoder: %w", err) + } + if err := dec.Decode(in); err != nil { + return nil, fmt.Errorf("error decoding: %w", err) + } + return &out, nil +} + +func (pt *Credential) GetUsernamePasswordDomainAttributes() (*UsernamePasswordDomainAttributes, error) { + if pt.Type != "username_password_domain" { + return nil, fmt.Errorf("asked to fetch %s-type attributes but credential is of type %s", "username_password_domain", pt.Type) + } + return AttributesMapToUsernamePasswordDomainAttributes(pt.Attributes) +} diff --git a/internal/api/genapi/input.go b/internal/api/genapi/input.go index 0f497ec2b3..673c83c1d7 100644 --- a/internal/api/genapi/input.go +++ b/internal/api/genapi/input.go @@ -696,6 +696,30 @@ var inputStructs = []*structInfo{ mapstructureConversionTemplate, }, }, + { + inProto: &credentials.UsernamePasswordDomainAttributes{}, + outFile: "credentials/username_password_domain_attributes.gen.go", + subtypeName: "UsernamePasswordDomainCredential", + subtype: "username_password_domain", + fieldOverrides: []fieldInfo{ + { + Name: "Username", + SkipDefault: true, + }, + { + Name: "Password", + SkipDefault: true, + }, + { + Name: "Domain", + SkipDefault: true, + }, + }, + parentTypeName: "Credential", + templates: []*template.Template{ + mapstructureConversionTemplate, + }, + }, { inProto: &credentials.SshPrivateKeyAttributes{}, outFile: "credentials/ssh_private_key_attributes.gen.go", diff --git a/internal/daemon/controller/handlers/credentials/credential_service.go b/internal/daemon/controller/handlers/credentials/credential_service.go index 2afcd305fe..d5469a108b 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service.go +++ b/internal/daemon/controller/handlers/credentials/credential_service.go @@ -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, ) diff --git a/internal/daemon/controller/handlers/credentials/credential_service_test.go b/internal/daemon/controller/handlers/credentials/credential_service_test.go index 7f553dfd7c..be53e5eac0 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service_test.go +++ b/internal/daemon/controller/handlers/credentials/credential_service_test.go @@ -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 diff --git a/internal/proto/controller/api/resources/credentials/v1/credential.proto b/internal/proto/controller/api/resources/credentials/v1/credential.proto index c00c1d8ef2..2b006398cc 100644 --- a/internal/proto/controller/api/resources/credentials/v1/credential.proto +++ b/internal/proto/controller/api/resources/credentials/v1/credential.proto @@ -77,6 +77,11 @@ message Credential { (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.subtype) = "json" ]; + UsernamePasswordDomainAttributes username_password_domain_attributes = 104 [ + (google.api.field_visibility).restriction = "INTERNAL", + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.subtype) = "username_password_domain" + ]; } // Output only. The available actions on this resource for this user. @@ -114,6 +119,44 @@ message UsernamePasswordAttributes { ]; // @gotags: `class:"public"` } +message UsernamePasswordDomainAttributes { + // The username associated with the credential. + google.protobuf.StringValue username = 10 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.mask_mapping) = { + this: "attributes.username" + that: "Username" + } + ]; // @gotags: `class:"public"` + + // Input only. The password associated with the credential. + google.protobuf.StringValue password = 20 [ + json_name = "password", + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.mask_mapping) = { + this: "attributes.password" + that: "Password" + } + ]; // @gotags: `class:"secret"` + + // Output only. The hmac value of the password. + string password_hmac = 30 [ + json_name = "password_hmac", + (custom_options.v1.mask_mapping) = { + this: "attributes.password_hmac" + that: "PasswordHmac" + } + ]; // @gotags: `class:"public"` + + google.protobuf.StringValue domain = 40 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.mask_mapping) = { + this: "attributes.domain" + that: "Domain" + } + ]; // @gotags: `class:"public"` +} + // The attributes of a SshPrivateKey Credential. message SshPrivateKeyAttributes { // The username associated with the credential. diff --git a/sdk/pbs/controller/api/resources/credentials/credential.pb.go b/sdk/pbs/controller/api/resources/credentials/credential.pb.go index 0c5714f99b..e75be32530 100644 --- a/sdk/pbs/controller/api/resources/credentials/credential.pb.go +++ b/sdk/pbs/controller/api/resources/credentials/credential.pb.go @@ -58,6 +58,7 @@ type Credential struct { // *Credential_UsernamePasswordAttributes // *Credential_SshPrivateKeyAttributes // *Credential_JsonAttributes + // *Credential_UsernamePasswordDomainAttributes Attrs isCredential_Attrs `protobuf_oneof:"attrs"` // Output only. The available actions on this resource for this user. AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty" class:"public"` // @gotags: `class:"public"` @@ -201,6 +202,15 @@ func (x *Credential) GetJsonAttributes() *JsonAttributes { return nil } +func (x *Credential) GetUsernamePasswordDomainAttributes() *UsernamePasswordDomainAttributes { + if x != nil { + if x, ok := x.Attrs.(*Credential_UsernamePasswordDomainAttributes); ok { + return x.UsernamePasswordDomainAttributes + } + } + return nil +} + func (x *Credential) GetAuthorizedActions() []string { if x != nil { return x.AuthorizedActions @@ -229,6 +239,10 @@ type Credential_JsonAttributes struct { JsonAttributes *JsonAttributes `protobuf:"bytes,103,opt,name=json_attributes,json=jsonAttributes,proto3,oneof"` } +type Credential_UsernamePasswordDomainAttributes struct { + UsernamePasswordDomainAttributes *UsernamePasswordDomainAttributes `protobuf:"bytes,104,opt,name=username_password_domain_attributes,json=usernamePasswordDomainAttributes,proto3,oneof"` +} + func (*Credential_Attributes) isCredential_Attrs() {} func (*Credential_UsernamePasswordAttributes) isCredential_Attrs() {} @@ -237,6 +251,8 @@ func (*Credential_SshPrivateKeyAttributes) isCredential_Attrs() {} func (*Credential_JsonAttributes) isCredential_Attrs() {} +func (*Credential_UsernamePasswordDomainAttributes) isCredential_Attrs() {} + // The attributes of a UsernamePassword Credential. type UsernamePasswordAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -301,6 +317,77 @@ func (x *UsernamePasswordAttributes) GetPasswordHmac() string { return "" } +type UsernamePasswordDomainAttributes struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The username associated with the credential. + Username *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty" class:"public"` // @gotags: `class:"public"` + // Input only. The password associated with the credential. + Password *wrapperspb.StringValue `protobuf:"bytes,20,opt,name=password,proto3" json:"password,omitempty" class:"secret"` // @gotags: `class:"secret"` + // Output only. The hmac value of the password. + PasswordHmac string `protobuf:"bytes,30,opt,name=password_hmac,proto3" json:"password_hmac,omitempty" class:"public"` // @gotags: `class:"public"` + Domain *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=domain,proto3" json:"domain,omitempty" class:"public"` // @gotags: `class:"public"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UsernamePasswordDomainAttributes) Reset() { + *x = UsernamePasswordDomainAttributes{} + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UsernamePasswordDomainAttributes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsernamePasswordDomainAttributes) ProtoMessage() {} + +func (x *UsernamePasswordDomainAttributes) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UsernamePasswordDomainAttributes.ProtoReflect.Descriptor instead. +func (*UsernamePasswordDomainAttributes) Descriptor() ([]byte, []int) { + return file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP(), []int{2} +} + +func (x *UsernamePasswordDomainAttributes) GetUsername() *wrapperspb.StringValue { + if x != nil { + return x.Username + } + return nil +} + +func (x *UsernamePasswordDomainAttributes) GetPassword() *wrapperspb.StringValue { + if x != nil { + return x.Password + } + return nil +} + +func (x *UsernamePasswordDomainAttributes) GetPasswordHmac() string { + if x != nil { + return x.PasswordHmac + } + return "" +} + +func (x *UsernamePasswordDomainAttributes) GetDomain() *wrapperspb.StringValue { + if x != nil { + return x.Domain + } + return nil +} + // The attributes of a SshPrivateKey Credential. type SshPrivateKeyAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -320,7 +407,7 @@ type SshPrivateKeyAttributes struct { func (x *SshPrivateKeyAttributes) Reset() { *x = SshPrivateKeyAttributes{} - mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[2] + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -332,7 +419,7 @@ func (x *SshPrivateKeyAttributes) String() string { func (*SshPrivateKeyAttributes) ProtoMessage() {} func (x *SshPrivateKeyAttributes) ProtoReflect() protoreflect.Message { - mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[2] + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -345,7 +432,7 @@ func (x *SshPrivateKeyAttributes) ProtoReflect() protoreflect.Message { // Deprecated: Use SshPrivateKeyAttributes.ProtoReflect.Descriptor instead. func (*SshPrivateKeyAttributes) Descriptor() ([]byte, []int) { - return file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP(), []int{2} + return file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP(), []int{3} } func (x *SshPrivateKeyAttributes) GetUsername() *wrapperspb.StringValue { @@ -396,7 +483,7 @@ type JsonAttributes struct { func (x *JsonAttributes) Reset() { *x = JsonAttributes{} - mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[3] + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -408,7 +495,7 @@ func (x *JsonAttributes) String() string { func (*JsonAttributes) ProtoMessage() {} func (x *JsonAttributes) ProtoReflect() protoreflect.Message { - mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[3] + mi := &file_controller_api_resources_credentials_v1_credential_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -421,7 +508,7 @@ func (x *JsonAttributes) ProtoReflect() protoreflect.Message { // Deprecated: Use JsonAttributes.ProtoReflect.Descriptor instead. func (*JsonAttributes) Descriptor() ([]byte, []int) { - return file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP(), []int{3} + return file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP(), []int{4} } func (x *JsonAttributes) GetObject() *structpb.Struct { @@ -442,7 +529,8 @@ var File_controller_api_resources_credentials_v1_credential_proto protoreflect.F const file_controller_api_resources_credentials_v1_credential_proto_rawDesc = "" + "\n" + - "8controller/api/resources/credentials/v1/credential.proto\x12'controller.api.resources.credentials.v1\x1a.controller/api/resources/scopes/v1/scope.proto\x1a*controller/custom_options/v1/options.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\xd6\b\n" + + "8controller/api/resources/credentials/v1/credential.proto\x12'controller.api.resources.credentials.v1\x1a.controller/api/resources/scopes/v1/scope.proto\x1a*controller/custom_options/v1/options.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\xa5\n" + + "\n" + "\n" + "Credential\x12\x0e\n" + "\x02id\x18\n" + @@ -465,7 +553,9 @@ const file_controller_api_resources_credentials_v1_credential_proto_rawDesc = "" "\x1assh_private_key_attributes\x18f \x01(\v2@.controller.api.resources.credentials.v1.SshPrivateKeyAttributesB'\xa0\xda)\x01\x9a\xe3)\x0fssh_private_key\xfa\xd2\xe4\x93\x02\n" + "\x12\bINTERNALH\x00R\x17sshPrivateKeyAttributes\x12\x80\x01\n" + "\x0fjson_attributes\x18g \x01(\v27.controller.api.resources.credentials.v1.JsonAttributesB\x1c\xa0\xda)\x01\x9a\xe3)\x04json\xfa\xd2\xe4\x93\x02\n" + - "\x12\bINTERNALH\x00R\x0ejsonAttributes\x12/\n" + + "\x12\bINTERNALH\x00R\x0ejsonAttributes\x12\xcc\x01\n" + + "#username_password_domain_attributes\x18h \x01(\v2I.controller.api.resources.credentials.v1.UsernamePasswordDomainAttributesB0\xa0\xda)\x01\x9a\xe3)\x18username_password_domain\xfa\xd2\xe4\x93\x02\n" + + "\x12\bINTERNALH\x00R usernamePasswordDomainAttributes\x12/\n" + "\x12authorized_actions\x18\xac\x02 \x03(\tR\x12authorized_actionsB\a\n" + "\x05attrs\"\xb6\x02\n" + "\x1aUsernamePasswordAttributes\x12a\n" + @@ -475,7 +565,17 @@ const file_controller_api_resources_credentials_v1_credential_proto_rawDesc = "" "\bpassword\x18\x14 \x01(\v2\x1c.google.protobuf.StringValueB'\xa0\xda)\x01\xc2\xdd)\x1f\n" + "\x13attributes.password\x12\bPasswordR\bpassword\x12R\n" + "\rpassword_hmac\x18\x1e \x01(\tB,\xc2\xdd)(\n" + - "\x18attributes.password_hmac\x12\fPasswordHmacR\rpassword_hmac\"\xee\x04\n" + + "\x18attributes.password_hmac\x12\fPasswordHmacR\rpassword_hmac\"\x97\x03\n" + + " UsernamePasswordDomainAttributes\x12a\n" + + "\busername\x18\n" + + " \x01(\v2\x1c.google.protobuf.StringValueB'\xa0\xda)\x01\xc2\xdd)\x1f\n" + + "\x13attributes.username\x12\bUsernameR\busername\x12a\n" + + "\bpassword\x18\x14 \x01(\v2\x1c.google.protobuf.StringValueB'\xa0\xda)\x01\xc2\xdd)\x1f\n" + + "\x13attributes.password\x12\bPasswordR\bpassword\x12R\n" + + "\rpassword_hmac\x18\x1e \x01(\tB,\xc2\xdd)(\n" + + "\x18attributes.password_hmac\x12\fPasswordHmacR\rpassword_hmac\x12Y\n" + + "\x06domain\x18( \x01(\v2\x1c.google.protobuf.StringValueB#\xa0\xda)\x01\xc2\xdd)\x1b\n" + + "\x11attributes.domain\x12\x06DomainR\x06domain\"\xee\x04\n" + "\x17SshPrivateKeyAttributes\x12a\n" + "\busername\x18\n" + " \x01(\v2\x1c.google.protobuf.StringValueB'\xa0\xda)\x01\xc2\xdd)\x1f\n" + @@ -509,38 +609,43 @@ func file_controller_api_resources_credentials_v1_credential_proto_rawDescGZIP() return file_controller_api_resources_credentials_v1_credential_proto_rawDescData } -var file_controller_api_resources_credentials_v1_credential_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_controller_api_resources_credentials_v1_credential_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_controller_api_resources_credentials_v1_credential_proto_goTypes = []any{ - (*Credential)(nil), // 0: controller.api.resources.credentials.v1.Credential - (*UsernamePasswordAttributes)(nil), // 1: controller.api.resources.credentials.v1.UsernamePasswordAttributes - (*SshPrivateKeyAttributes)(nil), // 2: controller.api.resources.credentials.v1.SshPrivateKeyAttributes - (*JsonAttributes)(nil), // 3: controller.api.resources.credentials.v1.JsonAttributes - (*scopes.ScopeInfo)(nil), // 4: controller.api.resources.scopes.v1.ScopeInfo - (*wrapperspb.StringValue)(nil), // 5: google.protobuf.StringValue - (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp - (*structpb.Struct)(nil), // 7: google.protobuf.Struct + (*Credential)(nil), // 0: controller.api.resources.credentials.v1.Credential + (*UsernamePasswordAttributes)(nil), // 1: controller.api.resources.credentials.v1.UsernamePasswordAttributes + (*UsernamePasswordDomainAttributes)(nil), // 2: controller.api.resources.credentials.v1.UsernamePasswordDomainAttributes + (*SshPrivateKeyAttributes)(nil), // 3: controller.api.resources.credentials.v1.SshPrivateKeyAttributes + (*JsonAttributes)(nil), // 4: controller.api.resources.credentials.v1.JsonAttributes + (*scopes.ScopeInfo)(nil), // 5: controller.api.resources.scopes.v1.ScopeInfo + (*wrapperspb.StringValue)(nil), // 6: google.protobuf.StringValue + (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 8: google.protobuf.Struct } var file_controller_api_resources_credentials_v1_credential_proto_depIdxs = []int32{ - 4, // 0: controller.api.resources.credentials.v1.Credential.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 5, // 1: controller.api.resources.credentials.v1.Credential.name:type_name -> google.protobuf.StringValue - 5, // 2: controller.api.resources.credentials.v1.Credential.description:type_name -> google.protobuf.StringValue - 6, // 3: controller.api.resources.credentials.v1.Credential.created_time:type_name -> google.protobuf.Timestamp - 6, // 4: controller.api.resources.credentials.v1.Credential.updated_time:type_name -> google.protobuf.Timestamp - 7, // 5: controller.api.resources.credentials.v1.Credential.attributes:type_name -> google.protobuf.Struct + 5, // 0: controller.api.resources.credentials.v1.Credential.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 6, // 1: controller.api.resources.credentials.v1.Credential.name:type_name -> google.protobuf.StringValue + 6, // 2: controller.api.resources.credentials.v1.Credential.description:type_name -> google.protobuf.StringValue + 7, // 3: controller.api.resources.credentials.v1.Credential.created_time:type_name -> google.protobuf.Timestamp + 7, // 4: controller.api.resources.credentials.v1.Credential.updated_time:type_name -> google.protobuf.Timestamp + 8, // 5: controller.api.resources.credentials.v1.Credential.attributes:type_name -> google.protobuf.Struct 1, // 6: controller.api.resources.credentials.v1.Credential.username_password_attributes:type_name -> controller.api.resources.credentials.v1.UsernamePasswordAttributes - 2, // 7: controller.api.resources.credentials.v1.Credential.ssh_private_key_attributes:type_name -> controller.api.resources.credentials.v1.SshPrivateKeyAttributes - 3, // 8: controller.api.resources.credentials.v1.Credential.json_attributes:type_name -> controller.api.resources.credentials.v1.JsonAttributes - 5, // 9: controller.api.resources.credentials.v1.UsernamePasswordAttributes.username:type_name -> google.protobuf.StringValue - 5, // 10: controller.api.resources.credentials.v1.UsernamePasswordAttributes.password:type_name -> google.protobuf.StringValue - 5, // 11: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.username:type_name -> google.protobuf.StringValue - 5, // 12: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.private_key:type_name -> google.protobuf.StringValue - 5, // 13: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.private_key_passphrase:type_name -> google.protobuf.StringValue - 7, // 14: controller.api.resources.credentials.v1.JsonAttributes.object:type_name -> google.protobuf.Struct - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 3, // 7: controller.api.resources.credentials.v1.Credential.ssh_private_key_attributes:type_name -> controller.api.resources.credentials.v1.SshPrivateKeyAttributes + 4, // 8: controller.api.resources.credentials.v1.Credential.json_attributes:type_name -> controller.api.resources.credentials.v1.JsonAttributes + 2, // 9: controller.api.resources.credentials.v1.Credential.username_password_domain_attributes:type_name -> controller.api.resources.credentials.v1.UsernamePasswordDomainAttributes + 6, // 10: controller.api.resources.credentials.v1.UsernamePasswordAttributes.username:type_name -> google.protobuf.StringValue + 6, // 11: controller.api.resources.credentials.v1.UsernamePasswordAttributes.password:type_name -> google.protobuf.StringValue + 6, // 12: controller.api.resources.credentials.v1.UsernamePasswordDomainAttributes.username:type_name -> google.protobuf.StringValue + 6, // 13: controller.api.resources.credentials.v1.UsernamePasswordDomainAttributes.password:type_name -> google.protobuf.StringValue + 6, // 14: controller.api.resources.credentials.v1.UsernamePasswordDomainAttributes.domain:type_name -> google.protobuf.StringValue + 6, // 15: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.username:type_name -> google.protobuf.StringValue + 6, // 16: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.private_key:type_name -> google.protobuf.StringValue + 6, // 17: controller.api.resources.credentials.v1.SshPrivateKeyAttributes.private_key_passphrase:type_name -> google.protobuf.StringValue + 8, // 18: controller.api.resources.credentials.v1.JsonAttributes.object:type_name -> google.protobuf.Struct + 19, // [19:19] is the sub-list for method output_type + 19, // [19:19] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_controller_api_resources_credentials_v1_credential_proto_init() } @@ -553,6 +658,7 @@ func file_controller_api_resources_credentials_v1_credential_proto_init() { (*Credential_UsernamePasswordAttributes)(nil), (*Credential_SshPrivateKeyAttributes)(nil), (*Credential_JsonAttributes)(nil), + (*Credential_UsernamePasswordDomainAttributes)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -560,7 +666,7 @@ func file_controller_api_resources_credentials_v1_credential_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_controller_api_resources_credentials_v1_credential_proto_rawDesc), len(file_controller_api_resources_credentials_v1_credential_proto_rawDesc)), NumEnums: 0, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, },