From 8c56a5648dbfcacd960f7c44e9f2dc530ff4c706 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 15 Jul 2022 13:09:55 -0400 Subject: [PATCH] Migrate plugin host/set/catalog prefixes to typed (#2256) * Migrate plugin host/set/catalog prefixes to typed * Add credential store typing too --- CHANGELOG.md | 11 ++++++- internal/credential/static/options.go | 8 +++++ internal/credential/static/public_ids.go | 16 +++++---- .../static/repository_credential.go | 2 +- .../static/repository_credential_test.go | 4 +-- internal/credential/static/testing.go | 28 +++++++++++----- .../usernamepassword_credential_test.go | 2 +- .../credentials/credential_service.go | 13 +++++--- .../credentials/credential_service_test.go | 33 ++++++++++++++++--- .../credentialstore_service.go | 6 ++-- .../credentialstore_service_test.go | 18 ++++++++++ .../host_catalogs/host_catalog_service.go | 6 ++-- .../host_catalog_service_test.go | 12 +++++++ .../handlers/host_sets/host_set_service.go | 10 +++--- .../host_sets/host_set_service_test.go | 18 ++++++++-- .../controller/handlers/hosts/host_service.go | 4 +-- .../handlers/hosts/host_service_test.go | 15 ++++++++- .../handlers/targets/target_service.go | 30 +++++++---------- internal/host/plugin/ids.go | 11 ++++--- .../tests/api/credentials/credentials_test.go | 2 +- 20 files changed, 178 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a342323..099e0117b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,16 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. -## Next +## 0.9.2 (Not Released) + +### Deprecations/Changes + +* Host plugins: Plugin-type host catalogs/sets/hosts now use typed prefixes for + any newly-created resources. Existing resources will not be affected. + ([PR](https://github.com/hashicorp/boundary/pull/2256)) +* Credential stores: Static-type credential stores/credentials now use typed + prefixes for any newly-created resources. Existing resources will not be + affected. ([PR](https://github.com/hashicorp/boundary/pull/2256)) ## 0.9.1 (2022/07/06) diff --git a/internal/credential/static/options.go b/internal/credential/static/options.go index 04c7a87e4..e325cca93 100644 --- a/internal/credential/static/options.go +++ b/internal/credential/static/options.go @@ -17,6 +17,7 @@ type options struct { withName string withDescription string withLimit int + withPublicId string } func getDefaultOptions() options { @@ -45,3 +46,10 @@ func WithLimit(l int) Option { o.withLimit = l } } + +// WithPublicId provides an optional public ID to use. +func WithPublicId(name string) Option { + return func(o *options) { + o.withPublicId = name + } +} diff --git a/internal/credential/static/public_ids.go b/internal/credential/static/public_ids.go index fb3730d2e..f7e1bc189 100644 --- a/internal/credential/static/public_ids.go +++ b/internal/credential/static/public_ids.go @@ -10,18 +10,20 @@ import ( ) func init() { - if err := subtypes.Register(credential.Domain, Subtype, CredentialStorePrefix); err != nil { + if err := subtypes.Register(credential.Domain, Subtype, CredentialStorePrefix, PreviousCredentialStorePrefix); err != nil { panic(err) } - if err := subtypes.Register(credential.Domain, UsernamePasswordSubtype, CredentialPrefix); err != nil { + if err := subtypes.Register(credential.Domain, UsernamePasswordSubtype, UsernamePasswordCredentialPrefix, PreviousUsernamePasswordCredentialPrefix); err != nil { panic(err) } } // PublicId prefixes for the resources in the static package. const ( - CredentialStorePrefix = "cs" - CredentialPrefix = "cred" + CredentialStorePrefix = "csst" + PreviousCredentialStorePrefix = "cs" + UsernamePasswordCredentialPrefix = "credup" + PreviousUsernamePasswordCredentialPrefix = "cred" Subtype = subtypes.Subtype("static") UsernamePasswordSubtype = subtypes.Subtype("username_password") @@ -35,10 +37,10 @@ func newCredentialStoreId(ctx context.Context) (string, error) { return id, nil } -func newCredentialId(ctx context.Context) (string, error) { - id, err := db.NewPublicId(CredentialPrefix) +func newUsernamePasswordCredentialId(ctx context.Context) (string, error) { + id, err := db.NewPublicId(UsernamePasswordCredentialPrefix) if err != nil { - return "", errors.Wrap(ctx, err, "static.newCredentialId") + return "", errors.Wrap(ctx, err, "static.newUsernamePasswordCredentialId") } return id, nil } diff --git a/internal/credential/static/repository_credential.go b/internal/credential/static/repository_credential.go index 3829397c2..2be656490 100644 --- a/internal/credential/static/repository_credential.go +++ b/internal/credential/static/repository_credential.go @@ -53,7 +53,7 @@ func (r *Repository) CreateUsernamePasswordCredential( } c = c.clone() - id, err := newCredentialId(ctx) + id, err := newUsernamePasswordCredentialId(ctx) if err != nil { return nil, errors.Wrap(ctx, err, op) } diff --git a/internal/credential/static/repository_credential_test.go b/internal/credential/static/repository_credential_test.go index fe1227a1b..b0c170bab 100644 --- a/internal/credential/static/repository_credential_test.go +++ b/internal/credential/static/repository_credential_test.go @@ -121,7 +121,7 @@ func TestRepository_CreateUsernamePasswordCredential(t *testing.T) { return } require.NoError(err) - assertPublicId(t, CredentialPrefix, got.PublicId) + assertPublicId(t, UsernamePasswordCredentialPrefix, got.PublicId) assert.Equal(tt.cred.Username, got.Username) assert.Nil(got.Password) assert.Nil(got.CtPassword) @@ -853,7 +853,7 @@ func TestRepository_UpdateUsernamePasswordCredential(t *testing.T) { assert.NoError(err) assert.Empty(tt.orig.PublicId) require.NotNil(got) - assertPublicId(t, CredentialPrefix, got.PublicId) + assertPublicId(t, UsernamePasswordCredentialPrefix, got.PublicId) assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.StoreId, got.StoreId) diff --git a/internal/credential/static/testing.go b/internal/credential/static/testing.go index 726bb8904..dd6e4add9 100644 --- a/internal/credential/static/testing.go +++ b/internal/credential/static/testing.go @@ -15,7 +15,7 @@ import ( // TestCredentialStore creates a static credential store in the provided DB with // the provided scope and any values passed in through the Options vars. // If any errors are encountered during the creation of the store, the test will fail. -func TestCredentialStore(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, scopeId string, opts ...Option) *CredentialStore { +func TestCredentialStore(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, scopeId string, opt ...Option) *CredentialStore { t.Helper() ctx := context.Background() kmsCache := kms.TestKms(t, conn, wrapper) @@ -25,12 +25,17 @@ func TestCredentialStore(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, sc assert.NoError(t, err) require.NotNil(t, databaseWrapper) - cs, err := NewCredentialStore(scopeId, opts...) + cs, err := NewCredentialStore(scopeId, opt...) assert.NoError(t, err) require.NotNil(t, cs) - id, err := newCredentialStoreId(ctx) - assert.NoError(t, err) - require.NotEmpty(t, id) + + opts := getOpts(opt...) + id := opts.withPublicId + if id == "" { + id, err = newCredentialStoreId(ctx) + assert.NoError(t, err) + require.NotEmpty(t, id) + } cs.PublicId = id _, err2 := w.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, @@ -72,23 +77,28 @@ func TestUsernamePasswordCredential( conn *db.DB, wrapper wrapping.Wrapper, username, password, storeId, scopeId string, - opts ...Option, + opt ...Option, ) *UsernamePasswordCredential { t.Helper() ctx := context.Background() kmsCache := kms.TestKms(t, conn, wrapper) w := db.New(conn) + opts := getOpts(opt...) + databaseWrapper, err := kmsCache.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase) assert.NoError(t, err) require.NotNil(t, databaseWrapper) - cred, err := NewUsernamePasswordCredential(storeId, username, credential.Password(password), opts...) + cred, err := NewUsernamePasswordCredential(storeId, username, credential.Password(password), opt...) require.NoError(t, err) require.NotNil(t, cred) - id, err := newCredentialId(ctx) - require.NoError(t, err) + id := opts.withPublicId + if id == "" { + id, err = newUsernamePasswordCredentialId(ctx) + require.NoError(t, err) + } cred.PublicId = id err = cred.encrypt(ctx, databaseWrapper) diff --git a/internal/credential/static/usernamepassword_credential_test.go b/internal/credential/static/usernamepassword_credential_test.go index c7596fde6..2285df99b 100644 --- a/internal/credential/static/usernamepassword_credential_test.go +++ b/internal/credential/static/usernamepassword_credential_test.go @@ -128,7 +128,7 @@ func TestCredential_New(t *testing.T) { require.NotNil(got) assert.Emptyf(got.PublicId, "PublicId set") - id, err := newCredentialId(ctx) + id, err := newUsernamePasswordCredentialId(ctx) require.NoError(err) tt.want.PublicId = id diff --git a/internal/daemon/controller/handlers/credentials/credential_service.go b/internal/daemon/controller/handlers/credentials/credential_service.go index 4874b12e7..58455928e 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service.go +++ b/internal/daemon/controller/handlers/credentials/credential_service.go @@ -360,6 +360,9 @@ func (s Service) updateInRepo( switch subtypes.SubtypeFromId(domain, id) { case static.UsernamePasswordSubtype: cred, err := toUsernamePasswordStorageCredential(storeId, in) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to convert to username/password storage credential")) + } cred.PublicId = id repo, err := s.repoFn() if err != nil { @@ -530,7 +533,7 @@ func toUsernamePasswordStorageCredential(storeId string, in *pb.Credential) (out // * All required parameters are set // * There are no conflicting parameters provided func validateGetRequest(req *pbs.GetCredentialRequest) error { - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.CredentialPrefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.UsernamePasswordCredentialPrefix, static.PreviousUsernamePasswordCredentialPrefix) } func validateCreateRequest(req *pbs.CreateCredentialRequest) error { @@ -539,7 +542,7 @@ func validateCreateRequest(req *pbs.CreateCredentialRequest) error { if req.Item.GetType() != static.UsernamePasswordSubtype.String() { badFields[globals.TypeField] = fmt.Sprintf("Unsupported credential type %q", req.Item.GetType()) } - if !handlers.ValidId(handlers.Id(req.Item.GetCredentialStoreId()), static.CredentialStorePrefix) { + if !handlers.ValidId(handlers.Id(req.Item.GetCredentialStoreId()), static.CredentialStorePrefix, static.PreviousCredentialStorePrefix) { badFields[globals.CredentialStoreIdField] = "This field must be a valid credential store id." } @@ -570,16 +573,16 @@ func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error { } return badFields - }, static.CredentialPrefix) + }, static.UsernamePasswordCredentialPrefix, static.PreviousUsernamePasswordCredentialPrefix) } func validateDeleteRequest(req *pbs.DeleteCredentialRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.CredentialPrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.UsernamePasswordCredentialPrefix, static.PreviousUsernamePasswordCredentialPrefix) } func validateListRequest(req *pbs.ListCredentialsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetCredentialStoreId()), static.CredentialStorePrefix) { + if !handlers.ValidId(handlers.Id(req.GetCredentialStoreId()), static.CredentialStorePrefix, static.PreviousCredentialStorePrefix) { badFields[globals.CredentialStoreIdField] = "This field must be a valid credential store id." } if _, err := handlers.NewFilter(req.GetFilter()); err != nil { diff --git a/internal/daemon/controller/handlers/credentials/credential_service_test.go b/internal/daemon/controller/handlers/credentials/credential_service_test.go index 5802575a8..7f14709f4 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service_test.go +++ b/internal/daemon/controller/handlers/credentials/credential_service_test.go @@ -172,6 +172,7 @@ func TestGet(t *testing.T) { store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId()) cred := static.TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId()) + credPrev := static.TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId(), static.WithPublicId(fmt.Sprintf("%s_1234567890", static.PreviousUsernamePasswordCredentialPrefix))) s, err := NewService(staticRepoFn, iamRepoFn) require.NoError(t, err) @@ -209,9 +210,31 @@ func TestGet(t *testing.T) { }, }, }, + { + name: "success-prev-prefix", + id: credPrev.GetPublicId(), + res: &pbs.GetCredentialResponse{ + Item: &pb.Credential{ + Id: credPrev.GetPublicId(), + CredentialStoreId: cred.GetStoreId(), + Scope: &scopepb.ScopeInfo{Id: store.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()}, + Type: static.UsernamePasswordSubtype.String(), + AuthorizedActions: testAuthorizedActions, + CreatedTime: credPrev.CreateTime.GetTimestamp(), + UpdatedTime: credPrev.UpdateTime.GetTimestamp(), + Version: 1, + Attrs: &pb.Credential_UsernamePasswordAttributes{ + UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{ + Username: wrapperspb.String("user"), + PasswordHmac: base64.RawURLEncoding.EncodeToString([]byte(hm)), + }, + }, + }, + }, + }, { name: "not found error", - id: fmt.Sprintf("%s_1234567890", static.CredentialPrefix), + id: fmt.Sprintf("%s_1234567890", static.UsernamePasswordCredentialPrefix), err: handlers.NotFoundError(), }, { @@ -279,7 +302,7 @@ func TestDelete(t *testing.T) { }, { name: "not found error", - id: fmt.Sprintf("%s_1234567890", static.CredentialPrefix), + id: fmt.Sprintf("%s_1234567890", static.UsernamePasswordCredentialPrefix), err: handlers.NotFoundError(), }, { @@ -334,7 +357,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Id", req: &pbs.CreateCredentialRequest{Item: &pb.Credential{ CredentialStoreId: store.GetPublicId(), - Id: static.CredentialPrefix + "_notallowed", + Id: static.UsernamePasswordCredentialPrefix + "_notallowed", Type: static.UsernamePasswordSubtype.String(), Attrs: &pb.Credential_UsernamePasswordAttributes{ UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{ @@ -446,9 +469,9 @@ func TestCreate(t *testing.T) { }, }, }}, - idPrefix: static.CredentialPrefix + "_", + idPrefix: static.UsernamePasswordCredentialPrefix + "_", res: &pbs.CreateCredentialResponse{ - Uri: fmt.Sprintf("credentials/%s_", static.CredentialPrefix), + Uri: fmt.Sprintf("credentials/%s_", static.UsernamePasswordCredentialPrefix), Item: &pb.Credential{ Id: store.GetPublicId(), CredentialStoreId: store.GetPublicId(), diff --git a/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go b/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go index c5769a004..2a687e433 100644 --- a/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go +++ b/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go @@ -759,7 +759,7 @@ func toStorageVaultStore(scopeId string, in *pb.CredentialStore) (out *vault.Cre // * All required parameters are set // * There are no conflicting parameters provided func validateGetRequest(req *pbs.GetCredentialStoreRequest) error { - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix, static.PreviousCredentialStorePrefix) } func validateCreateRequest(req *pbs.CreateCredentialStoreRequest) error { @@ -845,11 +845,11 @@ func validateUpdateRequest(req *pbs.UpdateCredentialStoreRequest) error { } } return badFields - }, vault.CredentialStorePrefix, static.CredentialStorePrefix) + }, vault.CredentialStorePrefix, static.CredentialStorePrefix, static.PreviousCredentialStorePrefix) } func validateDeleteRequest(req *pbs.DeleteCredentialStoreRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix, static.PreviousCredentialStorePrefix) } func validateListRequest(req *pbs.ListCredentialStoresRequest) error { diff --git a/internal/daemon/controller/handlers/credentialstores/credentialstore_service_test.go b/internal/daemon/controller/handlers/credentialstores/credentialstore_service_test.go index 3e5371c48..cda604e66 100644 --- a/internal/daemon/controller/handlers/credentialstores/credentialstore_service_test.go +++ b/internal/daemon/controller/handlers/credentialstores/credentialstore_service_test.go @@ -739,6 +739,7 @@ func TestGet(t *testing.T) { vaultStore := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1)[0] staticStore := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId()) + staticStorePrev := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId(), credstatic.WithPublicId(fmt.Sprintf("%s_1234567890", credstatic.PreviousCredentialStorePrefix))) s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn) require.NoError(t, err) @@ -790,6 +791,23 @@ func TestGet(t *testing.T) { }, }, }, + { + name: "static prev prefix success", + id: staticStorePrev.GetPublicId(), + res: &pbs.GetCredentialStoreResponse{ + Item: &pb.CredentialStore{ + Id: staticStorePrev.GetPublicId(), + ScopeId: staticStorePrev.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: staticStorePrev.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()}, + Type: credstatic.Subtype.String(), + AuthorizedActions: testAuthorizedActions, + AuthorizedCollectionActions: testAuthorizedStaticCollectionActions, + CreatedTime: staticStorePrev.CreateTime.GetTimestamp(), + UpdatedTime: staticStorePrev.UpdateTime.GetTimestamp(), + Version: 1, + }, + }, + }, { name: "vault not found error", id: fmt.Sprintf("%s_1234567890", vault.CredentialStorePrefix), diff --git a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go index b5cf2d1fa..8e83cb5cd 100644 --- a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go +++ b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go @@ -820,7 +820,7 @@ func toStoragePluginCatalog(ctx context.Context, scopeId, plgId string, item *pb // * The type asserted by the ID and/or field is known // * If relevant, the type derived from the id prefix matches what is claimed by the type field func validateGetRequest(req *pbs.GetHostCatalogRequest) error { - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.HostCatalogPrefix, plugin.HostCatalogPrefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) } func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error { @@ -876,11 +876,11 @@ func validateUpdateRequest(req *pbs.UpdateHostCatalogRequest) error { } } return badFields - }, static.HostCatalogPrefix, plugin.HostCatalogPrefix) + }, static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) } func validateDeleteRequest(req *pbs.DeleteHostCatalogRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.HostCatalogPrefix, plugin.HostCatalogPrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) } func validateListRequest(req *pbs.ListHostCatalogsRequest) error { diff --git a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go index 30a630a3b..5220f46e4 100644 --- a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go +++ b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go @@ -186,6 +186,7 @@ func TestGet_Plugin(t *testing.T) { name := "test" plg := host.TestPlugin(t, conn, name) hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId(), plugin.WithSecretsHmac([]byte("foobar"))) + hcPrev := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId(), plugin.WithSecretsHmac([]byte("foobar")), plugin.WithPublicId(fmt.Sprintf("%s_1234567890", plugin.PreviousHostCatalogPrefix))) toMerge := &pbs.GetHostCatalogRequest{ Id: hc.GetPublicId(), @@ -224,6 +225,17 @@ func TestGet_Plugin(t *testing.T) { req: &pbs.GetHostCatalogRequest{Id: hc.GetPublicId()}, res: &pbs.GetHostCatalogResponse{Item: pHostCatalog}, }, + { + name: "Get an Existing Previous-ID HostCatalog", + req: &pbs.GetHostCatalogRequest{Id: hcPrev.GetPublicId()}, + res: func() *pbs.GetHostCatalogResponse { + resp := proto.Clone(pHostCatalog).(*pb.HostCatalog) + resp.Id = hcPrev.PublicId + resp.CreatedTime = hcPrev.CreateTime.GetTimestamp() + resp.UpdatedTime = hcPrev.UpdateTime.GetTimestamp() + return &pbs.GetHostCatalogResponse{Item: resp} + }(), + }, { name: "Get a non existing Host Catalog", req: &pbs.GetHostCatalogRequest{Id: plugin.HostCatalogPrefix + "_DoesntExis"}, diff --git a/internal/daemon/controller/handlers/host_sets/host_set_service.go b/internal/daemon/controller/handlers/host_sets/host_set_service.go index fe3a655c0..ee5e42609 100644 --- a/internal/daemon/controller/handlers/host_sets/host_set_service.go +++ b/internal/daemon/controller/handlers/host_sets/host_set_service.go @@ -943,13 +943,13 @@ func toStoragePluginSet(ctx context.Context, catalogId string, item *pb.HostSet) // * The type asserted by the ID and/or field is known // * If relevant, the type derived from the id prefix matches what is claimed by the type field func validateGetRequest(req *pbs.GetHostSetRequest) error { - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.HostSetPrefix, plugin.HostSetPrefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) } func validateCreateRequest(ctx context.Context, req *pbs.CreateHostSetRequest) error { return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetItem().GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix) { + if !handlers.ValidId(handlers.Id(req.GetItem().GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) { badFields[globals.HostCatalogIdField] = "The field is incorrectly formatted." } if len(req.GetItem().GetPreferredEndpoints()) > 0 { @@ -1002,16 +1002,16 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateHostSetRequest) e } } return badFields - }, static.HostSetPrefix, plugin.HostSetPrefix) + }, static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) } func validateDeleteRequest(req *pbs.DeleteHostSetRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.HostSetPrefix, plugin.HostSetPrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) } func validateListRequest(req *pbs.ListHostSetsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix) { + if !handlers.ValidId(handlers.Id(req.GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) { badFields[globals.HostCatalogIdField] = "The field is incorrectly formatted." } if _, err := handlers.NewFilter(req.GetFilter()); err != nil { diff --git a/internal/daemon/controller/handlers/host_sets/host_set_service_test.go b/internal/daemon/controller/handlers/host_sets/host_set_service_test.go index bbb624be3..8d0fd65e0 100644 --- a/internal/daemon/controller/handlers/host_sets/host_set_service_test.go +++ b/internal/daemon/controller/handlers/host_sets/host_set_service_test.go @@ -170,10 +170,11 @@ func TestGet_Plugin(t *testing.T) { hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId()) hs := plugin.TestSet(t, conn, kms, sche, hc, plgm, plugin.WithPreferredEndpoints(prefEndpoints), plugin.WithSyncIntervalSeconds(-1)) + hsPrev := plugin.TestSet(t, conn, kms, sche, hc, plgm, plugin.WithPreferredEndpoints(prefEndpoints), plugin.WithSyncIntervalSeconds(-1), plugin.WithPublicId(fmt.Sprintf("%s_1234567890", plugin.PreviousHostSetPrefix))) toMerge := &pbs.GetHostSetRequest{} - pHost := &pb.HostSet{ + pHostSet := &pb.HostSet{ HostCatalogId: hc.GetPublicId(), Id: hs.GetPublicId(), CreatedTime: hs.CreateTime.GetTimestamp(), @@ -197,9 +198,20 @@ func TestGet_Plugin(t *testing.T) { err error }{ { - name: "Get an Existing Host", + name: "Get an Existing HostSet", req: &pbs.GetHostSetRequest{Id: hs.GetPublicId()}, - res: &pbs.GetHostSetResponse{Item: pHost}, + res: &pbs.GetHostSetResponse{Item: pHostSet}, + }, + { + name: "Get an Existing Previous-ID HostSet", + req: &pbs.GetHostSetRequest{Id: hsPrev.GetPublicId()}, + res: func() *pbs.GetHostSetResponse { + resp := proto.Clone(pHostSet).(*pb.HostSet) + resp.Id = hsPrev.PublicId + resp.CreatedTime = hsPrev.CreateTime.GetTimestamp() + resp.UpdatedTime = hsPrev.UpdateTime.GetTimestamp() + return &pbs.GetHostSetResponse{Item: resp} + }(), }, { name: "Get a non existing Host Set", diff --git a/internal/daemon/controller/handlers/hosts/host_service.go b/internal/daemon/controller/handlers/hosts/host_service.go index 24fd32e20..922b41a58 100644 --- a/internal/daemon/controller/handlers/hosts/host_service.go +++ b/internal/daemon/controller/handlers/hosts/host_service.go @@ -614,7 +614,7 @@ func validateGetRequest(req *pbs.GetHostRequest) error { badFields["id"] = "Improperly formatted identifier used." } return badFields - }, req, static.HostPrefix, plugin.HostPrefix) + }, req, static.HostPrefix, plugin.HostPrefix, plugin.PreviousHostPrefix) } func validateCreateRequest(req *pbs.CreateHostRequest) error { @@ -705,7 +705,7 @@ func validateDeleteRequest(req *pbs.DeleteHostRequest) error { func validateListRequest(req *pbs.ListHostsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix) { + if !handlers.ValidId(handlers.Id(req.GetHostCatalogId()), static.HostCatalogPrefix, plugin.HostCatalogPrefix, plugin.PreviousHostCatalogPrefix) { badFields["host_catalog_id"] = "The field is incorrectly formatted." } if _, err := handlers.NewFilter(req.GetFilter()); err != nil { diff --git a/internal/daemon/controller/handlers/hosts/host_service_test.go b/internal/daemon/controller/handlers/hosts/host_service_test.go index 7e4115236..66fc39668 100644 --- a/internal/daemon/controller/handlers/hosts/host_service_test.go +++ b/internal/daemon/controller/handlers/hosts/host_service_test.go @@ -162,8 +162,9 @@ func TestGet_Plugin(t *testing.T) { } hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId()) h := plugin.TestHost(t, conn, hc.GetPublicId(), "test") + hPrev := plugin.TestHost(t, conn, hc.GetPublicId(), "test-prev", plugin.WithPublicId(fmt.Sprintf("%s_1234567890", plugin.PreviousHostPrefix))) hs := plugin.TestSet(t, conn, kms, sche, hc, plgm) - plugin.TestSetMembers(t, conn, hs.GetPublicId(), []*plugin.Host{h}) + plugin.TestSetMembers(t, conn, hs.GetPublicId(), []*plugin.Host{h, hPrev}) pHost := &pb.Host{ HostCatalogId: hc.GetPublicId(), @@ -193,6 +194,18 @@ func TestGet_Plugin(t *testing.T) { req: &pbs.GetHostRequest{Id: h.GetPublicId()}, res: &pbs.GetHostResponse{Item: pHost}, }, + { + name: "Get an Existing Previous-ID Host", + req: &pbs.GetHostRequest{Id: hPrev.GetPublicId()}, + res: func() *pbs.GetHostResponse { + resp := proto.Clone(pHost).(*pb.Host) + resp.Id = hPrev.PublicId + resp.CreatedTime = hPrev.CreateTime.GetTimestamp() + resp.UpdatedTime = hPrev.UpdateTime.GetTimestamp() + resp.ExternalId = "test-prev" + return &pbs.GetHostResponse{Item: resp} + }(), + }, { name: "non existing", req: &pbs.GetHostRequest{Id: plugin.HostPrefix + "_DoesntExis"}, diff --git a/internal/daemon/controller/handlers/targets/target_service.go b/internal/daemon/controller/handlers/targets/target_service.go index 989044308..5e1f46cb4 100644 --- a/internal/daemon/controller/handlers/targets/target_service.go +++ b/internal/daemon/controller/handlers/targets/target_service.go @@ -1664,8 +1664,7 @@ func validateAddSetsRequest(req *pbs.AddTargetHostSetsRequest) error { badFields[globals.HostSetIdsField] = "Must be non-empty." } for _, id := range req.GetHostSetIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSetIdsField] = fmt.Sprintf("Incorrectly formatted host set identifier %q.", id) break } @@ -1685,8 +1684,7 @@ func validateSetSetsRequest(req *pbs.SetTargetHostSetsRequest) error { badFields[globals.VersionField] = "Required field." } for _, id := range req.GetHostSetIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSetIdsField] = fmt.Sprintf("Incorrectly formatted host set identifier %q.", id) break } @@ -1709,8 +1707,7 @@ func validateRemoveSetsRequest(req *pbs.RemoveTargetHostSetsRequest) error { badFields[globals.HostSetIdsField] = "Must be non-empty." } for _, id := range req.GetHostSetIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSetIdsField] = fmt.Sprintf("Incorrectly formatted host set identifier %q.", id) break } @@ -1733,8 +1730,7 @@ func validateAddHostSourcesRequest(req *pbs.AddTargetHostSourcesRequest) error { badFields[globals.HostSourceIdsField] = "Must be non-empty." } for _, id := range req.GetHostSourceIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSourceIdsField] = fmt.Sprintf("Incorrectly formatted host source identifier %q.", id) break } @@ -1754,8 +1750,7 @@ func validateSetHostSourcesRequest(req *pbs.SetTargetHostSourcesRequest) error { badFields[globals.VersionField] = "Required field." } for _, id := range req.GetHostSourceIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSourceIdsField] = fmt.Sprintf("Incorrectly formatted host source identifier %q.", id) break } @@ -1778,8 +1773,7 @@ func validateRemoveHostSourcesRequest(req *pbs.RemoveTargetHostSourcesRequest) e badFields[globals.HostSourceIdsField] = "Must be non-empty." } for _, id := range req.GetHostSourceIds() { - if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix) && - !strings.HasPrefix(id, fmt.Sprintf("%s_", plugin.HostSetPrefix)) { + if !handlers.ValidId(handlers.Id(id), static.HostSetPrefix, plugin.HostSetPrefix, plugin.PreviousHostSetPrefix) { badFields[globals.HostSourceIdsField] = fmt.Sprintf("Incorrectly formatted host source identifier %q.", id) break } @@ -1803,13 +1797,13 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided." } for _, cl := range req.GetApplicationCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } } for _, cl := range req.GetEgressCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } @@ -1829,13 +1823,13 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ badFields[globals.VersionField] = "Required field." } for _, cl := range req.GetApplicationCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } } for _, cl := range req.GetEgressCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } @@ -1859,13 +1853,13 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided." } for _, cl := range req.GetApplicationCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } } for _, cl := range req.GetEgressCredentialSourceIds() { - if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) { + if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.UsernamePasswordCredentialPrefix, credstatic.PreviousUsernamePasswordCredentialPrefix) { badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl) break } diff --git a/internal/host/plugin/ids.go b/internal/host/plugin/ids.go index 338d1a18f..75a9f1933 100644 --- a/internal/host/plugin/ids.go +++ b/internal/host/plugin/ids.go @@ -10,16 +10,19 @@ import ( ) func init() { - if err := subtypes.Register(host.Domain, Subtype, HostCatalogPrefix, HostSetPrefix, HostPrefix); err != nil { + if err := subtypes.Register(host.Domain, Subtype, HostCatalogPrefix, PreviousHostCatalogPrefix, HostSetPrefix, PreviousHostSetPrefix, HostPrefix, PreviousHostPrefix); err != nil { panic(err) } } // PublicId prefixes for the resources in the plugin package. const ( - HostCatalogPrefix = "hc" - HostSetPrefix = "hs" - HostPrefix = "h" + HostCatalogPrefix = "hcplg" + PreviousHostCatalogPrefix = "hc" + HostSetPrefix = "hsplg" + PreviousHostSetPrefix = "hs" + HostPrefix = "hplg" + PreviousHostPrefix = "h" Subtype = subtypes.Subtype("plugin") ) diff --git a/internal/tests/api/credentials/credentials_test.go b/internal/tests/api/credentials/credentials_test.go index 4b41ad42c..838d9a9f4 100644 --- a/internal/tests/api/credentials/credentials_test.go +++ b/internal/tests/api/credentials/credentials_test.go @@ -194,7 +194,7 @@ func TestErrors(t *testing.T) { apiErr = api.AsServerError(err) assert.NotNil(apiErr) - _, err = c.Read(tc.Context(), static.CredentialPrefix+"_doesntexis") + _, err = c.Read(tc.Context(), static.UsernamePasswordCredentialPrefix+"_doesntexis") require.Error(err) apiErr = api.AsServerError(err) assert.NotNil(apiErr)