From 81baa1843bef51e01b7e140086dafb8967d558a7 Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Fri, 11 Aug 2023 20:15:51 -0400 Subject: [PATCH] Add default identity type. Remove user,service,device types. Fixes #1428 --- .../internal/routes/identity_api_model.go | 2 +- controller/internal/routes/identity_router.go | 3 ++ controller/model/enrollment_mod_ca.go | 16 ++---- controller/model/identity_manager.go | 2 +- controller/model/identity_type_model.go | 4 -- controller/model/testing.go | 10 ++-- controller/persistence/identity_type_store.go | 3 +- .../persistence/migration_initialize.go | 4 +- controller/persistence/migration_v33.go | 49 +++++++++++++++++++ controller/persistence/migrations.go | 6 ++- tests/authenticate.go | 8 +-- tests/ca_test.go | 1 - tests/enrollment_updb_test.go | 4 +- tests/entities.go | 3 +- tests/identity_test.go | 17 ++++--- tests/model_sdk_performance_test.go | 3 +- 16 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 controller/persistence/migration_v33.go diff --git a/controller/internal/routes/identity_api_model.go b/controller/internal/routes/identity_api_model.go index 62d9a0371..8425dada4 100644 --- a/controller/internal/routes/identity_api_model.go +++ b/controller/internal/routes/identity_api_model.go @@ -118,7 +118,7 @@ func MapCreateIdentityToModel(identity *rest_model.IdentityCreate, identityTypeI Tags: TagsOrDefault(identity.Tags), }, Name: stringz.OrEmpty(identity.Name), - IdentityTypeId: identityTypeId, + IdentityTypeId: persistence.DefaultIdentityType, IsDefaultAdmin: false, IsAdmin: *identity.IsAdmin, RoleAttributes: AttributesOrDefault(identity.RoleAttributes), diff --git a/controller/internal/routes/identity_router.go b/controller/internal/routes/identity_router.go index 014556c5b..e24ef1314 100644 --- a/controller/internal/routes/identity_router.go +++ b/controller/internal/routes/identity_router.go @@ -192,6 +192,9 @@ func (r *IdentityRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { func getIdentityTypeId(ae *env.AppEnv, identityType rest_model.IdentityType) string { //todo: Remove this, should be identityTypeId coming in through the API so we can defer this lookup and subsequent checks to the handlers + if identityType == rest_model.IdentityTypeDevice || identityType == rest_model.IdentityTypeService || identityType == rest_model.IdentityTypeUser { + return persistence.DefaultIdentityType + } identityTypeId := "" if identityType, err := ae.Managers.IdentityType.ReadByName(string(identityType)); identityType != nil && err == nil { identityTypeId = identityType.Id diff --git a/controller/model/enrollment_mod_ca.go b/controller/model/enrollment_mod_ca.go index cf4680654..de4421fc0 100644 --- a/controller/model/enrollment_mod_ca.go +++ b/controller/model/enrollment_mod_ca.go @@ -175,17 +175,12 @@ func (module *EnrollModuleCa) completeCertAuthenticatorEnrollment(log *logrus.En log = log.WithField("determinedName", identityName) - identType, err := module.env.GetManagers().IdentityType.ReadByName("Device") - if err != nil { - return nil, err - } - identity := &Identity{ BaseEntity: models.BaseEntity{ Id: identityId, }, Name: identityName, - IdentityTypeId: identType.Id, + IdentityTypeId: persistence.DefaultIdentityType, IsDefaultAdmin: false, IsAdmin: false, RoleAttributes: ca.IdentityRoles, @@ -246,17 +241,12 @@ func (module *EnrollModuleCa) completeExternalIdEnrollment(log *logrus.Entry, co log = log.WithField("determinedName", identityName) - identType, err := module.env.GetManagers().IdentityType.ReadByName("Device") - if err != nil { - return nil, err - } - identity := &Identity{ BaseEntity: models.BaseEntity{ Id: identityId, }, Name: identityName, - IdentityTypeId: identType.Id, + IdentityTypeId: persistence.DefaultIdentityType, IsDefaultAdmin: false, IsAdmin: false, RoleAttributes: ca.IdentityRoles, @@ -264,7 +254,7 @@ func (module *EnrollModuleCa) completeExternalIdEnrollment(log *logrus.Entry, co identity.ExternalId = &externalId - if err = module.env.GetManagers().Identity.Create(identity, context.GetChangeContext()); err != nil { + if err := module.env.GetManagers().Identity.Create(identity, context.GetChangeContext()); err != nil { log.WithError(err).Error("failed to create identity, enrollment failed") return nil, err } diff --git a/controller/model/identity_manager.go b/controller/model/identity_manager.go index 8c09ce1ab..eb5d6feb4 100644 --- a/controller/model/identity_manager.go +++ b/controller/model/identity_manager.go @@ -208,7 +208,7 @@ func (self *IdentityManager) InitializeDefaultAdmin(username, password, name str return errorz.NewFieldError(fmt.Sprintf("name must be at most %v characters", maxDefaultAdminNameLength), "name", name) } - identityType, err := self.env.GetManagers().IdentityType.ReadByName(IdentityTypeUser) + identityType, err := self.env.GetManagers().IdentityType.ReadByName(persistence.DefaultIdentityType) if err != nil { return err diff --git a/controller/model/identity_type_model.go b/controller/model/identity_type_model.go index 9eb808866..c61fdb148 100644 --- a/controller/model/identity_type_model.go +++ b/controller/model/identity_type_model.go @@ -23,10 +23,6 @@ import ( "go.etcd.io/bbolt" ) -const ( - IdentityTypeUser = "User" -) - type IdentityType struct { models.BaseEntity Name string `json:"name"` diff --git a/controller/model/testing.go b/controller/model/testing.go index 891f54edd..ba1969127 100644 --- a/controller/model/testing.go +++ b/controller/model/testing.go @@ -178,15 +178,13 @@ func (ctx *TestContext) Cleanup() { } func (ctx *TestContext) requireNewIdentity(isAdmin bool) *Identity { - identityType, err := ctx.managers.IdentityType.ReadByIdOrName("Service") - ctx.NoError(err) - identity := &Identity{ + newIdentity := &Identity{ Name: eid.New(), IsAdmin: isAdmin, - IdentityTypeId: identityType.Id, + IdentityTypeId: persistence.DefaultIdentityType, } - ctx.NoError(ctx.managers.Identity.Create(identity, change.New())) - return identity + ctx.NoError(ctx.managers.Identity.Create(newIdentity, change.New())) + return newIdentity } func (ctx *TestContext) requireNewService() *Service { diff --git a/controller/persistence/identity_type_store.go b/controller/persistence/identity_type_store.go index 83e9b1f21..9a8d6387e 100644 --- a/controller/persistence/identity_type_store.go +++ b/controller/persistence/identity_type_store.go @@ -21,7 +21,8 @@ import ( ) const ( - RouterIdentityType = "Router" + RouterIdentityType = "Router" + DefaultIdentityType = "Default" ) type IdentityType struct { diff --git a/controller/persistence/migration_initialize.go b/controller/persistence/migration_initialize.go index bf51770c0..be0774b16 100644 --- a/controller/persistence/migration_initialize.go +++ b/controller/persistence/migration_initialize.go @@ -47,9 +47,7 @@ func (m *Migrations) initialize(step *boltz.MigrationStep) int { } var IdentityTypesV1 = map[string]string{ - "User": "User", - "Device": "Device", - "Service": "Service", + "Default": "Default", "Router": "Router", } diff --git a/controller/persistence/migration_v33.go b/controller/persistence/migration_v33.go new file mode 100644 index 000000000..5878e9b46 --- /dev/null +++ b/controller/persistence/migration_v33.go @@ -0,0 +1,49 @@ +/* + Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package persistence + +import ( + "github.com/openziti/storage/ast" + "github.com/openziti/storage/boltz" +) + +func (m *Migrations) migrateIdentityTypesToDefault(step *boltz.MigrationStep) { + step.SetError(m.stores.IdentityType.Create(step.Ctx, &IdentityType{ + BaseExtEntity: *boltz.NewExtEntity(DefaultIdentityType, nil), + Name: DefaultIdentityType, + })) + + cursor := m.stores.Identity.IterateIds(step.Ctx.Tx(), ast.BoolNodeTrue) + for cursor.IsValid() { + id := string(cursor.Current()) + if identityEntity, err := m.stores.Identity.LoadById(step.Ctx.Tx(), id); !step.SetError(err) { + if identityEntity.IdentityTypeId != RouterIdentityType { + identityEntity.IdentityTypeId = DefaultIdentityType + err = m.stores.Identity.Update(step.Ctx, identityEntity, boltz.MapFieldChecker{ + FieldIdentityType: struct{}{}, + "identityTypeId": struct{}{}, + }) + step.SetError(err) + } + } + cursor.Next() + } + + step.SetError(m.stores.IdentityType.DeleteById(step.Ctx, "User")) + step.SetError(m.stores.IdentityType.DeleteById(step.Ctx, "Service")) + step.SetError(m.stores.IdentityType.DeleteById(step.Ctx, "Device")) +} diff --git a/controller/persistence/migrations.go b/controller/persistence/migrations.go index 96d6aa575..a0af11656 100644 --- a/controller/persistence/migrations.go +++ b/controller/persistence/migrations.go @@ -24,7 +24,7 @@ import ( ) const ( - CurrentDbVersion = 32 + CurrentDbVersion = 33 FieldVersion = "version" ) @@ -146,6 +146,10 @@ func (m *Migrations) migrate(step *boltz.MigrationStep) int { step.SetError(m.stores.ConfigType.Update(step.Ctx, interceptV1ConfigType, nil)) } + if step.CurrentVersion < 33 { + m.migrateIdentityTypesToDefault(step) + } + // current version if step.CurrentVersion <= CurrentDbVersion { return CurrentDbVersion diff --git a/tests/authenticate.go b/tests/authenticate.go index 1deba087a..c4a9bf4e4 100644 --- a/tests/authenticate.go +++ b/tests/authenticate.go @@ -377,7 +377,7 @@ func (request *authenticatedRequests) RequireCreateSdkContext(roleAttributes ... func (request *authenticatedRequests) requireCreateIdentity(name string, isAdmin bool, rolesAttributes ...string) string { entityData := gabs.New() request.testContext.setJsonValue(entityData, name, "name") - request.testContext.setJsonValue(entityData, "User", "type") + request.testContext.setJsonValue(entityData, rest_model.IdentityTypeDefault, "type") request.testContext.setJsonValue(entityData, isAdmin, "isAdmin") request.testContext.setJsonValue(entityData, rolesAttributes, "roleAttributes") @@ -471,7 +471,7 @@ func (request *authenticatedRequests) requireCreateIdentityWithUpdbEnrollment(na identity := &identity{ name: name, - identityType: "User", + identityType: string(rest_model.IdentityTypeDefault), isAdmin: isAdmin, enrollment: map[string]interface{}{ "updb": name, @@ -487,7 +487,7 @@ func (request *authenticatedRequests) requireCreateIdentityWithUpdbEnrollment(na func (request *authenticatedRequests) requireCreateIdentityOttEnrollment(name string, isAdmin bool, rolesAttributes ...string) (string, *certAuthenticator) { entityData := gabs.New() request.testContext.setJsonValue(entityData, name, "name") - request.testContext.setJsonValue(entityData, "User", "type") + request.testContext.setJsonValue(entityData, rest_model.IdentityTypeDefault, "type") request.testContext.setJsonValue(entityData, isAdmin, "isAdmin") request.testContext.setJsonValue(entityData, rolesAttributes, "roleAttributes") @@ -506,7 +506,7 @@ func (request *authenticatedRequests) requireCreateIdentityOttEnrollment(name st func (request *authenticatedRequests) requireCreateIdentityOttEnrollmentUnfinished(name string, isAdmin bool, rolesAttributes ...string) string { entityData := gabs.New() request.testContext.setJsonValue(entityData, name, "name") - request.testContext.setJsonValue(entityData, "User", "type") + request.testContext.setJsonValue(entityData, rest_model.IdentityTypeDefault, "type") request.testContext.setJsonValue(entityData, isAdmin, "isAdmin") request.testContext.setJsonValue(entityData, rolesAttributes, "roleAttributes") diff --git a/tests/ca_test.go b/tests/ca_test.go index ad3868893..e6f2f8beb 100644 --- a/tests/ca_test.go +++ b/tests/ca_test.go @@ -1,5 +1,4 @@ //go:build apitests -// +build apitests package tests diff --git a/tests/enrollment_updb_test.go b/tests/enrollment_updb_test.go index f06aaa2c5..15103ee7b 100644 --- a/tests/enrollment_updb_test.go +++ b/tests/enrollment_updb_test.go @@ -1,5 +1,4 @@ //go:build apitests -// +build apitests /* Copyright NetFoundry Inc. @@ -22,6 +21,7 @@ package tests import ( "github.com/Jeffail/gabs" "github.com/google/uuid" + "github.com/openziti/edge-api/rest_model" "net/http" "testing" ) @@ -40,7 +40,7 @@ func Test_EnrollmentUpdb(t *testing.T) { updbName := uuid.New().String() updbUsername := uuid.New().String() updbPassword := uuid.New().String() - updbType := "User" + updbType := rest_model.IdentityTypeDefault _, err := updbCreate.Set(updbName, "name") ctx.Req.NoError(err) diff --git a/tests/entities.go b/tests/entities.go index 3052d34dd..7b2e1d86f 100644 --- a/tests/entities.go +++ b/tests/entities.go @@ -25,6 +25,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" + "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/common/eid" "github.com/openziti/sdk-golang/ziti" "math/big" @@ -243,7 +244,7 @@ func (entity *terminator) fromJson(ctx *TestContext, c *gabs.Container) { func newTestIdentity(isAdmin bool, roleAttributes ...string) *identity { return &identity{ name: eid.New(), - identityType: "User", + identityType: string(rest_model.IdentityTypeDefault), isAdmin: isAdmin, roleAttributes: roleAttributes, } diff --git a/tests/identity_test.go b/tests/identity_test.go index 2518fa45d..79cbefe63 100644 --- a/tests/identity_test.go +++ b/tests/identity_test.go @@ -328,7 +328,7 @@ func Test_Identity(t *testing.T) { ctx.testContextChanged(t) terminatorCost := rest_model.TerminatorCost(1) - identityType := rest_model.IdentityTypeDevice + identityType := rest_model.IdentityTypeDefault identityCreate := &rest_model.IdentityCreate{ AppData: &rest_model.Tags{ @@ -401,7 +401,7 @@ func Test_Identity(t *testing.T) { ctx.testContextChanged(t) updateContent := gabs.New() _, _ = updateContent.SetP(eid.New(), "name") - _, _ = updateContent.SetP("Device", "type") + _, _ = updateContent.SetP(rest_model.IdentityTypeDefault, "type") _, _ = updateContent.SetP(map[string]interface{}{}, "tags") _, _ = updateContent.SetP(false, "isAdmin") _, _ = updateContent.SetP("", "authPolicyId") @@ -424,7 +424,8 @@ func Test_Identity(t *testing.T) { ctx.testContextChanged(t) updateContent := gabs.New() _, _ = updateContent.SetP(eid.New(), "name") - _, _ = updateContent.SetP("Device", "type") + _, _ = updateContent.SetP(rest_model.IdentityTypeDefault, "type") + _, _ = updateContent.SetP(rest_model.IdentityTypeDefault, "type") _, _ = updateContent.SetP(map[string]interface{}{}, "tags") _, _ = updateContent.SetP(false, "isAdmin") _, _ = updateContent.SetP("", "authPolicyId") @@ -449,7 +450,7 @@ func Test_Identity(t *testing.T) { updateContent := gabs.New() _, _ = updateContent.SetP(eid.New(), "name") - _, _ = updateContent.SetP("Device", "type") + _, _ = updateContent.SetP(rest_model.IdentityTypeDefault, "type") _, _ = updateContent.SetP(map[string]interface{}{}, "tags") _, _ = updateContent.SetP(true, "isAdmin") _, _ = updateContent.SetP(true, "isDefaultAdmin") @@ -472,7 +473,7 @@ func Test_Identity(t *testing.T) { newName := eid.New() updateContent := gabs.New() _, _ = updateContent.SetP(newName, "name") - _, _ = updateContent.SetP("Device", "type") + _, _ = updateContent.SetP(rest_model.IdentityTypeDefault, "type") _, _ = updateContent.SetP(map[string]interface{}{}, "tags") _, _ = updateContent.SetP(false, "isAdmin") _, _ = updateContent.SetP("", "authPolicyId") @@ -562,7 +563,7 @@ func Test_Identity(t *testing.T) { t.Run("disable and enable identities affect cert authentication", func(t *testing.T) { ctx.testContextChanged(t) - identityType := rest_model.IdentityTypeDevice + identityType := rest_model.IdentityTypeDefault identity := &rest_model.IdentityCreate{ IsAdmin: B(false), Name: S("test-identity-disable-cert"), @@ -635,7 +636,7 @@ func Test_Identity(t *testing.T) { ctx.testContextChanged(t) username := "test-identity-disable-updb" password := "test-identity-disable-updb-password" - identityType := rest_model.IdentityTypeDevice + identityType := rest_model.IdentityTypeDefault identity := &rest_model.IdentityCreate{ IsAdmin: B(false), Name: S("test-identity-disable-updb"), @@ -741,7 +742,7 @@ func Test_Identity(t *testing.T) { ctx.NoError(err) ctx.Equal(http.StatusOK, resp.StatusCode()) - identityType := rest_model.IdentityTypeDevice + identityType := rest_model.IdentityTypeDefault identity := &rest_model.IdentityCreate{ IsAdmin: B(false), Name: S("test-identity-disable-updb-01"), diff --git a/tests/model_sdk_performance_test.go b/tests/model_sdk_performance_test.go index 946f14fdd..d37a310e1 100644 --- a/tests/model_sdk_performance_test.go +++ b/tests/model_sdk_performance_test.go @@ -1,5 +1,4 @@ //go:build perftests -// +build perftests package tests @@ -266,7 +265,7 @@ func (ctx *modelPerf) createIdentities(spec *perfScenarioSpec) { Id: id, }, Name: id, - IdentityTypeId: "User", + IdentityTypeId: string(rest_model.IdentityTypeDefault), IsDefaultAdmin: false, IsAdmin: false, RoleAttributes: spec.identityAttrs[i],