From 84dd5543cfb560baf80cf88cb9fbdc5c69295a51 Mon Sep 17 00:00:00 2001 From: Hugo <10965479+hugoghx@users.noreply.github.com> Date: Wed, 27 Aug 2025 20:36:10 +0100 Subject: [PATCH] feat(handlers/credentiallibraries): Support Vault LDAP credential library --- api/credentiallibraries/option.gen.go | 12 + ..._ldap_credential_library_attributes.gen.go | 40 ++ internal/api/genapi/input.go | 16 + .../credentiallibrary_service.go | 201 ++++++-- .../credentiallibrary_service_test.go | 474 +++++++++++++++++- .../handlers/targets/target_service.go | 6 + .../v1/credential_library.proto | 17 + .../credential_library.pb.go | 145 ++++-- 8 files changed, 820 insertions(+), 91 deletions(-) create mode 100644 api/credentiallibraries/vault_ldap_credential_library_attributes.gen.go diff --git a/api/credentiallibraries/option.gen.go b/api/credentiallibraries/option.gen.go index ffbadffd7..9e9ff2584 100644 --- a/api/credentiallibraries/option.gen.go +++ b/api/credentiallibraries/option.gen.go @@ -383,6 +383,18 @@ func WithVaultCredentialLibraryPath(inPath string) Option { } } +func WithVaultLdapCredentialLibraryPath(inPath string) Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = any(map[string]any{}) + } + val := raw.(map[string]any) + val["path"] = inPath + o.postMap["attributes"] = val + } +} + func WithVaultSSHCertificateCredentialLibraryPath(inPath string) Option { return func(o *options) { raw, ok := o.postMap["attributes"] diff --git a/api/credentiallibraries/vault_ldap_credential_library_attributes.gen.go b/api/credentiallibraries/vault_ldap_credential_library_attributes.gen.go new file mode 100644 index 000000000..ce3b26dc2 --- /dev/null +++ b/api/credentiallibraries/vault_ldap_credential_library_attributes.gen.go @@ -0,0 +1,40 @@ +// Code generated by "make api"; DO NOT EDIT. +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package credentiallibraries + +import ( + "fmt" + + "github.com/mitchellh/mapstructure" +) + +type VaultLdapCredentialLibraryAttributes struct { + Path string `json:"path,omitempty"` +} + +func AttributesMapToVaultLdapCredentialLibraryAttributes(in map[string]any) (*VaultLdapCredentialLibraryAttributes, error) { + if in == nil { + return nil, fmt.Errorf("nil input map") + } + var out VaultLdapCredentialLibraryAttributes + 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 *CredentialLibrary) GetVaultLdapCredentialLibraryAttributes() (*VaultLdapCredentialLibraryAttributes, error) { + if pt.Type != "vault-ldap" { + return nil, fmt.Errorf("asked to fetch %s-type attributes but credential-library is of type %s", "vault-ldap", pt.Type) + } + return AttributesMapToVaultLdapCredentialLibraryAttributes(pt.Attributes) +} diff --git a/internal/api/genapi/input.go b/internal/api/genapi/input.go index 5b32f31dd..f204c9af1 100644 --- a/internal/api/genapi/input.go +++ b/internal/api/genapi/input.go @@ -641,6 +641,22 @@ var inputStructs = []*structInfo{ mapstructureConversionTemplate, }, }, + { + inProto: &credentiallibraries.VaultLdapCredentialLibraryAttributes{}, + outFile: "credentiallibraries/vault_ldap_credential_library_attributes.gen.go", + subtypeName: "VaultLdapCredentialLibrary", + subtype: "vault-ldap", + fieldOverrides: []fieldInfo{ + { + Name: "Path", + SkipDefault: true, + }, + }, + parentTypeName: "CredentialLibrary", + templates: []*template.Template{ + mapstructureConversionTemplate, + }, + }, { inProto: &credentiallibraries.CredentialLibrary{}, outFile: "credentiallibraries/credential_library.gen.go", diff --git a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go index 3c785c55e..b6a61c335 100644 --- a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go +++ b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go @@ -60,6 +60,7 @@ const ( var ( maskManager handlers.MaskManager sshCertMaskManager handlers.MaskManager + ldapMaskManager handlers.MaskManager // IdActions contains the set of actions that can be performed on // individual resources @@ -107,6 +108,13 @@ func init() { ); err != nil { panic(err) } + if ldapMaskManager, err = handlers.NewMaskManager( + context.Background(), + handlers.MaskDestination{&store.LdapCredentialLibrary{}}, + handlers.MaskSource{&pb.CredentialLibrary{}, &pb.VaultLdapCredentialLibraryAttributes{}}, + ); err != nil { + panic(err) + } // TODO: refactor to remove IdActionsMap and CollectionActions package variables action.RegisterResource(resource.CredentialLibrary, IdActions, CollectionActions) @@ -366,19 +374,27 @@ func (s Service) UpdateCredentialLibrary(ctx context.Context, req *pbs.UpdateCre var currentCredentialType globals.CredentialType var mo vault.MappingOverride switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { - case vault.SSHCertificateLibrarySubtype: - cur, err := repo.LookupSSHCertificateCredentialLibrary(ctx, req.Id) - if err != nil { - return nil, err - } - currentCredentialType = globals.CredentialType(cur.GetCredentialType()) - default: + case vault.GenericLibrarySubtype: cur, err := repo.LookupCredentialLibrary(ctx, req.Id) if err != nil { return nil, err } currentCredentialType = globals.CredentialType(cur.GetCredentialType()) mo = cur.MappingOverride + case vault.SSHCertificateLibrarySubtype: + cur, err := repo.LookupSSHCertificateCredentialLibrary(ctx, req.Id) + if err != nil { + return nil, err + } + currentCredentialType = globals.CredentialType(cur.GetCredentialType()) + case vault.LdapCredentialLibrarySubtype: + cur, err := repo.LookupLdapCredentialLibrary(ctx, req.GetId()) + if err != nil { + return nil, err + } + currentCredentialType = globals.CredentialType(cur.GetCredentialType()) + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, "unknown vault credential library subtype") } if err := validateUpdateRequest(req, currentCredentialType); err != nil { @@ -456,6 +472,15 @@ func (s Service) getFromRepo(ctx context.Context, id string) (credential.Library return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("ssh certificate credential library %q not found", id)) } return cs, err + case vault.LdapCredentialLibrarySubtype: + cs, err := repo.LookupLdapCredentialLibrary(ctx, id) + if err != nil && !errors.IsNotFoundError(err) { + return nil, errors.Wrap(ctx, err, op) + } + if cs == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("ldapcredential library %q not found", id)) + } + return cs, err } return nil, errors.New(ctx, errors.InvalidParameter, op, "unrecognized credential library subtype") } @@ -464,6 +489,23 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Cred const op = "credentiallibraries.(Service).createInRepo" var out credential.Library switch item.GetType() { + case vault.GenericLibrarySubtype.String(): + cl, err := toStorageVaultLibrary(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) + } + rl, err := repo.CreateCredentialLibrary(ctx, scopeId, cl) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential library")) + } + if rl == nil { + return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential library but no error returned from repository.") + } + out = rl case vault.SSHCertificateLibrarySubtype.String(): cl, err := toStorageVaultSSHCertificateLibrary(ctx, item.GetCredentialStoreId(), item) if err != nil { @@ -481,8 +523,8 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Cred return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create ssh certificate credential library but no error returned from repository.") } out = rl - default: - cl, err := toStorageVaultLibrary(ctx, item.GetCredentialStoreId(), item) + case vault.LdapCredentialLibrarySubtype.String(): + cl, err := toStorageVaultLdapLibrary(ctx, item.GetCredentialStoreId(), item) if err != nil { return nil, errors.Wrap(ctx, err, op) } @@ -490,14 +532,16 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Cred if err != nil { return nil, errors.Wrap(ctx, err, op) } - rl, err := repo.CreateCredentialLibrary(ctx, scopeId, cl) + rl, err := repo.CreateLdapCredentialLibrary(ctx, scopeId, cl) if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential library")) + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create ldap credential library")) } if rl == nil { - return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential library but no error returned from repository.") + return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create ldap credential library but no error returned from repository.") } out = rl + default: + return nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, "Unknown vault credential library subtype %q", item.GetType()) } return out, nil } @@ -534,6 +578,23 @@ func (s Service) updateInRepo( return nil, errors.Wrap(ctx, err, op) } switch globals.ResourceInfoFromPrefix(id).Subtype { + case vault.GenericLibrarySubtype: + dbMasks = append(dbMasks, maskManager.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."}) + } + cl, err := toStorageVaultLibrary(ctx, item.GetCredentialStoreId(), item) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + cl.PublicId = id + out, rowsUpdated, err = repo.UpdateCredentialLibrary(ctx, projId, cl, item.GetVersion(), dbMasks) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential library")) + } + if rowsUpdated == 0 { + return nil, handlers.NotFoundErrorf("Credential Library %q doesn't exist or incorrect version provided.", id) + } case vault.SSHCertificateLibrarySubtype: dbMasks = append(dbMasks, sshCertMaskManager.Translate(masks)...) if getMapUpdate(criticalOptionsField, masks) { @@ -557,23 +618,25 @@ func (s Service) updateInRepo( if rowsUpdated == 0 { return nil, handlers.NotFoundErrorf("Credential Library %q doesn't exist or incorrect version provided.", id) } - default: - dbMasks = append(dbMasks, maskManager.Translate(masks)...) + case vault.LdapCredentialLibrarySubtype: + dbMasks = append(dbMasks, ldapMaskManager.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."}) } - cl, err := toStorageVaultLibrary(ctx, item.GetCredentialStoreId(), item) + cl, err := toStorageVaultLdapLibrary(ctx, item.GetCredentialStoreId(), item) if err != nil { return nil, errors.Wrap(ctx, err, op) } cl.PublicId = id - out, rowsUpdated, err = repo.UpdateCredentialLibrary(ctx, projId, cl, item.GetVersion(), dbMasks) + out, rowsUpdated, err = repo.UpdateLdapCredentialLibrary(ctx, projId, cl, item.GetVersion(), dbMasks) if err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential library")) } if rowsUpdated == 0 { return nil, handlers.NotFoundErrorf("Credential Library %q doesn't exist or incorrect version provided.", id) } + default: + return nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, "Unknown vault credential library subtype %q", globals.ResourceInfoFromPrefix(id).Subtype) } return out, nil } @@ -586,10 +649,14 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, } rows := 0 switch globals.ResourceInfoFromPrefix(id).Subtype { + case vault.GenericLibrarySubtype: + rows, err = repo.DeleteCredentialLibrary(ctx, scopeId, id) case vault.SSHCertificateLibrarySubtype: rows, err = repo.DeleteSSHCertificateCredentialLibrary(ctx, scopeId, id) + case vault.LdapCredentialLibrarySubtype: + rows, err = repo.DeleteLdapCredentialLibrary(ctx, scopeId, id) default: - rows, err = repo.DeleteCredentialLibrary(ctx, scopeId, id) + return false, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, "Unknown vault credential library subtype %q", globals.ResourceInfoFromPrefix(id).Subtype) } if err != nil { if errors.IsNotFoundError(err) { @@ -640,6 +707,17 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type, isRec return res } parentId = cl.GetStoreId() + case vault.LdapCredentialLibrarySubtype: + cl, err := repo.LookupLdapCredentialLibrary(ctx, id) + if err != nil { + res.Error = err + return res + } + if cl == nil { + res.Error = handlers.NotFoundError() + return res + } + parentId = cl.GetStoreId() default: res.Error = errors.New(ctx, errors.InvalidParameter, op, "unrecognized credential library subtype from id") return res @@ -854,7 +932,21 @@ func toProto(ctx context.Context, in credential.Library, opt ...handlers.Option) VaultSshCertificateCredentialLibraryAttributes: attrs, } } - + case vault.LdapCredentialLibrarySubtype: + vaultIn, ok := in.(*vault.LdapCredentialLibrary) + if !ok { + return nil, errors.New(ctx, errors.Internal, op, "unable to cast to vault ldap credential library") + } + if outputFields.Has(globals.CredentialTypeField) { + out.CredentialType = vaultIn.GetCredentialType() + } + if outputFields.Has(globals.AttributesField) { + out.Attrs = &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String(vaultIn.GetVaultPath()), + }, + } + } } return &out, nil } @@ -992,20 +1084,33 @@ func toStorageVaultSSHCertificateLibrary(ctx context.Context, storeId string, in return cs, err } +func toStorageVaultLdapLibrary(ctx context.Context, storeId string, in *pb.CredentialLibrary) (*vault.LdapCredentialLibrary, error) { + const op = "credentiallibraries.toStorageVaultLdapLibrary" + + var opts []vault.Option + if in.GetName() != nil { + opts = append(opts, vault.WithName(in.GetName().GetValue())) + } + if in.GetDescription() != nil { + opts = append(opts, vault.WithDescription(in.GetDescription().GetValue())) + } + + attrs := in.GetVaultLdapCredentialLibraryAttributes() + cs, err := vault.NewLdapCredentialLibrary(storeId, attrs.GetPath().GetValue(), opts...) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to build credential library")) + } + + return cs, nil +} + // A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce // requirements on the structure of the request. They verify that: // - The path passed in is correctly formatted // - All required parameters are set // - There are no conflicting parameters provided func validateGetRequest(req *pbs.GetCredentialLibraryRequest) error { - prefix := "" - switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { - case vault.SSHCertificateLibrarySubtype: - prefix = globals.VaultSshCertificateCredentialLibraryPrefix - default: - prefix = globals.VaultCredentialLibraryPrefix - } - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, prefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, globals.VaultLdapCredentialLibraryPrefix) } func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { @@ -1048,8 +1153,9 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { } if t != vault.GenericLibrarySubtype.String() && - t != vault.SSHCertificateLibrarySubtype.String() { - badFields[globals.CredentialStoreIdField] = fmt.Sprintf("Type must be a vault subtype %q or %q", vault.GenericLibrarySubtype.String(), vault.SSHCertificateLibrarySubtype.String()) + t != vault.SSHCertificateLibrarySubtype.String() && + t != vault.LdapCredentialLibrarySubtype.String() { + badFields[globals.CredentialStoreIdField] = fmt.Sprintf("Type must be a vault subtype %q, %q or %q", vault.GenericLibrarySubtype.String(), vault.SSHCertificateLibrarySubtype.String(), vault.LdapCredentialLibrarySubtype.String()) } switch req.GetItem().GetType() { @@ -1111,6 +1217,17 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { badFields[keyTypeField] = "If set, value must be 'ed25519', 'ecdsa', or 'rsa'." } validateKeyBits(badFields, attrs.GetKeyBits().GetValue(), attrs.GetKeyType().GetValue()) + case vault.LdapCredentialLibrarySubtype.String(): + if req.GetItem().GetCredentialType() != "" { + badFields[globals.CredentialTypeField] = "This field is read only and cannot be set." + } + attrs := req.GetItem().GetVaultLdapCredentialLibraryAttributes() + if attrs == nil { + badFields[attributesPathField] = "This is a required field." + } + if attrs.GetPath().GetValue() == "" { + badFields[vaultPathField] = "This is a required field." + } } default: badFields[globals.CredentialStoreIdField] = "This field must be a valid credential store id." @@ -1120,17 +1237,9 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { } func validateUpdateRequest(req *pbs.UpdateCredentialLibraryRequest, currentCredentialType globals.CredentialType) error { - prefix := "" - st := globals.ResourceInfoFromPrefix(req.GetId()).Subtype - switch st { - case vault.GenericLibrarySubtype: - prefix = globals.VaultCredentialLibraryPrefix - case vault.SSHCertificateLibrarySubtype: - prefix = globals.VaultSshCertificateCredentialLibraryPrefix - } return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch st { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case vault.GenericLibrarySubtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != vault.GenericLibrarySubtype.String() { badFields[globals.TypeField] = "Cannot modify resource type." @@ -1175,13 +1284,27 @@ func validateUpdateRequest(req *pbs.UpdateCredentialLibraryRequest, currentCrede } validateKeyBits(badFields, attrs.GetKeyBits().GetValue(), attrs.GetKeyType().GetValue()) } + case vault.LdapCredentialLibrarySubtype: + if req.GetItem().GetType() != "" && req.GetItem().GetType() != vault.LdapCredentialLibrarySubtype.String() { + badFields[globals.TypeField] = "Cannot modify resource type." + } + if req.GetItem().GetCredentialType() != "" && req.GetItem().GetCredentialType() != string(currentCredentialType) { + badFields[globals.CredentialTypeField] = "Cannot modify credential type." + } + + attrs := req.GetItem().GetVaultLdapCredentialLibraryAttributes() + if attrs != nil { + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), vaultPathField) && attrs.GetPath().GetValue() == "" { + badFields[vaultPathField] = "This is a required field and cannot be set to empty." + } + } } return badFields - }, prefix) + }, globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, globals.VaultLdapCredentialLibraryPrefix) } func validateDeleteRequest(req *pbs.DeleteCredentialLibraryRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, globals.VaultLdapCredentialLibraryPrefix) } func validateListRequest(ctx context.Context, req *pbs.ListCredentialLibrariesRequest) error { diff --git a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go index 295235acd..e4b59200d 100644 --- a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go +++ b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go @@ -14,6 +14,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/auth/password" "github.com/hashicorp/boundary/internal/authtoken" @@ -86,6 +87,25 @@ func sshCredentialLibraryToProto(credLib *vault.SSHCertificateCredentialLibrary, } } +func ldapCredentialLibraryToProto(credLib *vault.LdapCredentialLibrary, project *iam.Scope) *pb.CredentialLibrary { + return &pb.CredentialLibrary{ + Id: credLib.GetPublicId(), + CredentialStoreId: credLib.GetStoreId(), + CredentialType: credLib.GetCredentialType(), + Scope: &scopepb.ScopeInfo{Id: project.GetPublicId(), Type: scope.Project.String(), ParentScopeId: project.GetParentId()}, + CreatedTime: credLib.GetCreateTime().GetTimestamp(), + UpdatedTime: credLib.GetUpdateTime().GetTimestamp(), + Version: credLib.GetVersion(), + Type: vault.LdapCredentialLibrarySubtype.String(), + AuthorizedActions: testAuthorizedActions, + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String(credLib.GetVaultPath()), + }, + }, + } +} + func TestList(t *testing.T) { ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") @@ -114,6 +134,9 @@ func TestList(t *testing.T) { for _, l := range vault.TestSSHCertificateCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 10) { wantLibraries = append(wantLibraries, sshCredentialLibraryToProto(l, prj)) } + for _, l := range vault.TestLdapCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 10) { + wantLibraries = append(wantLibraries, ldapCredentialLibraryToProto(l, prj)) + } cases := []struct { name string @@ -131,7 +154,7 @@ func TestList(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 20, + EstItemCount: 30, }, anonRes: &pbs.ListCredentialLibrariesResponse{ Items: wantLibraries, @@ -139,7 +162,7 @@ func TestList(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 20, + EstItemCount: 30, }, }, { @@ -264,16 +287,20 @@ func TestList_Attributes(t *testing.T) { _, prj := iam.TestScopes(t, iamRepo) - ts := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 2) - storeGeneric, storeSSHCertificate := ts[0], ts[1] + ts := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 3) + storeGeneric, storeSSHCertificate, storeLdap := ts[0], ts[1], ts[2] var wantLibrariesGeneric []*pb.CredentialLibrary var wantLibrariesSSHCertificate []*pb.CredentialLibrary + var wantLibrariesLdap []*pb.CredentialLibrary for _, l := range vault.TestCredentialLibraries(t, conn, wrapper, storeGeneric.GetPublicId(), globals.UnspecifiedCredentialType, 5) { wantLibrariesGeneric = append(wantLibrariesGeneric, vaultCredentialLibraryToProto(l, prj)) } for _, l := range vault.TestSSHCertificateCredentialLibraries(t, conn, wrapper, storeSSHCertificate.GetPublicId(), 10) { wantLibrariesSSHCertificate = append(wantLibrariesSSHCertificate, sshCredentialLibraryToProto(l, prj)) } + for _, l := range vault.TestLdapCredentialLibraries(t, conn, wrapper, storeLdap.GetPublicId(), 10) { + wantLibrariesLdap = append(wantLibrariesLdap, ldapCredentialLibraryToProto(l, prj)) + } cases := []struct { name string @@ -318,6 +345,24 @@ func TestList_Attributes(t *testing.T) { RemovedIds: nil, }, // anonymous user does not have access to attributes }, + { + name: "Filter on Attribute Ldap Library", + req: &pbs.ListCredentialLibrariesRequest{CredentialStoreId: storeLdap.GetPublicId(), Filter: fmt.Sprintf(`"/item/attributes/path"==%q`, wantLibrariesLdap[2].GetVaultLdapCredentialLibraryAttributes().GetPath().Value)}, + res: &pbs.ListCredentialLibrariesResponse{ + Items: wantLibrariesLdap[2:3], + ResponseType: "complete", + SortBy: "created_time", + SortDir: "desc", + RemovedIds: nil, + EstItemCount: 1, + }, + anonRes: &pbs.ListCredentialLibrariesResponse{ + ResponseType: "complete", + SortBy: "created_time", + SortDir: "desc", + RemovedIds: nil, + }, // anonymous user does not have access to attributes + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -586,6 +631,51 @@ func TestCreate(t *testing.T) { res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, + { + name: "No Vault LDAP path", + req: &pbs.CreateCredentialLibraryRequest{ + Item: &pb.CredentialLibrary{ + CredentialStoreId: store.GetPublicId(), + Type: vault.LdapCredentialLibrarySubtype.String(), + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String(""), + }, + }, + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, + { + name: "Invalid Vault LDAP credential type", + req: &pbs.CreateCredentialLibraryRequest{ + Item: &pb.CredentialLibrary{ + CredentialStoreId: store.GetPublicId(), + Type: vault.LdapCredentialLibrarySubtype.String(), + CredentialType: string(globals.SshPrivateKeyCredentialType), + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("ldap/invalid/path"), + }, + }, + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, + { + name: "Invalid credential library type", + req: &pbs.CreateCredentialLibraryRequest{ + Item: &pb.CredentialLibrary{ + CredentialStoreId: store.GetPublicId(), + Type: "bla-invalid", + CredentialType: "bla-invalid", + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, { name: "Using POST method", req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{ @@ -1103,6 +1193,40 @@ func TestCreate(t *testing.T) { }, }, }, + { + name: "Create a valid Vault LDAP Credential library", + req: &pbs.CreateCredentialLibraryRequest{ + Item: &pb.CredentialLibrary{ + CredentialStoreId: store.GetPublicId(), + Type: vault.LdapCredentialLibrarySubtype.String(), + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("ldap/creds/hi"), + }, + }, + }, + }, + idPrefix: globals.VaultLdapCredentialLibraryPrefix + "_", + res: &pbs.CreateCredentialLibraryResponse{ + Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultLdapCredentialLibraryPrefix), + Item: &pb.CredentialLibrary{ + Id: store.GetPublicId(), + CredentialStoreId: store.GetPublicId(), + CreatedTime: store.GetCreateTime().GetTimestamp(), + UpdatedTime: store.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()}, + Version: 1, + Type: vault.LdapCredentialLibrarySubtype.String(), + CredentialType: string(globals.UsernamePasswordDomainCredentialType), + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("ldap/creds/hi"), + }, + }, + AuthorizedActions: testAuthorizedActions, + }, + }, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -1217,6 +1341,13 @@ func TestGet(t *testing.T) { sshCertLib, err := repo.CreateSSHCertificateCredentialLibrary(context.Background(), prj.GetPublicId(), lib2) require.NoError(t, err) + libLdap1, err := vault.NewLdapCredentialLibrary(store.GetPublicId(), "ldap/creds/test") + require.NoError(t, err) + require.NotNil(t, libLdap1) + libLdap1, err = repo.CreateLdapCredentialLibrary(t.Context(), prj.GetPublicId(), libLdap1) + require.NoError(t, err) + require.NotNil(t, libLdap1) + cases := []struct { name string id string @@ -1367,6 +1498,28 @@ func TestGet(t *testing.T) { }, }, }, + { + name: "success-ldap", + id: libLdap1.GetPublicId(), + res: &pbs.GetCredentialLibraryResponse{ + Item: &pb.CredentialLibrary{ + Id: libLdap1.GetPublicId(), + CredentialStoreId: libLdap1.GetStoreId(), + CredentialType: libLdap1.GetCredentialType(), + Scope: &scopepb.ScopeInfo{Id: store.GetProjectId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()}, + Type: vault.LdapCredentialLibrarySubtype.String(), + AuthorizedActions: testAuthorizedActions, + CreatedTime: libLdap1.CreateTime.GetTimestamp(), + UpdatedTime: libLdap1.UpdateTime.GetTimestamp(), + Version: 1, + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String(libLdap1.GetVaultPath()), + }, + }, + }, + }, + }, { name: "not found error", id: fmt.Sprintf("%s_1234567890", globals.VaultCredentialLibraryPrefix), @@ -1429,6 +1582,7 @@ func TestDelete(t *testing.T) { store := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1)[0] vl := vault.TestCredentialLibraries(t, conn, wrapper, store.GetPublicId(), globals.UnspecifiedCredentialType, 1)[0] vl2 := vault.TestSSHCertificateCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 1)[0] + vl3 := vault.TestLdapCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 1)[0] s, err := NewService(ctx, iamRepoFn, repoFn, 1000) require.NoError(t, err) cases := []struct { @@ -1445,6 +1599,10 @@ func TestDelete(t *testing.T) { name: "success-ssh-cert", id: vl2.GetPublicId(), }, + { + name: "success-ldap", + id: vl3.GetPublicId(), + }, { name: "not found error", id: fmt.Sprintf("%s_1234567890", globals.VaultCredentialLibraryPrefix), @@ -3244,6 +3402,287 @@ func TestUpdate_SSHCertificateCredentialLibrary(t *testing.T) { } } +func TestUpdate_LdapCredentialLibrary(t *testing.T) { + testCtx := context.Background() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + sche := scheduler.TestScheduler(t, conn, wrapper) + rw := db.New(conn) + + iamRepo := iam.TestRepo(t, conn, wrapper) + iamRepoFn := func() (*iam.Repository, error) { + return iamRepo, nil + } + repoFn := func() (*vault.Repository, error) { + return vault.NewRepository(testCtx, rw, rw, kms, sche) + } + + _, prj := iam.TestScopes(t, iamRepo) + ctx := auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()) + + s, err := NewService(testCtx, iamRepoFn, repoFn, 1000) + require.NoError(t, err) + cs := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1) + store := cs[0] + + freshLibrary := func(opt ...vault.Option) (*vault.LdapCredentialLibrary, func()) { + repo, err := repoFn() + require.NoError(t, err) + lib, err := vault.NewLdapCredentialLibrary(store.GetPublicId(), "ldap/creds/foo", opt...) + require.NoError(t, err) + + vl, err := repo.CreateLdapCredentialLibrary(ctx, prj.GetPublicId(), lib) + require.NoError(t, err) + clean := func() { + _, err := s.DeleteCredentialLibrary(ctx, &pbs.DeleteCredentialLibraryRequest{Id: vl.GetPublicId()}) + require.NoError(t, err) + } + return vl, clean + } + + tests := []struct { + name string + req *pbs.UpdateCredentialLibraryRequest + res func(*pb.CredentialLibrary) *pb.CredentialLibrary + wantErr bool + wantErrStatus int + wantErrStr string + }{ + { + name: "updateNonExistentField", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"doesntExist"}}, + Item: &pb.CredentialLibrary{ + Name: wrapperspb.String("updateNonExistentField_test"), + }, + }, + wantErr: true, + wantErrStatus: runtime.HTTPStatusFromCode(codes.InvalidArgument), + wantErrStr: "No valid fields included in the update mask.", + }, + { + name: "updateImmutableField", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"storeId"}}, + Item: &pb.CredentialLibrary{ + CredentialStoreId: "immutable", + }, + }, + wantErr: true, + wantErrStatus: runtime.HTTPStatusFromCode(codes.InvalidArgument), + wantErrStr: "No valid fields included in the update mask.", + }, + { + name: "updateValidFieldWithInvalidData", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"attributes.path"}}, + Item: &pb.CredentialLibrary{ + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("invalid_path"), + }, + }, + }, + }, + wantErr: true, + wantErrStr: "vault_path_must_have_staticcred_or_creds constraint failed", + }, + { + name: "updateImmutableCredentialTypeField", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"credentialType"}}, + Item: &pb.CredentialLibrary{ + CredentialType: string(globals.SshPrivateKeyCredentialType), + }, + }, + wantErr: true, + wantErrStatus: runtime.HTTPStatusFromCode(codes.InvalidArgument), + wantErrStr: "Cannot modify credential type.", + }, + { + name: "updateImmutableTypeField", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"type"}}, + Item: &pb.CredentialLibrary{ + Type: string(globals.SshCertificateCredentialType), + }, + }, + wantErr: true, + wantErrStatus: runtime.HTTPStatusFromCode(codes.InvalidArgument), + wantErrStr: "Cannot modify resource type.", + }, + { + name: "unsetVaultPath", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"attributes.path"}}, + Item: &pb.CredentialLibrary{ + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String(""), + }, + }, + }, + }, + wantErr: true, + wantErrStatus: runtime.HTTPStatusFromCode(codes.InvalidArgument), + wantErrStr: "attributes.path\", desc: \"This is a required field and cannot be set to empty.", + }, + { + name: "updateName", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name"}}, + Item: &pb.CredentialLibrary{ + Name: wrapperspb.String("updated_name"), + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.Name = wrapperspb.String("updated_name") + return cl + }, + }, + { + name: "updateDescription", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"description"}}, + Item: &pb.CredentialLibrary{ + Description: wrapperspb.String("updated_description"), + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.Description = wrapperspb.String("updated_description") + return cl + }, + }, + { + name: "updateValidVaultPath", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"attributes.path"}}, + Item: &pb.CredentialLibrary{ + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("ldap/static-cred/updated/path"), + }, + }, + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.GetVaultLdapCredentialLibraryAttributes().Path = wrapperspb.String("ldap/static-cred/updated/path") + return cl + }, + }, + { + name: "updateMultipleOneNonExistent", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "doesntExist"}}, + Item: &pb.CredentialLibrary{ + Name: wrapperspb.String("updated_name"), + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.Name = wrapperspb.String("updated_name") + return cl + }, + }, + { + name: "updateMultipleOneImmutable", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime. + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "credentialStoreId"}}, + Item: &pb.CredentialLibrary{ + Name: wrapperspb.String("updated_name"), + CredentialStoreId: "immutable", + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.Name = wrapperspb.String("updated_name") + return cl + }, + }, + { + name: "updateMultiple", + req: &pbs.UpdateCredentialLibraryRequest{ + Id: "", // Set at test runtime + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "attributes.path"}}, + Item: &pb.CredentialLibrary{ + Name: wrapperspb.String("updated_name"), + Attrs: &pb.CredentialLibrary_VaultLdapCredentialLibraryAttributes{ + VaultLdapCredentialLibraryAttributes: &pb.VaultLdapCredentialLibraryAttributes{ + Path: wrapperspb.String("ldap/creds/updated/path"), + }, + }, + }, + }, + res: func(cl *pb.CredentialLibrary) *pb.CredentialLibrary { + cl.Name = wrapperspb.String("updated_name") + cl.GetVaultLdapCredentialLibraryAttributes().Path = wrapperspb.String("ldap/creds/updated/path") + return cl + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + st, cleanup := freshLibrary() + defer cleanup() + + if tc.req.Item.GetVersion() == 0 { + tc.req.Item.Version = 1 + } + if tc.req.GetId() == "" { + tc.req.Id = st.GetPublicId() + } + resToChange, err := s.GetCredentialLibrary(ctx, &pbs.GetCredentialLibraryRequest{Id: st.GetPublicId()}) + require.NoError(err) + + got, gErr := s.UpdateCredentialLibrary(ctx, tc.req) + if tc.wantErr { + require.ErrorContains(gErr, tc.wantErrStr) + + gApiErr, ok := gErr.(*handlers.ApiError) + if ok { + // We don't always return status. + require.NotNil(gApiErr) + require.EqualValues(tc.wantErrStatus, gApiErr.Status) + } + require.Nil(got) + return + } + require.NoError(gErr) + require.NotNil(got) + + want := &pbs.UpdateCredentialLibraryResponse{Item: tc.res(resToChange.GetItem())} + gotUpdateTime := got.GetItem().GetUpdatedTime() + created := st.GetCreateTime().GetTimestamp() + assert.True(gotUpdateTime.AsTime().After(created.AsTime()), "Should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created) + + want.Item.UpdatedTime = got.Item.UpdatedTime + + assert.EqualValues(2, got.Item.Version) + want.Item.Version = 2 + + assert.Empty(cmp.Diff( + got, + want, + protocmp.Transform(), + cmpopts.SortSlices(func(a, b string) bool { + return a < b + }), + )) + }) + } +} + func TestListPagination(t *testing.T) { // Set database read timeout to avoid duplicates in response oldReadTimeout := globals.RefreshReadLookbackDuration @@ -3292,6 +3731,9 @@ func TestListPagination(t *testing.T) { for _, l := range vault.TestSSHCertificateCredentialLibraries(t, conn, wrapper, credStore.GetPublicId(), 5) { allCredentialLibraries = append(allCredentialLibraries, sshCredentialLibraryToProto(l, prj)) } + for _, l := range vault.TestLdapCredentialLibraries(t, conn, wrapper, credStore.GetPublicId(), 5) { + allCredentialLibraries = append(allCredentialLibraries, ldapCredentialLibraryToProto(l, prj)) + } // Reverse as we return items sorted by create_time desceding (newest first) slices.Reverse(allCredentialLibraries) @@ -3345,7 +3787,7 @@ func TestListPagination(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3370,7 +3812,7 @@ func TestListPagination(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3382,10 +3824,10 @@ func TestListPagination(t *testing.T) { // Request rest of results req.ListToken = got.ListToken - req.PageSize = 10 + req.PageSize = 15 got, err = s.ListCredentialLibraries(ctx, req) require.NoError(err) - require.Len(got.GetItems(), 6) + require.Len(got.GetItems(), 11) // Compare without comparing the list token assert.Empty( cmp.Diff( @@ -3396,7 +3838,7 @@ func TestListPagination(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3421,14 +3863,14 @@ func TestListPagination(t *testing.T) { // Update one of the other stores allCredentialLibraries[1].Name = wrapperspb.String("new-name") allCredentialLibraries[1].Version = 2 - updatedLibrary := &vault.SSHCertificateCredentialLibrary{ - SSHCertificateCredentialLibrary: &store.SSHCertificateCredentialLibrary{ + updatedLibrary := &vault.LdapCredentialLibrary{ + LdapCredentialLibrary: &store.LdapCredentialLibrary{ PublicId: allCredentialLibraries[1].GetId(), StoreId: allCredentialLibraries[1].GetCredentialStoreId(), Name: allCredentialLibraries[1].Name.Value, }, } - cred, _, err := vaultRepo.UpdateSSHCertificateCredentialLibrary(ctx, prj.PublicId, updatedLibrary, 1, []string{"name"}) + cred, _, err := vaultRepo.UpdateLdapCredentialLibrary(ctx, prj.PublicId, updatedLibrary, 1, []string{"name"}) require.NoError(err) allCredentialLibraries[1].UpdatedTime = cred.UpdateTime.GetTimestamp() allCredentialLibraries[1].Version = cred.Version @@ -3462,7 +3904,7 @@ func TestListPagination(t *testing.T) { SortDir: "desc", // Should contain the deleted library RemovedIds: []string{deletedCredLib.Id}, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3487,7 +3929,7 @@ func TestListPagination(t *testing.T) { SortBy: "updated_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3515,7 +3957,7 @@ func TestListPagination(t *testing.T) { SortDir: "desc", // Should be empty again RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b @@ -3538,7 +3980,7 @@ func TestListPagination(t *testing.T) { SortBy: "created_time", SortDir: "desc", RemovedIds: nil, - EstItemCount: 10, + EstItemCount: 15, }, cmpopts.SortSlices(func(a, b string) bool { return a < b diff --git a/internal/daemon/controller/handlers/targets/target_service.go b/internal/daemon/controller/handlers/targets/target_service.go index f7ae11100..8554c494c 100644 --- a/internal/daemon/controller/handlers/targets/target_service.go +++ b/internal/daemon/controller/handlers/targets/target_service.go @@ -2056,6 +2056,7 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ for _, cl := range req.GetBrokeredCredentialSourceIds() { if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, @@ -2069,6 +2070,7 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, @@ -2094,6 +2096,7 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ for _, cl := range req.GetBrokeredCredentialSourceIds() { if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, @@ -2107,6 +2110,7 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, @@ -2136,6 +2140,7 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc for _, cl := range req.GetBrokeredCredentialSourceIds() { if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, @@ -2149,6 +2154,7 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc if !handlers.ValidId(handlers.Id(cl), globals.VaultCredentialLibraryPrefix, globals.VaultSshCertificateCredentialLibraryPrefix, + globals.VaultLdapCredentialLibraryPrefix, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix, globals.UsernamePasswordDomainCredentialPrefix, diff --git a/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto b/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto index 565723d3b..e75ec5bcb 100644 --- a/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto +++ b/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto @@ -77,6 +77,11 @@ message CredentialLibrary { (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.subtype) = "vault-generic" ]; + VaultLdapCredentialLibraryAttributes vault_ldap_credential_library_attributes = 104 [ + (google.api.field_visibility).restriction = "INTERNAL", + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.subtype) = "vault-ldap" + ]; } // Output only. The available actions on this resource for this user. @@ -210,3 +215,15 @@ message VaultSSHCertificateCredentialLibraryAttributes { } ]; // @gotags: `class:"public"` } + +// The attributes of a vault LDAP Credential Library. +message VaultLdapCredentialLibraryAttributes { + // The path in Vault to request credentials from. + google.protobuf.StringValue path = 10 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.mask_mapping) = { + this: "attributes.path" + that: "VaultPath" + } + ]; // @gotags: `class:"public"` +} diff --git a/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go b/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go index aa2402579..ba98a316b 100644 --- a/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go +++ b/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go @@ -58,6 +58,7 @@ type CredentialLibrary struct { // *CredentialLibrary_VaultCredentialLibraryAttributes // *CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes // *CredentialLibrary_VaultGenericCredentialLibraryAttributes + // *CredentialLibrary_VaultLdapCredentialLibraryAttributes Attrs isCredentialLibrary_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"` @@ -205,6 +206,15 @@ func (x *CredentialLibrary) GetVaultGenericCredentialLibraryAttributes() *VaultC return nil } +func (x *CredentialLibrary) GetVaultLdapCredentialLibraryAttributes() *VaultLdapCredentialLibraryAttributes { + if x != nil { + if x, ok := x.Attrs.(*CredentialLibrary_VaultLdapCredentialLibraryAttributes); ok { + return x.VaultLdapCredentialLibraryAttributes + } + } + return nil +} + func (x *CredentialLibrary) GetAuthorizedActions() []string { if x != nil { return x.AuthorizedActions @@ -247,6 +257,10 @@ type CredentialLibrary_VaultGenericCredentialLibraryAttributes struct { VaultGenericCredentialLibraryAttributes *VaultCredentialLibraryAttributes `protobuf:"bytes,103,opt,name=vault_generic_credential_library_attributes,json=vaultGenericCredentialLibraryAttributes,proto3,oneof"` } +type CredentialLibrary_VaultLdapCredentialLibraryAttributes struct { + VaultLdapCredentialLibraryAttributes *VaultLdapCredentialLibraryAttributes `protobuf:"bytes,104,opt,name=vault_ldap_credential_library_attributes,json=vaultLdapCredentialLibraryAttributes,proto3,oneof"` +} + func (*CredentialLibrary_Attributes) isCredentialLibrary_Attrs() {} func (*CredentialLibrary_VaultCredentialLibraryAttributes) isCredentialLibrary_Attrs() {} @@ -256,6 +270,8 @@ func (*CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes) isCrede func (*CredentialLibrary_VaultGenericCredentialLibraryAttributes) isCredentialLibrary_Attrs() {} +func (*CredentialLibrary_VaultLdapCredentialLibraryAttributes) isCredentialLibrary_Attrs() {} + // The attributes of a vault typed Credential Library. type VaultCredentialLibraryAttributes struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -438,11 +454,57 @@ func (x *VaultSSHCertificateCredentialLibraryAttributes) GetAdditionalValidPrinc return nil } +// The attributes of a vault LDAP Credential Library. +type VaultLdapCredentialLibraryAttributes struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The path in Vault to request credentials from. + Path *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=path,proto3" json:"path,omitempty" class:"public"` // @gotags: `class:"public"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VaultLdapCredentialLibraryAttributes) Reset() { + *x = VaultLdapCredentialLibraryAttributes{} + mi := &file_controller_api_resources_credentiallibraries_v1_credential_library_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VaultLdapCredentialLibraryAttributes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VaultLdapCredentialLibraryAttributes) ProtoMessage() {} + +func (x *VaultLdapCredentialLibraryAttributes) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_resources_credentiallibraries_v1_credential_library_proto_msgTypes[3] + 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 VaultLdapCredentialLibraryAttributes.ProtoReflect.Descriptor instead. +func (*VaultLdapCredentialLibraryAttributes) Descriptor() ([]byte, []int) { + return file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDescGZIP(), []int{3} +} + +func (x *VaultLdapCredentialLibraryAttributes) GetPath() *wrapperspb.StringValue { + if x != nil { + return x.Path + } + return nil +} + var File_controller_api_resources_credentiallibraries_v1_credential_library_proto protoreflect.FileDescriptor const file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDesc = "" + "\n" + - "Hcontroller/api/resources/credentiallibraries/v1/credential_library.proto\x12/controller.api.resources.credentiallibraries.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\"\xae\v\n" + + "Hcontroller/api/resources/credentiallibraries/v1/credential_library.proto\x12/controller.api.resources.credentiallibraries.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\"\x84\r\n" + "\x11CredentialLibrary\x12\x0e\n" + "\x02id\x18\n" + " \x01(\tR\x02id\x120\n" + @@ -464,7 +526,10 @@ const file_controller_api_resources_credentiallibraries_v1_credential_library_pr "3vault_ssh_certificate_credential_library_attributes\x18f \x01(\v2_.controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributesB-\xa0\xda)\x01\x9a\xe3)\x15vault-ssh-certificate\xfa\xd2\xe4\x93\x02\n" + "\x12\bINTERNALH\x00R.vaultSshCertificateCredentialLibraryAttributes\x12\xd8\x01\n" + "+vault_generic_credential_library_attributes\x18g \x01(\v2Q.controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributesB%\xa0\xda)\x01\x9a\xe3)\rvault-generic\xfa\xd2\xe4\x93\x02\n" + - "\x12\bINTERNALH\x00R'vaultGenericCredentialLibraryAttributes\x12/\n" + + "\x12\bINTERNALH\x00R'vaultGenericCredentialLibraryAttributes\x12\xd3\x01\n" + + "(vault_ldap_credential_library_attributes\x18h \x01(\v2U.controller.api.resources.credentiallibraries.v1.VaultLdapCredentialLibraryAttributesB\"\xa0\xda)\x01\x9a\xe3)\n" + + "vault-ldap\xfa\xd2\xe4\x93\x02\n" + + "\x12\bINTERNALH\x00R$vaultLdapCredentialLibraryAttributes\x12/\n" + "\x12authorized_actions\x18\xac\x02 \x03(\tR\x12authorized_actions\x12/\n" + "\x0fcredential_type\x18\xb6\x02 \x01(\tB\x04\xa0\xda)\x01R\x0fcredential_type\x12b\n" + "\x1ccredential_mapping_overrides\x18\xc0\x02 \x01(\v2\x17.google.protobuf.StructB\x04\xa0\xda)\x01R\x1ccredential_mapping_overridesB\a\n" + @@ -507,7 +572,11 @@ const file_controller_api_resources_credentiallibraries_v1_credential_library_pr "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a=\n" + "\x0fExtensionsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01BhZfgithub.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentiallibraries;credentiallibrariesb\x06proto3" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"~\n" + + "$VaultLdapCredentialLibraryAttributes\x12V\n" + + "\x04path\x18\n" + + " \x01(\v2\x1c.google.protobuf.StringValueB$\xa0\xda)\x01\xc2\xdd)\x1c\n" + + "\x0fattributes.path\x12\tVaultPathR\x04pathBhZfgithub.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentiallibraries;credentiallibrariesb\x06proto3" var ( file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDescOnce sync.Once @@ -521,47 +590,50 @@ func file_controller_api_resources_credentiallibraries_v1_credential_library_pro return file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDescData } -var file_controller_api_resources_credentiallibraries_v1_credential_library_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_controller_api_resources_credentiallibraries_v1_credential_library_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_controller_api_resources_credentiallibraries_v1_credential_library_proto_goTypes = []any{ (*CredentialLibrary)(nil), // 0: controller.api.resources.credentiallibraries.v1.CredentialLibrary (*VaultCredentialLibraryAttributes)(nil), // 1: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes (*VaultSSHCertificateCredentialLibraryAttributes)(nil), // 2: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes - nil, // 3: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.CriticalOptionsEntry - nil, // 4: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ExtensionsEntry - (*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 - (*wrapperspb.UInt32Value)(nil), // 9: google.protobuf.UInt32Value + (*VaultLdapCredentialLibraryAttributes)(nil), // 3: controller.api.resources.credentiallibraries.v1.VaultLdapCredentialLibraryAttributes + nil, // 4: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.CriticalOptionsEntry + nil, // 5: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ExtensionsEntry + (*scopes.ScopeInfo)(nil), // 6: controller.api.resources.scopes.v1.ScopeInfo + (*wrapperspb.StringValue)(nil), // 7: google.protobuf.StringValue + (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 9: google.protobuf.Struct + (*wrapperspb.UInt32Value)(nil), // 10: google.protobuf.UInt32Value } var file_controller_api_resources_credentiallibraries_v1_credential_library_proto_depIdxs = []int32{ - 5, // 0: controller.api.resources.credentiallibraries.v1.CredentialLibrary.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 6, // 1: controller.api.resources.credentiallibraries.v1.CredentialLibrary.name:type_name -> google.protobuf.StringValue - 6, // 2: controller.api.resources.credentiallibraries.v1.CredentialLibrary.description:type_name -> google.protobuf.StringValue - 7, // 3: controller.api.resources.credentiallibraries.v1.CredentialLibrary.created_time:type_name -> google.protobuf.Timestamp - 7, // 4: controller.api.resources.credentiallibraries.v1.CredentialLibrary.updated_time:type_name -> google.protobuf.Timestamp - 8, // 5: controller.api.resources.credentiallibraries.v1.CredentialLibrary.attributes:type_name -> google.protobuf.Struct + 6, // 0: controller.api.resources.credentiallibraries.v1.CredentialLibrary.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 7, // 1: controller.api.resources.credentiallibraries.v1.CredentialLibrary.name:type_name -> google.protobuf.StringValue + 7, // 2: controller.api.resources.credentiallibraries.v1.CredentialLibrary.description:type_name -> google.protobuf.StringValue + 8, // 3: controller.api.resources.credentiallibraries.v1.CredentialLibrary.created_time:type_name -> google.protobuf.Timestamp + 8, // 4: controller.api.resources.credentiallibraries.v1.CredentialLibrary.updated_time:type_name -> google.protobuf.Timestamp + 9, // 5: controller.api.resources.credentiallibraries.v1.CredentialLibrary.attributes:type_name -> google.protobuf.Struct 1, // 6: controller.api.resources.credentiallibraries.v1.CredentialLibrary.vault_credential_library_attributes:type_name -> controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes 2, // 7: controller.api.resources.credentiallibraries.v1.CredentialLibrary.vault_ssh_certificate_credential_library_attributes:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes 1, // 8: controller.api.resources.credentiallibraries.v1.CredentialLibrary.vault_generic_credential_library_attributes:type_name -> controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes - 8, // 9: controller.api.resources.credentiallibraries.v1.CredentialLibrary.credential_mapping_overrides:type_name -> google.protobuf.Struct - 6, // 10: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.path:type_name -> google.protobuf.StringValue - 6, // 11: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.http_method:type_name -> google.protobuf.StringValue - 6, // 12: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.http_request_body:type_name -> google.protobuf.StringValue - 6, // 13: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.path:type_name -> google.protobuf.StringValue - 6, // 14: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.username:type_name -> google.protobuf.StringValue - 6, // 15: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_type:type_name -> google.protobuf.StringValue - 9, // 16: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_bits:type_name -> google.protobuf.UInt32Value - 6, // 17: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ttl:type_name -> google.protobuf.StringValue - 6, // 18: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_id:type_name -> google.protobuf.StringValue - 3, // 19: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.critical_options:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.CriticalOptionsEntry - 4, // 20: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.extensions:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ExtensionsEntry - 6, // 21: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.additional_valid_principals:type_name -> google.protobuf.StringValue - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 3, // 9: controller.api.resources.credentiallibraries.v1.CredentialLibrary.vault_ldap_credential_library_attributes:type_name -> controller.api.resources.credentiallibraries.v1.VaultLdapCredentialLibraryAttributes + 9, // 10: controller.api.resources.credentiallibraries.v1.CredentialLibrary.credential_mapping_overrides:type_name -> google.protobuf.Struct + 7, // 11: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.path:type_name -> google.protobuf.StringValue + 7, // 12: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.http_method:type_name -> google.protobuf.StringValue + 7, // 13: controller.api.resources.credentiallibraries.v1.VaultCredentialLibraryAttributes.http_request_body:type_name -> google.protobuf.StringValue + 7, // 14: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.path:type_name -> google.protobuf.StringValue + 7, // 15: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.username:type_name -> google.protobuf.StringValue + 7, // 16: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_type:type_name -> google.protobuf.StringValue + 10, // 17: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_bits:type_name -> google.protobuf.UInt32Value + 7, // 18: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ttl:type_name -> google.protobuf.StringValue + 7, // 19: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_id:type_name -> google.protobuf.StringValue + 4, // 20: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.critical_options:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.CriticalOptionsEntry + 5, // 21: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.extensions:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ExtensionsEntry + 7, // 22: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.additional_valid_principals:type_name -> google.protobuf.StringValue + 7, // 23: controller.api.resources.credentiallibraries.v1.VaultLdapCredentialLibraryAttributes.path:type_name -> google.protobuf.StringValue + 24, // [24:24] is the sub-list for method output_type + 24, // [24:24] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_controller_api_resources_credentiallibraries_v1_credential_library_proto_init() } @@ -574,6 +646,7 @@ func file_controller_api_resources_credentiallibraries_v1_credential_library_pro (*CredentialLibrary_VaultCredentialLibraryAttributes)(nil), (*CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes)(nil), (*CredentialLibrary_VaultGenericCredentialLibraryAttributes)(nil), + (*CredentialLibrary_VaultLdapCredentialLibraryAttributes)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -581,7 +654,7 @@ func file_controller_api_resources_credentiallibraries_v1_credential_library_pro GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDesc), len(file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDesc)), NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, },