diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 601379241..ccdc34770 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: '1.19.x' + go-version: '1.20.x' - name: Install Ziti CI uses: netfoundry/ziti-ci@v1 diff --git a/.golangci.yml b/.golangci.yml index cf80009a4..b2022d668 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,3 +2,10 @@ run: deadline: 8m skip-dirs: - controller/zitiql + +# golangci gives false positives for implementations of methods using generics in generic interfaces +issues: + exclude-rules: + - path: 'controller/model/.*.go' + linters: + - unused diff --git a/controller/env/appenv.go b/controller/env/appenv.go index c25e22b0e..90e7122a2 100644 --- a/controller/env/appenv.go +++ b/controller/env/appenv.go @@ -331,7 +331,7 @@ func processSecondaryJwtSigner(ae *AppEnv, rc *response.RequestContext) bool { extJwtAuthVal := ae.GetAuthRegistry().GetByMethod(model.AuthMethodExtJwt) extJwtAuth := extJwtAuthVal.(*model.AuthModuleExtJwt) if extJwtAuth != nil { - authResult, err := extJwtAuth.ProcessSecondary(model.NewAuthContextHttp(rc.Request, model.AuthMethodExtJwt, nil)) + authResult, err := extJwtAuth.ProcessSecondary(model.NewAuthContextHttp(rc.Request, model.AuthMethodExtJwt, nil, rc.NewChangeContext())) if err != nil { return false @@ -467,13 +467,7 @@ func (ae *AppEnv) InitPersistence() error { ae.EventDispatcher = events.NewDispatcher(ae.GetHostController().GetNetwork(), ae.GetDbProvider(), ae.BoltStores, ae.GetHostController().GetCloseNotifyChannel()) persistence.ServiceEvents.AddServiceEventHandler(ae.HandleServiceEvent) - ae.BoltStores.Identity.AddListener(boltz.EventDelete, func(i ...interface{}) { - for _, val := range i { - if identity, ok := val.(*persistence.Identity); ok { - ae.IdentityRefreshMap.Remove(identity.Id) - } - } - }) + ae.BoltStores.Identity.AddEntityIdListener(ae.IdentityRefreshMap.Remove, boltz.EntityDeletedAsync) return err } diff --git a/controller/env/broker.go b/controller/env/broker.go index 2c6644b87..f0f0c6f69 100644 --- a/controller/env/broker.go +++ b/controller/env/broker.go @@ -62,11 +62,11 @@ func NewBroker(ae *AppEnv, synchronizer RouterSyncStrategy) *Broker { routerMsgBufferSize: 100, } - broker.ae.GetStores().Session.AddListener(boltz.EventDelete, broker.sessionDeleted) - broker.ae.GetStores().ApiSession.AddListener(persistence.EventFullyAuthenticated, broker.apiSessionFullyAuthenticated) - broker.ae.GetStores().ApiSession.AddListener(boltz.EventDelete, broker.apiSessionDeleted) - broker.ae.GetStores().ApiSessionCertificate.AddListener(boltz.EventCreate, broker.apiSessionCertificateCreated) - broker.ae.GetStores().ApiSessionCertificate.AddListener(boltz.EventDelete, broker.apiSessionCertificateDeleted) + broker.ae.GetStores().Session.AddEntityEventListenerF(broker.routerSyncStrategy.SessionDeleted, boltz.EntityDeletedAsync) + broker.ae.GetStores().ApiSession.AddEntityEventListenerF(broker.routerSyncStrategy.ApiSessionDeleted, boltz.EntityDeletedAsync) + broker.ae.GetStores().ApiSession.GetEventsEmitter().AddListener(persistence.EventFullyAuthenticated, broker.apiSessionFullyAuthenticated) + broker.ae.GetStores().ApiSessionCertificate.AddEntityEventListenerF(broker.apiSessionCertificateCreated, boltz.EntityCreatedAsync) + broker.ae.GetStores().ApiSessionCertificate.AddEntityEventListenerF(broker.apiSessionCertificateDeleted, boltz.EntityDeletedAsync) ae.HostController.GetNetwork().AddRouterPresenceHandler(broker) @@ -124,52 +124,15 @@ func (broker *Broker) apiSessionFullyAuthenticated(args ...interface{}) { go broker.routerSyncStrategy.ApiSessionAdded(apiSession) } -func (broker *Broker) apiSessionDeleted(args ...interface{}) { - var apiSession *persistence.ApiSession - if len(args) == 1 { - apiSession, _ = args[0].(*persistence.ApiSession) - } - - if apiSession == nil { - pfxlog.Logger().Error("during broker apiSessionDeleted could not cast arg[0] to *persistence.ApiSession") - return - } - - go broker.routerSyncStrategy.ApiSessionDeleted(apiSession) +func (broker *Broker) apiSessionCertificateCreated(entity *persistence.ApiSessionCertificate) { + go broker.apiSessionCertificateHandler(false, entity) } -func (broker *Broker) sessionDeleted(args ...interface{}) { - var session *persistence.Session - if len(args) == 1 { - session, _ = args[0].(*persistence.Session) - } - - if session == nil { - pfxlog.Logger().Error("during broker sessionDeleted could not cast arg[0] to *persistence.Session") - return - } - - go broker.routerSyncStrategy.SessionDeleted(session) +func (broker *Broker) apiSessionCertificateDeleted(entity *persistence.ApiSessionCertificate) { + go broker.apiSessionCertificateHandler(true, entity) } -func (broker *Broker) apiSessionCertificateCreated(args ...interface{}) { - go broker.apiSessionCertificateHandler(false, args...) -} - -func (broker *Broker) apiSessionCertificateDeleted(args ...interface{}) { - go broker.apiSessionCertificateHandler(true, args...) -} - -func (broker *Broker) apiSessionCertificateHandler(delete bool, args ...interface{}) { - var apiSessionCert *persistence.ApiSessionCertificate - if len(args) == 1 { - apiSessionCert, _ = args[0].(*persistence.ApiSessionCertificate) - } - - if apiSessionCert == nil { - pfxlog.Logger().Error("during broker apiSessionCertificateEvent could not cast arg[0] to *persistence.ApiSessionCertificate") - return - } +func (broker *Broker) apiSessionCertificateHandler(delete bool, apiSessionCert *persistence.ApiSessionCertificate) { var apiSession *persistence.ApiSession var err error err = broker.ae.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { diff --git a/controller/handler_edge_ctrl/common.go b/controller/handler_edge_ctrl/common.go index b55ed7134..e120e541d 100644 --- a/controller/handler_edge_ctrl/common.go +++ b/controller/handler_edge_ctrl/common.go @@ -2,6 +2,7 @@ package handler_edge_ctrl import ( "fmt" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/fields" "math" "time" @@ -107,11 +108,36 @@ type baseSessionRequestContext struct { err controllerError sourceRouter *network.Router session *model.Session + apiSession *model.ApiSession service *model.Service newSession bool logContext logcontext.Context } +func (self *baseSessionRequestContext) newChangeContext() *change.Context { + result := change.New().SetSource(fmt.Sprintf("ctrl[edge/%v]", self.handler.getChannel().Underlay().GetRemoteAddr().String())) + if self.session != nil { + result. + SetChangeAuthorId(self.session.IdentityId). + SetChangeAuthorName(self.apiSession.Identity.Name). + SetChangeAuthorType("identity") + } else if self.sourceRouter != nil { + result. + SetChangeAuthorId(self.sourceRouter.Id). + SetChangeAuthorName(self.sourceRouter.Name). + SetChangeAuthorType("router") + } + return result +} + +func (self *baseSessionRequestContext) newTunnelChangeContext() *change.Context { + return change.New(). + SetChangeAuthorId(self.sourceRouter.Id). + SetChangeAuthorName(self.sourceRouter.Name). + SetChangeAuthorType("router"). + SetSource(fmt.Sprintf("ctrl[edge:tunnel/%v]", self.handler.getChannel().Underlay().GetRemoteAddr().String())) +} + func (self *baseSessionRequestContext) GetMessage() *channel.Message { return self.msg } @@ -165,6 +191,7 @@ func (self *baseSessionRequestContext) loadSession(token string) { WithError(self.err).Errorf("invalid api-session") return } + self.apiSession = apiSession self.logContext = logcontext.NewContext() traceSpec := self.handler.getAppEnv().TraceManager.GetIdentityTrace(apiSession.IdentityId) @@ -331,7 +358,7 @@ func (self *baseSessionRequestContext) verifyTerminator(terminatorId string, bin return nil } -func (self *baseSessionRequestContext) updateTerminator(terminator *network.Terminator, request UpdateTerminatorRequest) { +func (self *baseSessionRequestContext) updateTerminator(terminator *network.Terminator, request UpdateTerminatorRequest, ctx *change.Context) { if self.err == nil { checker := fields.UpdatedFieldsMap{} @@ -359,7 +386,7 @@ func (self *baseSessionRequestContext) updateTerminator(terminator *network.Term checker[db.FieldTerminatorPrecedence] = struct{}{} } - self.err = internalError(self.handler.getNetwork().Terminators.Update(terminator, checker)) + self.err = internalError(self.handler.getNetwork().Terminators.Update(terminator, checker, ctx)) } } diff --git a/controller/handler_edge_ctrl/common_tunnel.go b/controller/handler_edge_ctrl/common_tunnel.go index 34c266850..40556b25e 100644 --- a/controller/handler_edge_ctrl/common_tunnel.go +++ b/controller/handler_edge_ctrl/common_tunnel.go @@ -12,7 +12,6 @@ import ( "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/storage/boltz" "github.com/sirupsen/logrus" - "go.etcd.io/bbolt" "sync" "time" ) @@ -152,9 +151,7 @@ func (self *baseTunnelRequestContext) ensureApiSessionLocking(configTypes []stri IPAddress: self.handler.getChannel().Underlay().GetRemoteAddr().String(), } - err := self.handler.getAppEnv().GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - + err := self.handler.getAppEnv().GetDbProvider().GetDb().Update(self.newTunnelChangeContext().NewMutateContext(), func(ctx boltz.MutateContext) error { var err error apiSession.Id, err = self.handler.getAppEnv().GetManagers().ApiSession.Create(ctx, apiSession, nil) if err != nil { @@ -272,7 +269,7 @@ func (self *baseTunnelRequestContext) ensureSessionForService(sessionId, session Type: sessionType, } - id, err := self.handler.getAppEnv().Managers.Session.Create(session) + id, err := self.handler.getAppEnv().Managers.Session.Create(session, self.newTunnelChangeContext()) if err != nil { self.err = internalError(err) return @@ -362,7 +359,7 @@ func (self *baseTunnelRequestContext) updateIdentityInfo(envInfo *edge_ctrl_pb.E } if envInfo != nil || sdkInfo != nil { - self.err = internalError(self.handler.getAppEnv().GetManagers().Identity.PatchInfo(self.identity)) + self.err = internalError(self.handler.getAppEnv().GetManagers().Identity.PatchInfo(self.identity, self.newTunnelChangeContext())) } } } diff --git a/controller/handler_edge_ctrl/create_terminator.go b/controller/handler_edge_ctrl/create_terminator.go index 0734b3194..0e9ec3220 100644 --- a/controller/handler_edge_ctrl/create_terminator.go +++ b/controller/handler_edge_ctrl/create_terminator.go @@ -115,7 +115,11 @@ func (self *createTerminatorHandler) CreateTerminator(ctx *CreateTerminatorReque HostId: ctx.session.IdentityId, } - cmd := &model.CreateEdgeTerminatorCmd{Env: self.appEnv, Entity: terminator} + cmd := &model.CreateEdgeTerminatorCmd{ + Env: self.appEnv, + Entity: terminator, + Context: ctx.newChangeContext(), + } err = self.appEnv.GetHostController().GetNetwork().Managers.Command.Dispatch(cmd) if err != nil { self.returnError(ctx, internalError(err)) diff --git a/controller/handler_edge_ctrl/create_tunnel_terminator.go b/controller/handler_edge_ctrl/create_tunnel_terminator.go index 99fac2977..d68cfc8ac 100644 --- a/controller/handler_edge_ctrl/create_tunnel_terminator.go +++ b/controller/handler_edge_ctrl/create_tunnel_terminator.go @@ -125,7 +125,7 @@ func (self *createTunnelTerminatorHandler) CreateTerminator(ctx *CreateTunnelTer } n := self.appEnv.GetHostController().GetNetwork() - err := n.Terminators.Create(terminator) + err := n.Terminators.Create(terminator, ctx.newTunnelChangeContext()) if err != nil { // terminator might have been created while we were trying to create. terminator, _ = self.getNetwork().Terminators.Read(ctx.req.Address) diff --git a/controller/handler_edge_ctrl/extend_enrollment.go b/controller/handler_edge_ctrl/extend_enrollment.go index db5677e82..6764a36b4 100644 --- a/controller/handler_edge_ctrl/extend_enrollment.go +++ b/controller/handler_edge_ctrl/extend_enrollment.go @@ -17,15 +17,29 @@ package handler_edge_ctrl import ( + "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" "github.com/openziti/edge/internal/cert" "github.com/openziti/edge/pb/edge_ctrl_pb" + "github.com/openziti/fabric/controller/change" + "github.com/openziti/fabric/controller/models" "google.golang.org/protobuf/proto" ) +func newRouterChangeContext(router interface { + models.Named + GetId() string +}, ch channel.Channel) *change.Context { + return change.New(). + SetChangeAuthorId(router.GetId()). + SetChangeAuthorName(router.GetName()). + SetChangeAuthorType("router"). + SetSource(fmt.Sprintf("ctrl[edge/%v]", ch.Underlay().GetRemoteAddr().String())) +} + type extendEnrollmentHandler struct { appEnv *env.AppEnv } @@ -68,6 +82,7 @@ func (h *extendEnrollmentHandler) HandleReceive(msg *channel.Message, ch channel var newCerts *model.ExtendedCerts if router, _ := h.appEnv.Managers.EdgeRouter.ReadOneByFingerprint(fingerprint); router != nil { + changeCtx := newRouterChangeContext(router, ch) log = log.WithFields(map[string]interface{}{ "routerId": router.Id, @@ -75,9 +90,9 @@ func (h *extendEnrollmentHandler) HandleReceive(msg *channel.Message, ch channel }) if req.RequireVerification { - newCerts, err = h.appEnv.Managers.EdgeRouter.ExtendEnrollmentWithVerify(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr)) + newCerts, err = h.appEnv.Managers.EdgeRouter.ExtendEnrollmentWithVerify(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr), changeCtx) } else { - newCerts, err = h.appEnv.Managers.EdgeRouter.ExtendEnrollment(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr)) + newCerts, err = h.appEnv.Managers.EdgeRouter.ExtendEnrollment(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr), changeCtx) } if err != nil { @@ -86,11 +101,12 @@ func (h *extendEnrollmentHandler) HandleReceive(msg *channel.Message, ch channel } } else if router, _ := h.appEnv.Managers.TransitRouter.ReadOneByFingerprint(fingerprint); router != nil { + changeCtx := newRouterChangeContext(router, ch) if req.RequireVerification { - newCerts, err = h.appEnv.Managers.TransitRouter.ExtendEnrollmentWithVerify(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr)) + newCerts, err = h.appEnv.Managers.TransitRouter.ExtendEnrollmentWithVerify(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr), changeCtx) } else { - newCerts, err = h.appEnv.Managers.TransitRouter.ExtendEnrollment(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr)) + newCerts, err = h.appEnv.Managers.TransitRouter.ExtendEnrollment(router, []byte(req.ClientCertCsr), []byte(req.ServerCertCsr), changeCtx) } if err != nil { diff --git a/controller/handler_edge_ctrl/extend_enrollment_verify.go b/controller/handler_edge_ctrl/extend_enrollment_verify.go index 7de0009d8..2783d63ca 100644 --- a/controller/handler_edge_ctrl/extend_enrollment_verify.go +++ b/controller/handler_edge_ctrl/extend_enrollment_verify.go @@ -90,7 +90,8 @@ func (h *extendEnrollmentVerifyHandler) HandleReceive(msg *channel.Message, ch c return } - err := h.appEnv.Managers.EdgeRouter.ExtendEnrollmentVerify(edgeRouter) + changeCtx := newRouterChangeContext(edgeRouter, ch) + err := h.appEnv.Managers.EdgeRouter.ExtendEnrollmentVerify(edgeRouter, changeCtx) if err != nil { h.respond(&edge_ctrl_pb.Error{ Code: "VERIFY_ERROR", @@ -122,7 +123,8 @@ func (h *extendEnrollmentVerifyHandler) HandleReceive(msg *channel.Message, ch c return } - err := h.appEnv.Managers.TransitRouter.ExtendEnrollmentVerify(router) + changeCtx := newRouterChangeContext(router, ch) + err := h.appEnv.Managers.TransitRouter.ExtendEnrollmentVerify(router, changeCtx) if err != nil { h.respond(&edge_ctrl_pb.Error{ Code: "VERIFY_ERROR", diff --git a/controller/handler_edge_ctrl/remove_terminator.go b/controller/handler_edge_ctrl/remove_terminator.go index f6203ef84..31d182424 100644 --- a/controller/handler_edge_ctrl/remove_terminator.go +++ b/controller/handler_edge_ctrl/remove_terminator.go @@ -104,7 +104,7 @@ func (self *removeTerminatorHandler) RemoveTerminator(ctx *RemoveTerminatorReque return } - err := self.getNetwork().Terminators.Delete(ctx.req.TerminatorId) + err := self.getNetwork().Terminators.Delete(ctx.req.TerminatorId, ctx.newChangeContext()) if err != nil { self.returnError(ctx, internalError(err)) return diff --git a/controller/handler_edge_ctrl/remove_tunnel_terminator.go b/controller/handler_edge_ctrl/remove_tunnel_terminator.go index f434c8944..5dff69ae7 100644 --- a/controller/handler_edge_ctrl/remove_tunnel_terminator.go +++ b/controller/handler_edge_ctrl/remove_tunnel_terminator.go @@ -69,7 +69,7 @@ func (self *removeTunnelTerminatorHandler) RemoveTerminator(ctx *RemoveTunnelTer logger = logger.WithField("serviceId", t.Service) - err := self.getNetwork().Terminators.Delete(ctx.terminatorId) + err := self.getNetwork().Terminators.Delete(ctx.terminatorId, ctx.newTunnelChangeContext()) if err != nil { self.returnError(ctx, internalError(err)) return diff --git a/controller/handler_edge_ctrl/update_terminator.go b/controller/handler_edge_ctrl/update_terminator.go index 80f08dd78..a7cd93238 100644 --- a/controller/handler_edge_ctrl/update_terminator.go +++ b/controller/handler_edge_ctrl/update_terminator.go @@ -83,7 +83,8 @@ func (self *updateTerminatorHandler) UpdateTerminator(ctx *UpdateTerminatorReque ctx.checkSessionType(persistence.SessionTypeBind) ctx.checkSessionFingerprints(ctx.req.Fingerprints) terminator := ctx.verifyTerminator(ctx.req.TerminatorId, edge_common.EdgeBinding) - ctx.updateTerminator(terminator, ctx.req) + + ctx.updateTerminator(terminator, ctx.req, ctx.newChangeContext()) if ctx.err != nil { self.returnError(ctx, ctx.err) diff --git a/controller/handler_edge_ctrl/update_tunnel_terminator.go b/controller/handler_edge_ctrl/update_tunnel_terminator.go index e9b29a0c0..b8e4e4a02 100644 --- a/controller/handler_edge_ctrl/update_tunnel_terminator.go +++ b/controller/handler_edge_ctrl/update_tunnel_terminator.go @@ -77,7 +77,7 @@ func (self *updateTunnelTerminatorHandler) UpdateTerminator(ctx *UpdateTunnelTer logrus.Debug("update request received") terminator := ctx.verifyTerminator(ctx.req.TerminatorId, edge_common.TunnelBinding) - ctx.updateTerminator(terminator, ctx.req) + ctx.updateTerminator(terminator, ctx.req, ctx.newTunnelChangeContext()) if ctx.err != nil { self.returnError(ctx, ctx.err) return diff --git a/controller/internal/policy/api_session_enforcer.go b/controller/internal/policy/api_session_enforcer.go index 1ea85aeff..3a6678704 100644 --- a/controller/internal/policy/api_session_enforcer.go +++ b/controller/internal/policy/api_session_enforcer.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" "github.com/openziti/edge/runner" + "github.com/openziti/fabric/controller/change" "github.com/sirupsen/logrus" "time" ) @@ -97,11 +98,12 @@ func (s *ApiSessionEnforcer) Run() error { logrus.Debugf("found %v expired api-sessions to remove", len(ids)) - if err = s.appEnv.GetManagers().ApiSession.DeleteBatch(ids); err != nil { + ctx := change.New().SetSource("api-session.enforcer").SetChangeAuthorType("controller") + if err = s.appEnv.GetManagers().ApiSession.DeleteBatch(ids, ctx); err != nil { logrus.WithError(err).Error("failure while batch deleting expired api sessions") for _, id := range ids { - if err = s.appEnv.GetManagers().ApiSession.Delete(id); err != nil { + if err = s.appEnv.GetManagers().ApiSession.Delete(id, ctx); err != nil { logrus.WithError(err).Errorf("failure while deleting expired api session: %v", id) } } diff --git a/controller/internal/policy/service_policy_enforcer.go b/controller/internal/policy/service_policy_enforcer.go index 03e39a41d..1eca8b431 100644 --- a/controller/internal/policy/service_policy_enforcer.go +++ b/controller/internal/policy/service_policy_enforcer.go @@ -19,6 +19,7 @@ package policy import ( "fmt" "github.com/michaelquigley/pfxlog" + "github.com/openziti/fabric/controller/change" "time" "github.com/openziti/edge/controller/env" @@ -77,10 +78,8 @@ func (enforcer *ServicePolicyEnforcer) handleServiceEvent(event *persistence.Ser var sessionsToDelete []string err := enforcer.appEnv.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { - var err error - identity := &persistence.Identity{} - - if _, err := enforcer.appEnv.GetStores().Identity.BaseLoadOneById(tx, event.IdentityId, identity); err != nil { + identity, err := enforcer.appEnv.GetStores().Identity.LoadOneById(tx, event.IdentityId) + if err != nil { return err } @@ -103,8 +102,9 @@ func (enforcer *ServicePolicyEnforcer) handleServiceEvent(event *persistence.Ser } } + ctx := change.New().SetSource("service-policy.enforcer").SetChangeAuthorType("controller") for _, sessionId := range sessionsToDelete { - _ = enforcer.appEnv.GetManagers().Session.Delete(sessionId) + _ = enforcer.appEnv.GetManagers().Session.Delete(sessionId, ctx) log.Debugf("session %v deleted", sessionId) } @@ -134,16 +134,12 @@ func (enforcer *ServicePolicyEnforcer) Run() error { var sessionsToRemove []string err = enforcer.appEnv.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { for _, session := range result.Sessions { - apiSession := &persistence.ApiSession{} - _, err := enforcer.appEnv.GetStores().ApiSession.BaseLoadOneById(tx, session.ApiSessionId, apiSession) - + apiSession, err := enforcer.appEnv.GetStores().ApiSession.LoadOneById(tx, session.ApiSessionId) if err != nil { return err } - identity := &persistence.Identity{} - _, err = enforcer.appEnv.GetStores().Identity.BaseLoadOneById(tx, apiSession.IdentityId, identity) - + identity, err := enforcer.appEnv.GetStores().Identity.LoadOneById(tx, apiSession.IdentityId) if err != nil { return err } @@ -172,8 +168,9 @@ func (enforcer *ServicePolicyEnforcer) Run() error { return err } + ctx := change.New().SetSource("service-policy.enforcer").SetChangeAuthorType("controller") for _, sessionId := range sessionsToRemove { - _ = enforcer.appEnv.GetManagers().Session.Delete(sessionId) + _ = enforcer.appEnv.GetManagers().Session.Delete(sessionId, ctx) } enforcer.appEnv.GetMetricsRegistry().Meter(SessionPolicyEnforcerRunDeletes).Mark(int64(len(sessionsToRemove))) diff --git a/controller/internal/policy/session_enforcer_test.go b/controller/internal/policy/session_enforcer_test.go index cb3a17a0c..de50f486c 100644 --- a/controller/internal/policy/session_enforcer_test.go +++ b/controller/internal/policy/session_enforcer_test.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/eid" "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "github.com/sirupsen/logrus" "testing" "time" @@ -49,25 +50,25 @@ func (ctx *enforcerTestContext) testSessionsCleanup() { identity := ctx.RequireNewIdentity("Jojo", false) apiSession := persistence.NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) service := ctx.RequireNewService("test-service") session := NewSession(apiSession.Id, service.Id) - ctx.RequireCreate(session) - ctx.ValidateBaseline(session, compareOpts) + boltztest.RequireCreate(ctx, session) + boltztest.ValidateBaseline(ctx, session, compareOpts) session2 := NewSession(apiSession.Id, service.Id) session2.Type = persistence.PolicyTypeBindName - ctx.RequireCreate(session2) - ctx.ValidateBaseline(session2, compareOpts) + boltztest.RequireCreate(ctx, session2) + boltztest.ValidateBaseline(ctx, session2, compareOpts) service2 := ctx.RequireNewService("test-service-2") session3 := NewSession(apiSession.Id, service2.Id) session3.Tags = ctx.CreateTags() - ctx.RequireCreate(session3) - ctx.ValidateBaseline(session3, compareOpts) + boltztest.RequireCreate(ctx, session3) + boltztest.ValidateBaseline(ctx, session3, compareOpts) - ctx.RequireReload(session) - ctx.RequireReload(session2) + boltztest.RequireReload(ctx, session) + boltztest.RequireReload(ctx, session2) enforcer := &ApiSessionEnforcer{ appEnv: ctx, @@ -85,10 +86,10 @@ func (ctx *enforcerTestContext) testSessionsCleanup() { ctx.Fail("did not receive done notification from eventual eventer") } - ctx.ValidateDeleted(apiSession.Id) - ctx.ValidateDeleted(session.Id) - ctx.ValidateDeleted(session2.Id) - ctx.ValidateDeleted(session3.Id) + boltztest.ValidateDeleted(ctx, apiSession.Id) + boltztest.ValidateDeleted(ctx, session.Id) + boltztest.ValidateDeleted(ctx, session2.Id) + boltztest.ValidateDeleted(ctx, session3.Id) } func NewSession(apiSessionId, serviceId string) *persistence.Session { diff --git a/controller/internal/routes/api_session_api_model.go b/controller/internal/routes/api_session_api_model.go index 0d82dc4d0..6e0ce7fa2 100644 --- a/controller/internal/routes/api_session_api_model.go +++ b/controller/internal/routes/api_session_api_model.go @@ -17,9 +17,7 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -58,25 +56,8 @@ func (factory *ApiSessionLinkFactoryImpl) Links(entity models.Entity) rest_model } } -func MapApiSessionToRestInterface(ae *env.AppEnv, _ *response.RequestContext, apiSessionEntity models.Entity) (interface{}, error) { - apiSession, ok := apiSessionEntity.(*model.ApiSession) - - if !ok { - err := fmt.Errorf("entity is not an ApiSession \"%s\"", apiSessionEntity.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapApiSessionToRestModel(ae, apiSession) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", apiSessionEntity.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapApiSessionToRestInterface(ae *env.AppEnv, _ *response.RequestContext, apiSession *model.ApiSession) (interface{}, error) { + return MapApiSessionToRestModel(ae, apiSession) } func MapApiSessionToRestModel(ae *env.AppEnv, apiSession *model.ApiSession) (*rest_model.APISessionDetail, error) { diff --git a/controller/internal/routes/api_session_router.go b/controller/internal/routes/api_session_router.go index 79499564f..c5298b809 100644 --- a/controller/internal/routes/api_session_router.go +++ b/controller/internal/routes/api_session_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/api_session" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" ) @@ -54,11 +55,11 @@ func (ir *ApiSessionHandler) Register(ae *env.AppEnv) { } func (ir *ApiSessionHandler) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.ApiSession, MapApiSessionToRestInterface) + ListWithHandler[*model.ApiSession](ae, rc, ae.Managers.ApiSession, MapApiSessionToRestInterface) } func (ir *ApiSessionHandler) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.ApiSession, MapApiSessionToRestInterface) + DetailWithHandler[*model.ApiSession](ae, rc, ae.Managers.ApiSession, MapApiSessionToRestInterface) } func (ir *ApiSessionHandler) Delete(ae *env.AppEnv, rc *response.RequestContext) { diff --git a/controller/internal/routes/auth_policy_api_model.go b/controller/internal/routes/auth_policy_api_model.go index 0f848de36..5e25118b2 100644 --- a/controller/internal/routes/auth_policy_api_model.go +++ b/controller/internal/routes/auth_policy_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -31,26 +29,8 @@ const EntityNameAuthPolicy = "auth-policies" var AuthPolicyLinkFactory = NewBasicLinkFactory(EntityNameAuthPolicy) -func MapAuthPolicyToRestEntity(_ *env.AppEnv, _ *response.RequestContext, entity models.Entity) (interface{}, error) { - authPolicyModel, ok := entity.(*model.AuthPolicy) - - if !ok { - err := fmt.Errorf("could not convert to %T to %T: \"%s\"", entity, authPolicyModel, entity.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapAuthPolicyToRestModel(authPolicyModel) - - if err != nil { - err := fmt.Errorf("could not convert to %T to %T: \"%s\": %s", authPolicyModel, restModel, entity.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - return restModel, err +func MapAuthPolicyToRestEntity(_ *env.AppEnv, _ *response.RequestContext, authPolicyModel *model.AuthPolicy) (interface{}, error) { + return MapAuthPolicyToRestModel(authPolicyModel) } func MapAuthPolicyToRestModel(model *model.AuthPolicy) (*rest_model.AuthPolicyDetail, error) { diff --git a/controller/internal/routes/auth_policy_router.go b/controller/internal/routes/auth_policy_router.go index ad19e4155..72362b7ac 100644 --- a/controller/internal/routes/auth_policy_router.go +++ b/controller/internal/routes/auth_policy_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/auth_policy" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -67,16 +68,16 @@ func (r *AuthPolicyRouter) Register(ae *env.AppEnv) { } func (r *AuthPolicyRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.AuthPolicy, MapAuthPolicyToRestEntity) + ListWithHandler[*model.AuthPolicy](ae, rc, ae.Managers.AuthPolicy, MapAuthPolicyToRestEntity) } func (r *AuthPolicyRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.AuthPolicy, MapAuthPolicyToRestEntity) + DetailWithHandler[*model.AuthPolicy](ae, rc, ae.Managers.AuthPolicy, MapAuthPolicyToRestEntity) } func (r *AuthPolicyRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params auth_policy.CreateAuthPolicyParams) { Create(rc, rc, AuthPolicyLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.AuthPolicy.Create, MapCreateAuthPolicyToModel(params.AuthPolicy)) + return MapCreate(ae.Managers.AuthPolicy.Create, MapCreateAuthPolicyToModel(params.AuthPolicy), rc) }) } @@ -86,12 +87,12 @@ func (r *AuthPolicyRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *AuthPolicyRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params auth_policy.UpdateAuthPolicyParams) { Update(rc, func(id string) error { - return ae.Managers.AuthPolicy.Update(MapUpdateAuthPolicyToModel(params.ID, params.AuthPolicy), nil) + return ae.Managers.AuthPolicy.Update(MapUpdateAuthPolicyToModel(params.ID, params.AuthPolicy), nil, rc.NewChangeContext()) }) } func (r *AuthPolicyRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params auth_policy.PatchAuthPolicyParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.AuthPolicy.Update(MapPatchAuthPolicyToModel(params.ID, params.AuthPolicy), fields.FilterMaps("tags")) + return ae.Managers.AuthPolicy.Update(MapPatchAuthPolicyToModel(params.ID, params.AuthPolicy), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } diff --git a/controller/internal/routes/authenticate_router.go b/controller/internal/routes/authenticate_router.go index 1cad95a99..ccc476b1b 100644 --- a/controller/internal/routes/authenticate_router.go +++ b/controller/internal/routes/authenticate_router.go @@ -76,10 +76,12 @@ func (ro *AuthRouter) Register(ae *env.AppEnv) { func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, httpRequest *http.Request, method string, auth *rest_model.Authenticate) { start := time.Now() logger := pfxlog.Logger() - authContext := model.NewAuthContextHttp(httpRequest, method, auth) + authContext := model.NewAuthContextHttp(httpRequest, method, auth, rc.NewChangeContext()) authResult, err := ae.Managers.Authenticator.Authorize(authContext) + changeCtx := rc.NewChangeContext() + if err != nil { rc.RespondWithError(err) return @@ -124,7 +126,7 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h } if shouldUpdate { - if err := ae.GetManagers().Identity.PatchInfo(identity); err != nil { + if err := ae.GetManagers().Identity.PatchInfo(identity, changeCtx); err != nil { logger.WithError(err).Errorf("failed to update sdk/env info on identity [%s] auth", identity.Id) } } @@ -170,7 +172,7 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h sessionCerts = append(sessionCerts, sessionCert) } - sessionId, err := ae.Managers.ApiSession.Create(nil, newApiSession, sessionCerts) + sessionId, err := ae.Managers.ApiSession.Create(changeCtx.NewMutateContext(), newApiSession, sessionCerts) if err != nil { rc.RespondWithError(err) @@ -215,14 +217,14 @@ func (ro *AuthRouter) authMfa(ae *env.AppEnv, rc *response.RequestContext, mfaCo return } - ok, _ := ae.Managers.Mfa.Verify(mfa, *mfaCode.Code) + ok, _ := ae.Managers.Mfa.Verify(mfa, *mfaCode.Code, rc.NewChangeContext()) if !ok { rc.RespondWithError(apierror.NewInvalidMfaTokenError()) return } - if err := ae.Managers.ApiSession.MfaCompleted(rc.ApiSession); err != nil { + if err := ae.Managers.ApiSession.MfaCompleted(rc.ApiSession, rc.NewChangeContext()); err != nil { rc.RespondWithError(err) return } diff --git a/controller/internal/routes/authenticator_api_model.go b/controller/internal/routes/authenticator_api_model.go index 94c44e0f0..c49ac2e93 100644 --- a/controller/internal/routes/authenticator_api_model.go +++ b/controller/internal/routes/authenticator_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -142,25 +140,8 @@ func MapPatchAuthenticatorToModel(id string, in *rest_model.AuthenticatorPatch) return result } -func MapAuthenticatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - i, ok := e.(*model.Authenticator) - - if !ok { - err := fmt.Errorf("entity is not an authenticator \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - al, err := MapAuthenticatorToRestModel(ae, i) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return al, nil +func MapAuthenticatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e *model.Authenticator) (interface{}, error) { + return MapAuthenticatorToRestModel(ae, e) } func MapAuthenticatorToRestModel(ae *env.AppEnv, i *model.Authenticator) (*rest_model.AuthenticatorDetail, error) { @@ -191,7 +172,7 @@ func MapAuthenticatorToRestModel(ae *env.AppEnv, i *model.Authenticator) (*rest_ return result, nil } -func MapAuthenticatorsToRestEntities(ae *env.AppEnv, rc *response.RequestContext, es []*model.Authenticator) ([]*rest_model.AuthenticatorDetail, error) { +func MapAuthenticatorsToRestEntities(ae *env.AppEnv, _ *response.RequestContext, es []*model.Authenticator) ([]*rest_model.AuthenticatorDetail, error) { apiEntities := make([]*rest_model.AuthenticatorDetail, 0) for _, e := range es { diff --git a/controller/internal/routes/authenticator_router.go b/controller/internal/routes/authenticator_router.go index 724ab5615..ad07c8653 100644 --- a/controller/internal/routes/authenticator_router.go +++ b/controller/internal/routes/authenticator_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/authenticator" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" "github.com/openziti/foundation/v2/errorz" @@ -76,11 +77,11 @@ func (r *AuthenticatorRouter) Register(ae *env.AppEnv) { } func (r *AuthenticatorRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) + ListWithHandler[*model.Authenticator](ae, rc, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) } func (r *AuthenticatorRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) + DetailWithHandler[*model.Authenticator](ae, rc, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) } func (r *AuthenticatorRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params authenticator.CreateAuthenticatorParams) { @@ -91,7 +92,7 @@ func (r *AuthenticatorRouter) Create(ae *env.AppEnv, rc *response.RequestContext return "", err } - return MapCreate(ae.Managers.Authenticator.Create, authenticator) + return MapCreate(ae.Managers.Authenticator.Create, authenticator, rc) }) } @@ -101,7 +102,7 @@ func (r *AuthenticatorRouter) Delete(ae *env.AppEnv, rc *response.RequestContext func (r *AuthenticatorRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params authenticator.UpdateAuthenticatorParams) { Update(rc, func(id string) error { - return ae.Managers.Authenticator.Update(MapUpdateAuthenticatorToModel(params.ID, params.Authenticator), false, nil) + return ae.Managers.Authenticator.Update(MapUpdateAuthenticatorToModel(params.ID, params.Authenticator), false, nil, rc.NewChangeContext()) }) } @@ -113,7 +114,7 @@ func (r *AuthenticatorRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, fields.AddField("salt") } - return ae.Managers.Authenticator.Update(model, false, fields.FilterMaps("tags")) + return ae.Managers.Authenticator.Update(model, false, fields.FilterMaps("tags"), rc.NewChangeContext()) }) } @@ -130,7 +131,7 @@ func (r *AuthenticatorRouter) ReEnroll(ae *env.AppEnv, rc *response.RequestConte return } - if id, err := ae.Managers.Authenticator.ReEnroll(id, time.Time(*params.ReEnroll.ExpiresAt)); err == nil { + if id, err := ae.Managers.Authenticator.ReEnroll(id, time.Time(*params.ReEnroll.ExpiresAt), rc.NewChangeContext()); err == nil { rc.RespondWithCreatedId(id, EnrollmentLinkFactory.SelfLinkFromId(id)) } else { if fe, ok := err.(*errorz.FieldError); ok { diff --git a/controller/internal/routes/base_router.go b/controller/internal/routes/base_router.go index 10744c7b8..5d465983f 100644 --- a/controller/internal/routes/base_router.go +++ b/controller/internal/routes/base_router.go @@ -22,15 +22,19 @@ import ( "github.com/openziti/edge-api/rest_model" edgeApiError "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/env" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/api" "github.com/openziti/fabric/controller/apierror" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" + "github.com/pkg/errors" + "go.etcd.io/bbolt" "net/http" "reflect" "strings" @@ -40,13 +44,19 @@ const ( EntityNameSelf = "self" ) -func modelToApi(ae *env.AppEnv, rc *response.RequestContext, mapper ModelToApiMapper, es []models.Entity) ([]interface{}, error) { +func modelToApi[E models.Entity](ae *env.AppEnv, rc *response.RequestContext, mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error), es []E) ([]interface{}, error) { apiEntities := make([]interface{}, 0) for _, e := range es { al, err := mapper(ae, rc, e) if err != nil { + pfxlog.Logger(). + WithError(err). + WithField("entityId", e.GetId()). + WithField("entityType", reflect.TypeOf(e).String()). + Error("could not convert to API entity") + err = errors.Wrapf(err, "could not convert %T with id [%v] to API entity", e, e.GetId()) return nil, err } @@ -56,13 +66,16 @@ func modelToApi(ae *env.AppEnv, rc *response.RequestContext, mapper ModelToApiMa return apiEntities, nil } -func ListWithHandler(ae *env.AppEnv, rc *response.RequestContext, lister models.EntityRetriever[models.Entity], mapper ModelToApiMapper) { +func ListWithHandler[E models.Entity](ae *env.AppEnv, rc *response.RequestContext, lister models.EntityRetriever[E], + mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error)) { ListWithQueryF(ae, rc, lister, mapper, lister.BasePreparedList) } -type queryF func(query ast.Query) (*models.EntityListResult[models.Entity], error) - -func ListWithQueryF(ae *env.AppEnv, rc *response.RequestContext, lister models.EntityRetriever[models.Entity], mapper ModelToApiMapper, qf queryF) { +func ListWithQueryF[E models.Entity](ae *env.AppEnv, + rc *response.RequestContext, + lister models.EntityRetriever[E], + mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error), + qf func(query ast.Query) (*models.EntityListResult[E], error)) { ListWithQueryFAndCollector(ae, rc, lister, mapper, defaultToListEnvelope, qf) } @@ -76,11 +89,16 @@ func defaultToListEnvelope(data []interface{}, meta *rest_model.Meta) interface{ type ApiListEnvelopeFactory func(data []interface{}, meta *rest_model.Meta) interface{} type ApiEntityEnvelopeFactory func(data interface{}, meta *rest_model.Meta) interface{} -func ListWithQueryFAndCollector(ae *env.AppEnv, rc *response.RequestContext, lister models.EntityRetriever[models.Entity], mapper ModelToApiMapper, toEnvelope ApiListEnvelopeFactory, qf queryF) { +func ListWithQueryFAndCollector[E models.Entity](ae *env.AppEnv, + rc *response.RequestContext, + lister models.EntityRetriever[E], + mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error), + toEnvelope ApiListEnvelopeFactory, + qf func(query ast.Query) (*models.EntityListResult[E], error)) { ListWithEnvelopeFactory(rc, toEnvelope, func(rc *response.RequestContext, queryOptions *PublicQueryOptions) (*QueryResult, error) { // validate that the submitted query is only using public symbols. The query options may contain an final // query which has been modified with additional filters - query, err := queryOptions.getFullQuery(lister.GetStore()) + query, err := queryOptions.getFullQuery(lister.GetListStore()) if err != nil { return nil, err } @@ -196,7 +214,8 @@ func CreateWithResponder(rc *response.RequestContext, rsp response.Responder, li rsp.RespondWithCreatedId(id, linkFactory.SelfLinkFromId(id)) } -func DetailWithHandler(ae *env.AppEnv, rc *response.RequestContext, loader models.EntityRetriever[models.Entity], mapper ModelToApiMapper) { +func DetailWithHandler[E models.Entity](ae *env.AppEnv, rc *response.RequestContext, loader models.EntityRetriever[E], + mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error)) { Detail(rc, func(rc *response.RequestContext, id string) (interface{}, error) { entity, err := loader.BaseLoad(id) if err != nil { @@ -236,12 +255,12 @@ func Detail(rc *response.RequestContext, f ModelDetailF) { type ModelDeleteF func(rc *response.RequestContext, id string) error type DeleteHandler interface { - Delete(id string) error + Delete(id string, ctx *change.Context) error } func DeleteWithHandler(rc *response.RequestContext, deleteHandler DeleteHandler) { Delete(rc, func(rc *response.RequestContext, id string) error { - return deleteHandler.Delete(id) + return deleteHandler.Delete(id, rc.NewChangeContext()) }) } @@ -397,9 +416,19 @@ func listWithId(rc *response.RequestContext, f func(id string) ([]interface{}, e // type ListAssocF func(string, func(models.Entity)) error type listAssocF func(rc *response.RequestContext, id string, queryOptions *PublicQueryOptions) (*QueryResult, error) -func ListAssociationsWithFilter(ae *env.AppEnv, rc *response.RequestContext, filterTemplate string, entityController models.EntityRetriever[models.Entity], mapper ModelToApiMapper) { +type AssociationLister[E models.Entity] interface { + GetListStore() boltz.Store + BasePreparedList(query ast.Query) (*models.EntityListResult[E], error) + BaseLoadInTx(tx *bbolt.Tx, id string) (E, error) +} + +func ListAssociationsWithFilter[E models.Entity](ae *env.AppEnv, + rc *response.RequestContext, + filterTemplate string, + entityController AssociationLister[E], + mapper func(*env.AppEnv, *response.RequestContext, E) (interface{}, error)) { ListAssociations(rc, func(rc *response.RequestContext, id string, queryOptions *PublicQueryOptions) (*QueryResult, error) { - query, err := queryOptions.getFullQuery(entityController.GetStore()) + query, err := queryOptions.getFullQuery(entityController.GetListStore()) if err != nil { return nil, err } @@ -409,7 +438,7 @@ func ListAssociationsWithFilter(ae *env.AppEnv, rc *response.RequestContext, fil filter = fmt.Sprintf(filterTemplate, id) } - filterQuery, err := ast.Parse(entityController.GetStore(), filter) + filterQuery, err := ast.Parse(entityController.GetListStore(), filter) if err != nil { return nil, err } @@ -430,19 +459,23 @@ func ListAssociationsWithFilter(ae *env.AppEnv, rc *response.RequestContext, fil }) } -func ListAssociationWithHandler(ae *env.AppEnv, rc *response.RequestContext, lister models.EntityRetriever[models.Entity], associationLoader models.EntityRetriever[models.Entity], mapper ModelToApiMapper) { +func ListAssociationWithHandler[E models.Entity, A models.Entity](ae *env.AppEnv, + rc *response.RequestContext, + lister models.EntityRetriever[E], + associationLoader AssociationLister[A], + mapper func(*env.AppEnv, *response.RequestContext, A) (interface{}, error)) { ListAssociations(rc, func(rc *response.RequestContext, id string, queryOptions *PublicQueryOptions) (*QueryResult, error) { // validate that the submitted query is only using public symbols. The query options may contain an final // query which has been modified with additional filters - query, err := queryOptions.getFullQuery(associationLoader.GetStore()) + query, err := queryOptions.getFullQuery(associationLoader.GetListStore()) if err != nil { return nil, err } - result := models.EntityListResult[models.Entity]{ + result := models.EntityListResult[A]{ Loader: associationLoader, } - err = lister.PreparedListAssociatedWithHandler(id, associationLoader.GetStore().GetEntityType(), query, result.Collect) + err = lister.PreparedListAssociatedWithHandler(id, associationLoader.GetListStore().GetEntityType(), query, result.Collect) if err != nil { return nil, err } @@ -457,9 +490,9 @@ func ListAssociationWithHandler(ae *env.AppEnv, rc *response.RequestContext, lis } func ListTerminatorAssociations(ae *env.AppEnv, rc *response.RequestContext, - lister models.EntityRetriever[models.Entity], + lister models.EntityRetriever[*model.Service], associationLoader *network.TerminatorManager, - mapper ModelToApiMapper) { + mapper func(ae *env.AppEnv, _ *response.RequestContext, terminator *network.Terminator) (interface{}, error)) { ListAssociations(rc, func(rc *response.RequestContext, id string, queryOptions *PublicQueryOptions) (*QueryResult, error) { // validate that the submitted query is only using public symbols. The query options may contain an final // query which has been modified with additional filters @@ -539,8 +572,8 @@ func ListAssociations(rc *response.RequestContext, listF listAssocF) { rc.RespondWithOk(result.Result, meta) } -func MapCreate[T models.Entity](f func(T) error, entity T) (string, error) { - err := f(entity) +func MapCreate[T models.Entity](f func(T, *change.Context) error, entity T, rc *response.RequestContext) (string, error) { + err := f(entity, rc.NewChangeContext()) if err != nil { return "", err } diff --git a/controller/internal/routes/ca_api_model.go b/controller/internal/routes/ca_api_model.go index 5848ad206..0fcd73e2b 100644 --- a/controller/internal/routes/ca_api_model.go +++ b/controller/internal/routes/ca_api_model.go @@ -17,10 +17,8 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" "github.com/google/uuid" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -144,25 +142,8 @@ func MapPatchCaToModel(id string, ca *rest_model.CaPatch) *model.Ca { return ret } -func MapCaToRestEntity(_ *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - i, ok := e.(*model.Ca) - - if !ok { - err := fmt.Errorf("entity is not a CA \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - al, err := MapCaToRestModel(i) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return al, nil +func MapCaToRestEntity(_ *env.AppEnv, _ *response.RequestContext, e *model.Ca) (interface{}, error) { + return MapCaToRestModel(e) } func MapCaToRestModel(i *model.Ca) (*rest_model.CaDetail, error) { diff --git a/controller/internal/routes/ca_router.go b/controller/internal/routes/ca_router.go index e5d389cf5..2d364e192 100644 --- a/controller/internal/routes/ca_router.go +++ b/controller/internal/routes/ca_router.go @@ -27,6 +27,7 @@ import ( "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" "github.com/openziti/sdk-golang/ziti/config" @@ -90,16 +91,16 @@ func (r *CaRouter) Register(ae *env.AppEnv) { } func (r *CaRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.Ca, MapCaToRestEntity) + ListWithHandler[*model.Ca](ae, rc, ae.Managers.Ca, MapCaToRestEntity) } func (r *CaRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.Ca, MapCaToRestEntity) + DetailWithHandler[*model.Ca](ae, rc, ae.Managers.Ca, MapCaToRestEntity) } func (r *CaRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params certificate_authority.CreateCaParams) { Create(rc, rc, CaLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.Ca.Create, MapCreateCaToModel(params.Ca)) + return MapCreate(ae.Managers.Ca.Create, MapCreateCaToModel(params.Ca), rc) }) } @@ -109,13 +110,13 @@ func (r *CaRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *CaRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params certificate_authority.UpdateCaParams) { Update(rc, func(id string) error { - return ae.Managers.Ca.Update(MapUpdateCaToModel(params.ID, params.Ca), nil) + return ae.Managers.Ca.Update(MapUpdateCaToModel(params.ID, params.Ca), nil, rc.NewChangeContext()) }) } func (r *CaRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params certificate_authority.PatchCaParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.Ca.Update(MapPatchCaToModel(params.ID, params.Ca), fields.FilterMaps("tags")) + return ae.Managers.Ca.Update(MapPatchCaToModel(params.ID, params.Ca), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } @@ -219,7 +220,7 @@ func (r *CaRouter) VerifyCert(ae *env.AppEnv, rc *response.RequestContext, param return } - err = ae.Managers.Ca.Verified(ca) + err = ae.Managers.Ca.Verified(ca, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) diff --git a/controller/internal/routes/config_api_model.go b/controller/internal/routes/config_api_model.go index 085d9ed3f..ada0fd21f 100644 --- a/controller/internal/routes/config_api_model.go +++ b/controller/internal/routes/config_api_model.go @@ -18,7 +18,6 @@ package routes import ( "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -98,25 +97,8 @@ func MapPatchConfigToModel(id string, config *rest_model.ConfigPatch) (*model.Co return ret, nil } -func MapConfigToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - config, ok := e.(*model.Config) - - if !ok { - err := fmt.Errorf("entity is not a Config \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - al, err := MapConfigToRestModel(ae, config) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return al, nil +func MapConfigToRestEntity(ae *env.AppEnv, _ *response.RequestContext, config *model.Config) (interface{}, error) { + return MapConfigToRestModel(ae, config) } func MapConfigToRestModel(ae *env.AppEnv, config *model.Config) (*rest_model.ConfigDetail, error) { diff --git a/controller/internal/routes/config_router.go b/controller/internal/routes/config_router.go index 861911ff0..660680e20 100644 --- a/controller/internal/routes/config_router.go +++ b/controller/internal/routes/config_router.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/config" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -68,11 +69,11 @@ func (r *ConfigRouter) Register(ae *env.AppEnv) { } func (r *ConfigRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.Config, MapConfigToRestEntity) + ListWithHandler[*model.Config](ae, rc, ae.Managers.Config, MapConfigToRestEntity) } func (r *ConfigRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.Config, MapConfigToRestEntity) + DetailWithHandler[*model.Config](ae, rc, ae.Managers.Config, MapConfigToRestEntity) } func (r *ConfigRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params config.CreateConfigParams) { @@ -86,7 +87,7 @@ func (r *ConfigRouter) Create(ae *env.AppEnv, rc *response.RequestContext, param if err != nil { return "", err } - return MapCreate(ae.Managers.Config.Create, entity) + return MapCreate(ae.Managers.Config.Create, entity, rc) }) } @@ -107,7 +108,7 @@ func (r *ConfigRouter) Update(ae *env.AppEnv, rc *response.RequestContext, param return err } - return ae.Managers.Config.Update(model, nil) + return ae.Managers.Config.Update(model, nil, rc.NewChangeContext()) }) } @@ -118,6 +119,6 @@ func (r *ConfigRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params if err != nil { return err } - return ae.Managers.Config.Update(model, fields.FilterMaps("tags", "data")) + return ae.Managers.Config.Update(model, fields.FilterMaps("tags", "data"), rc.NewChangeContext()) }) } diff --git a/controller/internal/routes/config_type_api_model.go b/controller/internal/routes/config_type_api_model.go index 7bf1c70a0..c19c48fa7 100644 --- a/controller/internal/routes/config_type_api_model.go +++ b/controller/internal/routes/config_type_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -78,25 +76,8 @@ func MapPatchConfigTypeToModel(id string, configType *rest_model.ConfigTypePatch return ret } -func MapConfigTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - configType, ok := e.(*model.ConfigType) - - if !ok { - err := fmt.Errorf("entity is not a ConfigType \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapConfigTypeToRestModel(configType) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapConfigTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, configType *model.ConfigType) (interface{}, error) { + return MapConfigTypeToRestModel(configType) } func MapConfigTypeToRestModel(configType *model.ConfigType) (*rest_model.ConfigTypeDetail, error) { diff --git a/controller/internal/routes/config_type_router.go b/controller/internal/routes/config_type_router.go index caca2779c..fa61543a2 100644 --- a/controller/internal/routes/config_type_router.go +++ b/controller/internal/routes/config_type_router.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/config" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -72,11 +73,11 @@ func (r *ConfigTypeRouter) Register(ae *env.AppEnv) { } func (r *ConfigTypeRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.ConfigType, MapConfigTypeToRestEntity) + ListWithHandler[*model.ConfigType](ae, rc, ae.Managers.ConfigType, MapConfigTypeToRestEntity) } func (r *ConfigTypeRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.ConfigType, MapConfigTypeToRestEntity) + DetailWithHandler[*model.ConfigType](ae, rc, ae.Managers.ConfigType, MapConfigTypeToRestEntity) } func (r *ConfigTypeRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params config.CreateConfigTypeParams) { @@ -88,7 +89,7 @@ func (r *ConfigTypeRouter) Create(ae *env.AppEnv, rc *response.RequestContext, p } Create(rc, rc, ConfigTypeLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.ConfigType.Create, MapCreateConfigTypeToModel(params.ConfigType)) + return MapCreate(ae.Managers.ConfigType.Create, MapCreateConfigTypeToModel(params.ConfigType), rc) }) } @@ -105,7 +106,7 @@ func (r *ConfigTypeRouter) Update(ae *env.AppEnv, rc *response.RequestContext, p } Update(rc, func(id string) error { - return ae.Managers.ConfigType.Update(MapUpdateConfigTypeToModel(params.ID, params.ConfigType), nil) + return ae.Managers.ConfigType.Update(MapUpdateConfigTypeToModel(params.ID, params.ConfigType), nil, rc.NewChangeContext()) }) } @@ -120,10 +121,10 @@ func (r *ConfigTypeRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, pa } Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.ConfigType.Update(MapPatchConfigTypeToModel(params.ID, params.ConfigType), fields.FilterMaps("tags", "schema")) + return ae.Managers.ConfigType.Update(MapPatchConfigTypeToModel(params.ID, params.ConfigType), fields.FilterMaps("tags", "schema"), rc.NewChangeContext()) }) } func (r *ConfigTypeRouter) ListConfigs(ae *env.AppEnv, rc *response.RequestContext, params config.ListConfigsForConfigTypeParams) { - ListAssociationWithHandler(ae, rc, ae.Managers.ConfigType, ae.Managers.Config, MapConfigToRestEntity) + ListAssociationWithHandler[*model.ConfigType, *model.Config](ae, rc, ae.Managers.ConfigType, ae.Managers.Config, MapConfigToRestEntity) } diff --git a/controller/internal/routes/current_api_session_api_model.go b/controller/internal/routes/current_api_session_api_model.go index e80d81edf..fa05ceb7d 100644 --- a/controller/internal/routes/current_api_session_api_model.go +++ b/controller/internal/routes/current_api_session_api_model.go @@ -17,7 +17,6 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" @@ -79,25 +78,8 @@ func MapToCurrentApiSessionRestModel(ae *env.AppEnv, apiSession *model.ApiSessio return ret } -func MapApiSessionCertificateToRestEntity(appEnv *env.AppEnv, context *response.RequestContext, e models.Entity) (interface{}, error) { - i, ok := e.(*model.ApiSessionCertificate) - - if !ok { - err := fmt.Errorf("entity is not an API Session Certificate \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - al, err := MapApiSessionCertificateToRestModel(i) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return al, nil +func MapApiSessionCertificateToRestEntity(appEnv *env.AppEnv, context *response.RequestContext, i *model.ApiSessionCertificate) (interface{}, error) { + return MapApiSessionCertificateToRestModel(i) } func MapApiSessionCertificateToRestModel(apiSessionCert *model.ApiSessionCertificate) (*rest_model.CurrentAPISessionCertificateDetail, error) { diff --git a/controller/internal/routes/current_api_session_router.go b/controller/internal/routes/current_api_session_router.go index 67675ae3c..ff30f4571 100644 --- a/controller/internal/routes/current_api_session_router.go +++ b/controller/internal/routes/current_api_session_router.go @@ -108,7 +108,7 @@ func (router *CurrentSessionRouter) Detail(ae *env.AppEnv, rc *response.RequestC } func (router *CurrentSessionRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { - err := ae.GetManagers().ApiSession.Delete(rc.ApiSession.Id) + err := ae.GetManagers().ApiSession.Delete(rc.ApiSession.Id, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -142,7 +142,7 @@ func (router *CurrentSessionRouter) ListCertificates(ae *env.AppEnv, rc *respons func (router *CurrentSessionRouter) CreateCertificate(ae *env.AppEnv, rc *response.RequestContext, params clientCurrentApiSession.CreateCurrentAPISessionCertificateParams) { responder := &ApiSessionCertificateCreateResponder{ae: ae, Responder: rc} CreateWithResponder(rc, responder, CurrentApiSessionCertificateLinkFactory, func() (string, error) { - return ae.GetManagers().ApiSessionCertificate.CreateFromCSR(rc.ApiSession.Id, 12*time.Hour, []byte(*params.SessionCertificate.Csr)) + return ae.GetManagers().ApiSessionCertificate.CreateFromCSR(rc.ApiSession.Id, 12*time.Hour, []byte(*params.SessionCertificate.Csr), rc.NewChangeContext()) }) } @@ -184,7 +184,7 @@ func (router *CurrentSessionRouter) DeleteCertificate(ae *env.AppEnv, rc *respon return } - if err := ae.GetManagers().ApiSessionCertificate.Delete(certId); err != nil { + if err := ae.GetManagers().ApiSessionCertificate.Delete(certId, rc.NewChangeContext()); err != nil { rc.RespondWithError(err) return } diff --git a/controller/internal/routes/current_identity_api_model.go b/controller/internal/routes/current_identity_api_model.go index 9d46e8441..b2b9c324f 100644 --- a/controller/internal/routes/current_identity_api_model.go +++ b/controller/internal/routes/current_identity_api_model.go @@ -139,25 +139,8 @@ func MapMfaToRestModel(ae *env.AppEnv, mfa *model.Mfa) (*rest_model.DetailMfa, e return result, nil } -func MapCurrentIdentityEdgeRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - router, ok := e.(*model.EdgeRouter) - - if !ok { - err := fmt.Errorf("entity is not a EdgeRouter \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapCurrentIdentityEdgeRouterToRestModel(ae, router) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapCurrentIdentityEdgeRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, router *model.EdgeRouter) (interface{}, error) { + return MapCurrentIdentityEdgeRouterToRestModel(ae, router) } func MapCurrentIdentityEdgeRouterToRestModel(ae *env.AppEnv, router *model.EdgeRouter) (*rest_model.CurrentIdentityEdgeRouterDetail, error) { diff --git a/controller/internal/routes/current_identity_authenticator_router.go b/controller/internal/routes/current_identity_authenticator_router.go index adf30cc58..c175bf851 100644 --- a/controller/internal/routes/current_identity_authenticator_router.go +++ b/controller/internal/routes/current_identity_authenticator_router.go @@ -113,12 +113,12 @@ func (r *CurrentIdentityAuthenticatorRouter) List(ae *env.AppEnv, rc *response.R return nil, err } - apiAuthenticators, err := MapAuthenticatorsToRestEntities(ae, rc, result.Authenticators) + apiAuthenticators, err := MapAuthenticatorsToRestEntities(ae, rc, result.Entities) if err != nil { return nil, err } for i, authenticator := range apiAuthenticators { - authenticator.Links = CurrentIdentityAuthenticatorLinkFactory.Links(result.Authenticators[i]) + authenticator.Links = CurrentIdentityAuthenticatorLinkFactory.Links(result.Entities[i]) } return NewQueryResult(apiAuthenticators, result.GetMetaData()), nil @@ -150,13 +150,13 @@ func (r *CurrentIdentityAuthenticatorRouter) Detail(ae *env.AppEnv, rc *response func (r *CurrentIdentityAuthenticatorRouter) Update(ae *env.AppEnv, rc *response.RequestContext, authenticator *rest_model.AuthenticatorUpdateWithCurrent) { Update(rc, func(id string) error { - return ae.Managers.Authenticator.UpdateSelf(MapUpdateAuthenticatorWithCurrentToModel(id, rc.Identity.Id, authenticator)) + return ae.Managers.Authenticator.UpdateSelf(MapUpdateAuthenticatorWithCurrentToModel(id, rc.Identity.Id, authenticator), rc.NewChangeContext()) }) } func (r *CurrentIdentityAuthenticatorRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, authenticator *rest_model.AuthenticatorPatchWithCurrent) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.Authenticator.PatchSelf(MapPatchAuthenticatorWithCurrentToModel(id, rc.Identity.Id, authenticator), fields.FilterMaps("tags")) + return ae.Managers.Authenticator.PatchSelf(MapPatchAuthenticatorWithCurrentToModel(id, rc.Identity.Id, authenticator), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } @@ -206,7 +206,7 @@ func (r *CurrentIdentityAuthenticatorRouter) Extend(ae *env.AppEnv, rc *response return } - certPem, err := ae.Managers.Authenticator.ExtendCertForIdentity(rc.Identity.Id, authId, peerCerts, *extend.ClientCertCsr) + certPem, err := ae.Managers.Authenticator.ExtendCertForIdentity(rc.Identity.Id, authId, peerCerts, *extend.ClientCertCsr, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -226,7 +226,7 @@ func (r *CurrentIdentityAuthenticatorRouter) ExtendVerify(ae *env.AppEnv, rc *re return } - err = ae.Managers.Authenticator.VerifyExtendCertForIdentity(rc.ApiSession.Id, rc.Identity.Id, authId, *extend.ClientCert) + err = ae.Managers.Authenticator.VerifyExtendCertForIdentity(rc.ApiSession.Id, rc.Identity.Id, authId, *extend.ClientCert, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) diff --git a/controller/internal/routes/current_identity_router.go b/controller/internal/routes/current_identity_router.go index 20db9af13..616ac9832 100644 --- a/controller/internal/routes/current_identity_router.go +++ b/controller/internal/routes/current_identity_router.go @@ -25,6 +25,7 @@ import ( "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/controller/response" "github.com/openziti/foundation/v2/errorz" @@ -164,8 +165,9 @@ func (r *CurrentIdentityRouter) verifyMfa(ae *env.AppEnv, rc *response.RequestCo } if ok { + changeCtx := rc.NewChangeContext() mfa.IsVerified = true - if err := ae.Managers.Mfa.Update(mfa, nil); err != nil { + if err := ae.Managers.Mfa.Update(mfa, nil, changeCtx); err != nil { pfxlog.Logger().Errorf("could not update MFA with new MFA status: %v", err) rc.RespondWithApiError(errorz.NewUnhandled(errors.New("could not update MFA status"))) return @@ -174,7 +176,7 @@ func (r *CurrentIdentityRouter) verifyMfa(ae *env.AppEnv, rc *response.RequestCo rc.ApiSession.MfaComplete = true rc.ApiSession.MfaRequired = true - if err := ae.Managers.ApiSession.UpdateWithFieldChecker(rc.ApiSession, boltz.MapFieldChecker{persistence.FieldApiSessionMfaComplete: struct{}{}, persistence.FieldApiSessionMfaRequired: struct{}{}}); err != nil { + if err := ae.Managers.ApiSession.UpdateWithFieldChecker(rc.ApiSession, boltz.MapFieldChecker{persistence.FieldApiSessionMfaComplete: struct{}{}, persistence.FieldApiSessionMfaRequired: struct{}{}}, changeCtx); err != nil { pfxlog.Logger().Errorf("could not update API Session with new MFA status: %v", err) } @@ -189,7 +191,7 @@ func (r *CurrentIdentityRouter) verifyMfa(ae *env.AppEnv, rc *response.RequestCo } func (r *CurrentIdentityRouter) createMfa(ae *env.AppEnv, rc *response.RequestContext) { - id, err := ae.Managers.Mfa.CreateForIdentity(rc.Identity) + id, err := ae.Managers.Mfa.CreateForIdentity(rc.Identity, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -227,7 +229,7 @@ func (r *CurrentIdentityRouter) removeMfa(ae *env.AppEnv, rc *response.RequestCo code = *mfaCodeHeader } - err := ae.Managers.Mfa.DeleteForIdentity(rc.Identity, code) + err := ae.Managers.Mfa.DeleteForIdentity(rc.Identity, code, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -287,14 +289,15 @@ func (r *CurrentIdentityRouter) createMfaRecoveryCodes(ae *env.AppEnv, rc *respo return } - ok, _ := ae.Managers.Mfa.Verify(mfa, *body.Code) + changeCtx := rc.NewChangeContext() + ok, _ := ae.Managers.Mfa.Verify(mfa, *body.Code, changeCtx) if !ok { rc.RespondWithError(apierror.NewInvalidMfaTokenError()) return } - if err := ae.Managers.Mfa.RecreateRecoveryCodes(mfa); err != nil { + if err := ae.Managers.Mfa.RecreateRecoveryCodes(mfa, changeCtx); err != nil { rc.RespondWithError(err) return } @@ -352,11 +355,11 @@ func (r *CurrentIdentityRouter) listEdgeRouters(ae *env.AppEnv, rc *response.Req if rc.Identity.IsAdmin { filterTemplate := `isVerified = true` rc.SetEntityId(rc.Identity.Id) - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapCurrentIdentityEdgeRouterToRestEntity) + ListAssociationsWithFilter[*model.EdgeRouter](ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapCurrentIdentityEdgeRouterToRestEntity) } else { filterTemplate := `isVerified = true and not isEmpty(from edgeRouterPolicies where anyOf(identities) = "%v")` rc.SetEntityId(rc.Identity.Id) - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapCurrentIdentityEdgeRouterToRestEntity) + ListAssociationsWithFilter[*model.EdgeRouter](ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapCurrentIdentityEdgeRouterToRestEntity) } } diff --git a/controller/internal/routes/database_router.go b/controller/internal/routes/database_router.go index a3a2100ac..12bf7e2f6 100644 --- a/controller/internal/routes/database_router.go +++ b/controller/internal/routes/database_router.go @@ -91,7 +91,7 @@ func (r *DatabaseRouter) CreateSnapshot(ae *env.AppEnv, rc *response.RequestCont func (r *DatabaseRouter) CheckDatastoreIntegrity(ae *env.AppEnv, rc *response.RequestContext, fixErrors bool) { if r.integrityCheck.running.CompareAndSwap(false, true) { r.integrityCheck.fixingErrors = fixErrors - go r.runDataIntegrityCheck(ae, fixErrors) + go r.runDataIntegrityCheck(ae, rc, fixErrors) rc.Respond(&rest_model.Empty{Data: map[string]interface{}{}, Meta: &rest_model.Meta{}}, http.StatusAccepted) } else { rc.RespondWithApiError(apierror.NewRateLimited()) @@ -139,7 +139,7 @@ func (r *DatabaseRouter) GetCheckProgress(rc *response.RequestContext) { rc.Respond(result, http.StatusOK) } -func (r *DatabaseRouter) runDataIntegrityCheck(ae *env.AppEnv, fixErrors bool) { +func (r *DatabaseRouter) runDataIntegrityCheck(ae *env.AppEnv, rc *response.RequestContext, fixErrors bool) { defer func() { r.integrityCheck.lock.Lock() now := time.Now() @@ -176,5 +176,5 @@ func (r *DatabaseRouter) runDataIntegrityCheck(ae *env.AppEnv, fixErrors bool) { } } - r.integrityCheck.err = ae.GetDbProvider().GetStores().CheckIntegrity(ae.GetDbProvider().GetDb(), fixErrors, errorHandler) + r.integrityCheck.err = ae.GetDbProvider().GetStores().CheckIntegrity(ae.GetDbProvider().GetDb(), rc.NewChangeContext().GetContext(), fixErrors, errorHandler) } diff --git a/controller/internal/routes/edge_router_api_model.go b/controller/internal/routes/edge_router_api_model.go index b702591c2..7a7573269 100644 --- a/controller/internal/routes/edge_router_api_model.go +++ b/controller/internal/routes/edge_router_api_model.go @@ -17,7 +17,6 @@ package routes import ( - "fmt" "github.com/openziti/foundation/v2/versions" "strings" @@ -107,25 +106,8 @@ func MapPatchEdgeRouterToModel(id string, router *rest_model.EdgeRouterPatch) *m return ret } -func MapEdgeRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - router, ok := e.(*model.EdgeRouter) - - if !ok { - err := fmt.Errorf("entity is not a EdgeRouter \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapEdgeRouterToRestModel(ae, router) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapEdgeRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, router *model.EdgeRouter) (interface{}, error) { + return MapEdgeRouterToRestModel(ae, router) } func MapVersionInfoToRestModel(versionInfo versions.VersionInfo) *rest_model.VersionInfo { diff --git a/controller/internal/routes/edge_router_policy_api_model.go b/controller/internal/routes/edge_router_policy_api_model.go index 28d45b58b..33551c7fb 100644 --- a/controller/internal/routes/edge_router_policy_api_model.go +++ b/controller/internal/routes/edge_router_policy_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -102,25 +100,8 @@ func MapPatchEdgeRouterPolicyToModel(id string, policy *rest_model.EdgeRouterPol return ret } -func MapEdgeRouterPolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - policy, ok := e.(*model.EdgeRouterPolicy) - - if !ok { - err := fmt.Errorf("entity is not a EdgeRouterPolicy \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapEdgeRouterPolicyToRestModel(ae, policy) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapEdgeRouterPolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, policy *model.EdgeRouterPolicy) (interface{}, error) { + return MapEdgeRouterPolicyToRestModel(ae, policy) } func MapEdgeRouterPolicyToRestModel(ae *env.AppEnv, policy *model.EdgeRouterPolicy) (*rest_model.EdgeRouterPolicyDetail, error) { diff --git a/controller/internal/routes/edge_router_policy_router.go b/controller/internal/routes/edge_router_policy_router.go index adf2ee71c..6858a9abf 100644 --- a/controller/internal/routes/edge_router_policy_router.go +++ b/controller/internal/routes/edge_router_policy_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/edge_router_policy" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -77,16 +78,16 @@ func (r *EdgeRouterPolicyRouter) Register(ae *env.AppEnv) { } func (r *EdgeRouterPolicyRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) + ListWithHandler[*model.EdgeRouterPolicy](ae, rc, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) } func (r *EdgeRouterPolicyRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) + DetailWithHandler[*model.EdgeRouterPolicy](ae, rc, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) } func (r *EdgeRouterPolicyRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params edge_router_policy.CreateEdgeRouterPolicyParams) { Create(rc, rc, EdgeRouterPolicyLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.EdgeRouterPolicy.Create, MapCreateEdgeRouterPolicyToModel(params.Policy)) + return MapCreate(ae.Managers.EdgeRouterPolicy.Create, MapCreateEdgeRouterPolicyToModel(params.Policy), rc) }) } @@ -96,20 +97,20 @@ func (r *EdgeRouterPolicyRouter) Delete(ae *env.AppEnv, rc *response.RequestCont func (r *EdgeRouterPolicyRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params edge_router_policy.UpdateEdgeRouterPolicyParams) { Update(rc, func(id string) error { - return ae.Managers.EdgeRouterPolicy.Update(MapUpdateEdgeRouterPolicyToModel(params.ID, params.Policy), nil) + return ae.Managers.EdgeRouterPolicy.Update(MapUpdateEdgeRouterPolicyToModel(params.ID, params.Policy), nil, rc.NewChangeContext()) }) } func (r *EdgeRouterPolicyRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params edge_router_policy.PatchEdgeRouterPolicyParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.EdgeRouterPolicy.Update(MapPatchEdgeRouterPolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags")) + return ae.Managers.EdgeRouterPolicy.Update(MapPatchEdgeRouterPolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } func (r *EdgeRouterPolicyRouter) ListEdgeRouters(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.EdgeRouterPolicy, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + ListAssociationWithHandler[*model.EdgeRouterPolicy, *model.EdgeRouter](ae, rc, ae.Managers.EdgeRouterPolicy, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } func (r *EdgeRouterPolicyRouter) ListIdentities(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.EdgeRouterPolicy, ae.Managers.Identity, MapIdentityToRestEntity) + ListAssociationWithHandler[*model.EdgeRouterPolicy, *model.Identity](ae, rc, ae.Managers.EdgeRouterPolicy, ae.Managers.Identity, MapIdentityToRestEntity) } diff --git a/controller/internal/routes/edge_router_router.go b/controller/internal/routes/edge_router_router.go index a2740c8ef..bede3a6a1 100644 --- a/controller/internal/routes/edge_router_router.go +++ b/controller/internal/routes/edge_router_router.go @@ -98,7 +98,7 @@ func (r *EdgeRouterRouter) List(ae *env.AppEnv, rc *response.RequestContext) { roleSemantic := rc.Request.URL.Query().Get("roleSemantic") if len(roleFilters) > 0 { - ListWithQueryF(ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity, func(query ast.Query) (*models.EntityListResult[models.Entity], error) { + ListWithQueryF[*model.EdgeRouter](ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity, func(query ast.Query) (*models.EntityListResult[*model.EdgeRouter], error) { cursorProvider, err := ae.GetStores().EdgeRouter.GetRoleAttributesCursorProvider(roleFilters, roleSemantic) if err != nil { return nil, err @@ -106,17 +106,17 @@ func (r *EdgeRouterRouter) List(ae *env.AppEnv, rc *response.RequestContext) { return ae.Managers.EdgeRouter.BasePreparedListIndexed(cursorProvider, query) }) } else { - ListWithHandler(ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + ListWithHandler[*model.EdgeRouter](ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } } func (r *EdgeRouterRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + DetailWithHandler[*model.EdgeRouter](ae, rc, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } func (r *EdgeRouterRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params edge_router.CreateEdgeRouterParams) { Create(rc, rc, EdgeRouterLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.EdgeRouter.Create, MapCreateEdgeRouterToModel(params.EdgeRouter)) + return MapCreate(ae.Managers.EdgeRouter.Create, MapCreateEdgeRouterToModel(params.EdgeRouter), rc) }) } @@ -126,32 +126,32 @@ func (r *EdgeRouterRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *EdgeRouterRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params edge_router.UpdateEdgeRouterParams) { Update(rc, func(id string) error { - return ae.Managers.EdgeRouter.Update(MapUpdateEdgeRouterToModel(params.ID, params.EdgeRouter), false, nil) + return ae.Managers.EdgeRouter.Update(MapUpdateEdgeRouterToModel(params.ID, params.EdgeRouter), false, nil, rc.NewChangeContext()) }) } func (r *EdgeRouterRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params edge_router.PatchEdgeRouterParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.EdgeRouter.Update(MapPatchEdgeRouterToModel(params.ID, params.EdgeRouter), false, fields.FilterMaps("tags")) + return ae.Managers.EdgeRouter.Update(MapPatchEdgeRouterToModel(params.ID, params.EdgeRouter), false, fields.FilterMaps("tags"), rc.NewChangeContext()) }) } func (r *EdgeRouterRouter) listServiceEdgeRouterPolicies(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.EdgeRouter, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) + ListAssociationWithHandler[*model.EdgeRouter, *model.ServiceEdgeRouterPolicy](ae, rc, ae.Managers.EdgeRouter, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) } func (r *EdgeRouterRouter) listEdgeRouterPolicies(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.EdgeRouter, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) + ListAssociationWithHandler[*model.EdgeRouter, *model.EdgeRouterPolicy](ae, rc, ae.Managers.EdgeRouter, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) } func (r *EdgeRouterRouter) listIdentities(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from edgeRouterPolicies where anyOf(routers) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.Identity, MapIdentityToRestEntity) + ListAssociationsWithFilter[*model.Identity](ae, rc, filterTemplate, ae.Managers.Identity, MapIdentityToRestEntity) } func (r *EdgeRouterRouter) listServices(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from serviceEdgeRouterPolicies where anyOf(routers) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeService, MapServiceToRestEntity) + ListAssociationsWithFilter[*model.ServiceDetail](ae, rc, filterTemplate, ae.Managers.EdgeService.GetDetailLister(), MapServiceToRestEntity) } func (r *EdgeRouterRouter) ReEnroll(ae *env.AppEnv, rc *response.RequestContext) { @@ -170,7 +170,7 @@ func (r *EdgeRouterRouter) ReEnroll(ae *env.AppEnv, rc *response.RequestContext) return } - if err := ae.GetManagers().EdgeRouter.ReEnroll(router); err != nil { + if err := ae.GetManagers().EdgeRouter.ReEnroll(router, rc.NewChangeContext()); err != nil { rc.RespondWithApiError(apierror.NewEdgeRouterFailedReEnrollment(err)) return } diff --git a/controller/internal/routes/enroll_router.go b/controller/internal/routes/enroll_router.go index 96a78d9cf..01d9fe6ee 100644 --- a/controller/internal/routes/enroll_router.go +++ b/controller/internal/routes/enroll_router.go @@ -131,7 +131,7 @@ func (ro *EnrollRouter) getCaCerts(ae *env.AppEnv, rc *response.RequestContext) func (ro *EnrollRouter) enrollHandler(ae *env.AppEnv, rc *response.RequestContext) { enrollContext := &model.EnrollmentContextHttp{} - err := enrollContext.FillFromHttpRequest(rc.Request) + err := enrollContext.FillFromHttpRequest(rc.Request, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -221,8 +221,11 @@ func (ro *EnrollRouter) extendRouterEnrollment(ae *env.AppEnv, rc *response.Requ return } + certCsr := []byte(*params.RouterExtendEnrollmentRequest.CertCsr) + serverCertCsr := []byte(*params.RouterExtendEnrollmentRequest.ServerCertCsr) + if edgeRouter, _ := ae.Managers.EdgeRouter.ReadOneByFingerprint(fingerprint); edgeRouter != nil { - certs, err := ae.Managers.EdgeRouter.ExtendEnrollment(edgeRouter, []byte(*params.RouterExtendEnrollmentRequest.CertCsr), []byte(*params.RouterExtendEnrollmentRequest.ServerCertCsr)) + certs, err := ae.Managers.EdgeRouter.ExtendEnrollment(edgeRouter, certCsr, serverCertCsr, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -251,7 +254,7 @@ func (ro *EnrollRouter) extendRouterEnrollment(ae *env.AppEnv, rc *response.Requ } if router, _ := ae.Managers.TransitRouter.ReadOneByFingerprint(fingerprint); router != nil { - certs, err := ae.Managers.TransitRouter.ExtendEnrollment(router, []byte(*params.RouterExtendEnrollmentRequest.CertCsr), []byte(*params.RouterExtendEnrollmentRequest.ServerCertCsr)) + certs, err := ae.Managers.TransitRouter.ExtendEnrollment(router, certCsr, serverCertCsr, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) diff --git a/controller/internal/routes/enrollment_api_model.go b/controller/internal/routes/enrollment_api_model.go index 398160265..4678c80ab 100644 --- a/controller/internal/routes/enrollment_api_model.go +++ b/controller/internal/routes/enrollment_api_model.go @@ -17,14 +17,11 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" - "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/stringz" ) @@ -32,25 +29,8 @@ const EntityNameEnrollment = "enrollments" var EnrollmentLinkFactory = NewBasicLinkFactory(EntityNameEnrollment) -func MapEnrollmentToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - enrollment, ok := e.(*model.Enrollment) - - if !ok { - err := fmt.Errorf("entity is not a Enrollment \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapEnrollmentToRestModel(ae, enrollment) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapEnrollmentToRestEntity(ae *env.AppEnv, _ *response.RequestContext, enrollment *model.Enrollment) (interface{}, error) { + return MapEnrollmentToRestModel(ae, enrollment) } func MapEnrollmentToRestModel(ae *env.AppEnv, enrollment *model.Enrollment) (*rest_model.EnrollmentDetail, error) { diff --git a/controller/internal/routes/enrollment_router.go b/controller/internal/routes/enrollment_router.go index 76b3e129a..846dceaf8 100644 --- a/controller/internal/routes/enrollment_router.go +++ b/controller/internal/routes/enrollment_router.go @@ -44,7 +44,6 @@ func NewEnrollmentRouter() *EnrollmentRouter { } func (r *EnrollmentRouter) Register(ae *env.AppEnv) { - ae.ManagementApi.EnrollmentDeleteEnrollmentHandler = enrollment.DeleteEnrollmentHandlerFunc(func(params enrollment.DeleteEnrollmentParams, _ interface{}) middleware.Responder { return ae.IsAllowed(r.Delete, params.HTTPRequest, params.ID, "", permissions.IsAdmin()) }) @@ -71,11 +70,11 @@ func (r *EnrollmentRouter) Register(ae *env.AppEnv) { } func (r *EnrollmentRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.Enrollment, MapEnrollmentToRestEntity) + ListWithHandler[*model.Enrollment](ae, rc, ae.Managers.Enrollment, MapEnrollmentToRestEntity) } func (r *EnrollmentRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.Enrollment, MapEnrollmentToRestEntity) + DetailWithHandler[*model.Enrollment](ae, rc, ae.Managers.Enrollment, MapEnrollmentToRestEntity) } func (r *EnrollmentRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { @@ -95,7 +94,7 @@ func (r *EnrollmentRouter) Refresh(ae *env.AppEnv, rc *response.RequestContext, return } - if err := ae.Managers.Enrollment.RefreshJwt(id, time.Time(*params.Refresh.ExpiresAt)); err != nil { + if err := ae.Managers.Enrollment.RefreshJwt(id, time.Time(*params.Refresh.ExpiresAt), rc.NewChangeContext()); err != nil { if fe, ok := err.(*errorz.FieldError); ok { rc.RespondWithFieldError(fe) return @@ -109,7 +108,7 @@ func (r *EnrollmentRouter) Refresh(ae *env.AppEnv, rc *response.RequestContext, func (r *EnrollmentRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params enrollment.CreateEnrollmentParams) { Create(rc, rc, EnrollmentLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.Enrollment.Create, MapCreateEnrollmentToModel(params.Enrollment)) + return MapCreate(ae.Managers.Enrollment.Create, MapCreateEnrollmentToModel(params.Enrollment), rc) }) } diff --git a/controller/internal/routes/external_jwt_signer_api_model.go b/controller/internal/routes/external_jwt_signer_api_model.go index acc7adb27..49ae533a6 100644 --- a/controller/internal/routes/external_jwt_signer_api_model.go +++ b/controller/internal/routes/external_jwt_signer_api_model.go @@ -17,9 +17,7 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -32,19 +30,8 @@ const EntityNameExternalJwtSigner = "external-jwt-signers" var ExternalJwtSignerLinkFactory = NewBasicLinkFactory(EntityNameExternalJwtSigner) -func MapExternalJwtSignerToRestEntity(_ *env.AppEnv, _ *response.RequestContext, ExternalJwtSignerModel models.Entity) (interface{}, error) { - externalJwtSigner, ok := ExternalJwtSignerModel.(*model.ExternalJwtSigner) - - if !ok { - err := fmt.Errorf("entity is not an identity type \"%s\"", ExternalJwtSignerModel.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel := MapExternalJwtSignerToRestModel(externalJwtSigner) - - return restModel, nil +func MapExternalJwtSignerToRestEntity(_ *env.AppEnv, _ *response.RequestContext, externalJwtSigner *model.ExternalJwtSigner) (interface{}, error) { + return MapExternalJwtSignerToRestModel(externalJwtSigner), nil } func MapClientExtJwtSignersToRestEntity(_ *env.AppEnv, _ *response.RequestContext, signers []*model.ExternalJwtSigner) ([]*rest_model.ClientExternalJWTSignerDetail, error) { diff --git a/controller/internal/routes/external_jwt_signer_router.go b/controller/internal/routes/external_jwt_signer_router.go index 75c7543e8..82b0190a1 100644 --- a/controller/internal/routes/external_jwt_signer_router.go +++ b/controller/internal/routes/external_jwt_signer_router.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/external_jwt_signer" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" @@ -44,7 +45,6 @@ func NewExternalJwtSignerRouter() *ExternalJwtSignerRouter { func (r *ExternalJwtSignerRouter) Register(ae *env.AppEnv) { // client - ae.ManagementApi.ExternalJWTSignerListExternalJWTSignersHandler = external_jwt_signer.ListExternalJWTSignersHandlerFunc(func(params external_jwt_signer.ListExternalJWTSignersParams, _ interface{}) middleware.Responder { return ae.IsAllowed(r.ListClient, params.HTTPRequest, "", "", permissions.Always()) }) @@ -76,16 +76,16 @@ func (r *ExternalJwtSignerRouter) Register(ae *env.AppEnv) { } func (r *ExternalJwtSignerRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.ExternalJwtSigner, MapExternalJwtSignerToRestEntity) + ListWithHandler[*model.ExternalJwtSigner](ae, rc, ae.Managers.ExternalJwtSigner, MapExternalJwtSignerToRestEntity) } func (r *ExternalJwtSignerRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.ExternalJwtSigner, MapExternalJwtSignerToRestEntity) + DetailWithHandler[*model.ExternalJwtSigner](ae, rc, ae.Managers.ExternalJwtSigner, MapExternalJwtSignerToRestEntity) } func (r *ExternalJwtSignerRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params external_jwt_signer.CreateExternalJWTSignerParams) { Create(rc, rc, ExternalJwtSignerLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.ExternalJwtSigner.Create, MapCreateExternalJwtSignerToModel(params.ExternalJWTSigner)) + return MapCreate(ae.Managers.ExternalJwtSigner.Create, MapCreateExternalJwtSignerToModel(params.ExternalJWTSigner), rc) }) } @@ -95,7 +95,7 @@ func (r *ExternalJwtSignerRouter) Delete(ae *env.AppEnv, rc *response.RequestCon func (r *ExternalJwtSignerRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params external_jwt_signer.UpdateExternalJWTSignerParams) { Update(rc, func(id string) error { - return ae.Managers.ExternalJwtSigner.Update(MapUpdateExternalJwtSignerToModel(params.ID, params.ExternalJWTSigner), nil) + return ae.Managers.ExternalJwtSigner.Update(MapUpdateExternalJwtSignerToModel(params.ID, params.ExternalJWTSigner), nil, rc.NewChangeContext()) }) } @@ -109,13 +109,13 @@ func (r *ExternalJwtSignerRouter) Patch(ae *env.AppEnv, rc *response.RequestCont fields.AddField(persistence.FieldExternalJwtSignerFingerprint) } - return ae.Managers.ExternalJwtSigner.Update(MapPatchExternalJwtSignerToModel(params.ID, params.ExternalJWTSigner), fields.FilterMaps("tags", "data")) + externalJwtSigner := MapPatchExternalJwtSignerToModel(params.ID, params.ExternalJWTSigner) + return ae.Managers.ExternalJwtSigner.Update(externalJwtSigner, fields.FilterMaps("tags", "data"), rc.NewChangeContext()) }) } func (r *ExternalJwtSignerRouter) ListClient(ae *env.AppEnv, rc *response.RequestContext) { List(rc, func(rc *response.RequestContext, queryOptions *PublicQueryOptions) (*QueryResult, error) { - query, err := queryOptions.getFullQuery(ae.Managers.EdgeService.GetStore()) if err != nil { return nil, err diff --git a/controller/internal/routes/identity_api_model.go b/controller/internal/routes/identity_api_model.go index 5bf4e0078..4a957987e 100644 --- a/controller/internal/routes/identity_api_model.go +++ b/controller/internal/routes/identity_api_model.go @@ -204,25 +204,8 @@ func MapPatchIdentityToModel(id string, identity *rest_model.IdentityPatch, iden return ret } -func MapIdentityToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - identity, ok := e.(*model.Identity) - - if !ok { - err := fmt.Errorf("entity is not a Identity \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapIdentityToRestModel(ae, identity) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapIdentityToRestEntity(ae *env.AppEnv, _ *response.RequestContext, entity *model.Identity) (interface{}, error) { + return MapIdentityToRestModel(ae, entity) } func MapIdentityToRestModel(ae *env.AppEnv, identity *model.Identity) (*rest_model.IdentityDetail, error) { diff --git a/controller/internal/routes/identity_router.go b/controller/internal/routes/identity_router.go index 037fbee38..014556c5b 100644 --- a/controller/internal/routes/identity_router.go +++ b/controller/internal/routes/identity_router.go @@ -174,7 +174,7 @@ func (r *IdentityRouter) List(ae *env.AppEnv, rc *response.RequestContext) { roleSemantic := rc.Request.URL.Query().Get("roleSemantic") if len(roleFilters) > 0 { - ListWithQueryF(ae, rc, ae.Managers.EdgeRouter, MapIdentityToRestEntity, func(query ast.Query) (*models.EntityListResult[models.Entity], error) { + ListWithQueryF[*model.Identity](ae, rc, ae.Managers.Identity, MapIdentityToRestEntity, func(query ast.Query) (*models.EntityListResult[*model.Identity], error) { cursorProvider, err := ae.GetStores().Identity.GetRoleAttributesCursorProvider(roleFilters, roleSemantic) if err != nil { return nil, err @@ -182,12 +182,12 @@ func (r *IdentityRouter) List(ae *env.AppEnv, rc *response.RequestContext) { return ae.Managers.Identity.BasePreparedListIndexed(cursorProvider, query) }) } else { - ListWithHandler(ae, rc, ae.Managers.Identity, MapIdentityToRestEntity) + ListWithHandler[*model.Identity](ae, rc, ae.Managers.Identity, MapIdentityToRestEntity) } } func (r *IdentityRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.Identity, MapIdentityToRestEntity) + DetailWithHandler[*model.Identity](ae, rc, ae.Managers.Identity, MapIdentityToRestEntity) } func getIdentityTypeId(ae *env.AppEnv, identityType rest_model.IdentityType) string { @@ -203,7 +203,7 @@ func getIdentityTypeId(ae *env.AppEnv, identityType rest_model.IdentityType) str func (r *IdentityRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params identity.CreateIdentityParams) { Create(rc, rc, IdentityLinkFactory, func() (string, error) { identityModel, enrollments := MapCreateIdentityToModel(params.Identity, getIdentityTypeId(ae, *params.Identity.Type)) - err := ae.Managers.Identity.CreateWithEnrollments(identityModel, enrollments) + err := ae.Managers.Identity.CreateWithEnrollments(identityModel, enrollments, rc.NewChangeContext()) if err != nil { return "", err } @@ -217,43 +217,43 @@ func (r *IdentityRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *IdentityRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params identity.UpdateIdentityParams) { Update(rc, func(id string) error { - return ae.Managers.Identity.Update(MapUpdateIdentityToModel(params.ID, params.Identity, getIdentityTypeId(ae, *params.Identity.Type)), nil) + return ae.Managers.Identity.Update(MapUpdateIdentityToModel(params.ID, params.Identity, getIdentityTypeId(ae, *params.Identity.Type)), nil, rc.NewChangeContext()) }) } func (r *IdentityRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params identity.PatchIdentityParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { fields = fields.FilterMaps(boltz.FieldTags, persistence.FieldIdentityAppData, persistence.FieldIdentityServiceHostingCosts, persistence.FieldIdentityServiceHostingPrecedences) - return ae.Managers.Identity.Update(MapPatchIdentityToModel(params.ID, params.Identity, getIdentityTypeId(ae, params.Identity.Type)), fields) + return ae.Managers.Identity.Update(MapPatchIdentityToModel(params.ID, params.Identity, getIdentityTypeId(ae, params.Identity.Type)), fields, rc.NewChangeContext()) }) } func (r *IdentityRouter) listEdgeRouterPolicies(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.Identity, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) + ListAssociationWithHandler[*model.Identity, *model.EdgeRouterPolicy](ae, rc, ae.Managers.Identity, ae.Managers.EdgeRouterPolicy, MapEdgeRouterPolicyToRestEntity) } func (r *IdentityRouter) listServicePolicies(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.Identity, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) + ListAssociationWithHandler[*model.Identity, *model.ServicePolicy](ae, rc, ae.Managers.Identity, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) } func (r *IdentityRouter) listServices(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from servicePolicies where anyOf(identities) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeService, MapServiceToRestEntity) + ListAssociationsWithFilter[*model.ServiceDetail](ae, rc, filterTemplate, ae.Managers.EdgeService.GetDetailLister(), MapServiceToRestEntity) } func (r *IdentityRouter) listAuthenticators(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `identity = "%v"` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) + ListAssociationsWithFilter[*model.Authenticator](ae, rc, filterTemplate, ae.Managers.Authenticator, MapAuthenticatorToRestEntity) } func (r *IdentityRouter) listEnrollments(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `identity = "%v"` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.Enrollment, MapEnrollmentToRestEntity) + ListAssociationsWithFilter[*model.Enrollment](ae, rc, filterTemplate, ae.Managers.Enrollment, MapEnrollmentToRestEntity) } func (r *IdentityRouter) listEdgeRouters(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from edgeRouterPolicies where anyOf(identities) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + ListAssociationsWithFilter[*model.EdgeRouter](ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } func (r *IdentityRouter) listServiceConfigs(ae *env.AppEnv, rc *response.RequestContext) { @@ -293,7 +293,7 @@ func (r *IdentityRouter) assignServiceConfigs(ae *env.AppEnv, rc *response.Reque for _, serviceConfig := range params.ServiceConfigs { modelServiceConfigs = append(modelServiceConfigs, MapServiceConfigToModel(*serviceConfig)) } - return ae.Managers.Identity.AssignServiceConfigs(id, modelServiceConfigs) + return ae.Managers.Identity.AssignServiceConfigs(id, modelServiceConfigs, rc.NewChangeContext()) }) } @@ -303,7 +303,7 @@ func (r *IdentityRouter) removeServiceConfigs(ae *env.AppEnv, rc *response.Reque for _, serviceConfig := range params.ServiceConfigIDPairs { modelServiceConfigs = append(modelServiceConfigs, MapServiceConfigToModel(*serviceConfig)) } - return ae.Managers.Identity.RemoveServiceConfigs(id, modelServiceConfigs) + return ae.Managers.Identity.RemoveServiceConfigs(id, modelServiceConfigs, rc.NewChangeContext()) }) } @@ -362,7 +362,7 @@ func (r *IdentityRouter) getPostureDataFailedServiceRequests(ae *env.AppEnv, rc func (r *IdentityRouter) removeMfa(ae *env.AppEnv, rc *response.RequestContext) { id, _ := rc.GetEntityId() - err := ae.Managers.Mfa.DeleteAllForIdentity(id) + err := ae.Managers.Mfa.DeleteAllForIdentity(id, rc.NewChangeContext()) if err != nil { rc.RespondWithError(err) @@ -420,7 +420,7 @@ func (r *IdentityRouter) updateTracing(ae *env.AppEnv, rc *response.RequestConte } func (r *IdentityRouter) Enable(ae *env.AppEnv, rc *response.RequestContext, params identity.EnableIdentityParams) { - if err := ae.Managers.Identity.Enable(params.ID); err != nil { + if err := ae.Managers.Identity.Enable(params.ID, rc.NewChangeContext()); err != nil { rc.RespondWithError(err) return } @@ -429,7 +429,7 @@ func (r *IdentityRouter) Enable(ae *env.AppEnv, rc *response.RequestContext, par } func (r *IdentityRouter) Disable(ae *env.AppEnv, rc *response.RequestContext, params identity.DisableIdentityParams) { - if err := ae.Managers.Identity.Disable(params.ID, time.Duration(*params.Disable.DurationMinutes)*time.Minute); err != nil { + if err := ae.Managers.Identity.Disable(params.ID, time.Duration(*params.Disable.DurationMinutes)*time.Minute, rc.NewChangeContext()); err != nil { rc.RespondWithError(err) return } diff --git a/controller/internal/routes/identity_type_api_model.go b/controller/internal/routes/identity_type_api_model.go index 35d620b8d..fa5fc7d9a 100644 --- a/controller/internal/routes/identity_type_api_model.go +++ b/controller/internal/routes/identity_type_api_model.go @@ -17,32 +17,18 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" - "github.com/openziti/fabric/controller/models" ) const EntityNameIdentityType = "identity-types" var IdentityTypeLinkFactory = NewBasicLinkFactory(EntityNameIdentityType) -func MapIdentityTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, identityTypeModel models.Entity) (interface{}, error) { - identityType, ok := identityTypeModel.(*model.IdentityType) - - if !ok { - err := fmt.Errorf("entity is not an identity type \"%s\"", identityTypeModel.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel := MapIdentityTypeToRestModel(identityType) - - return restModel, nil +func MapIdentityTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, identityType *model.IdentityType) (interface{}, error) { + return MapIdentityTypeToRestModel(identityType), nil } func MapIdentityTypeToRestModel(identityType *model.IdentityType) *rest_model.IdentityTypeDetail { diff --git a/controller/internal/routes/identity_type_router.go b/controller/internal/routes/identity_type_router.go index 6290e4b83..e8beed740 100644 --- a/controller/internal/routes/identity_type_router.go +++ b/controller/internal/routes/identity_type_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/identity" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" ) @@ -51,9 +52,9 @@ func (r *IdentityTypeRouter) Register(ae *env.AppEnv) { } func (r *IdentityTypeRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.IdentityType, MapIdentityTypeToRestEntity) + ListWithHandler[*model.IdentityType](ae, rc, ae.Managers.IdentityType, MapIdentityTypeToRestEntity) } func (r *IdentityTypeRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.IdentityType, MapIdentityTypeToRestEntity) + DetailWithHandler[*model.IdentityType](ae, rc, ae.Managers.IdentityType, MapIdentityTypeToRestEntity) } diff --git a/controller/internal/routes/posture_check_api_model.go b/controller/internal/routes/posture_check_api_model.go index dd78b77f1..ffc57b3f2 100644 --- a/controller/internal/routes/posture_check_api_model.go +++ b/controller/internal/routes/posture_check_api_model.go @@ -17,7 +17,6 @@ package routes import ( - "fmt" "github.com/go-openapi/strfmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" @@ -283,25 +282,8 @@ func MapPostureChecksToRestEntity(ae *env.AppEnv, rc *response.RequestContext, e return restModel, nil } -func MapPostureCheckToRestEntity(ae *env.AppEnv, rc *response.RequestContext, e models.Entity) (interface{}, error) { - i, ok := e.(*model.PostureCheck) - - if !ok { - err := fmt.Errorf("entity is not a Posture Check \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - al, err := MapPostureCheckToRestModel(ae, rc, i) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return al, nil +func MapPostureCheckToRestEntity(ae *env.AppEnv, rc *response.RequestContext, i *model.PostureCheck) (interface{}, error) { + return MapPostureCheckToRestModel(ae, rc, i) } func MapPostureCheckToRestModel(ae *env.AppEnv, rc *response.RequestContext, i *model.PostureCheck) (rest_model.PostureCheckDetail, error) { diff --git a/controller/internal/routes/posture_check_router.go b/controller/internal/routes/posture_check_router.go index 3b25ad7c3..136e36f8c 100644 --- a/controller/internal/routes/posture_check_router.go +++ b/controller/internal/routes/posture_check_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/posture_checks" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" @@ -113,12 +114,12 @@ func (r *PostureCheckRouter) List(ae *env.AppEnv, rc *response.RequestContext) { } func (r *PostureCheckRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.PostureCheck, MapPostureCheckToRestEntity) + DetailWithHandler[*model.PostureCheck](ae, rc, ae.Managers.PostureCheck, MapPostureCheckToRestEntity) } func (r *PostureCheckRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params posture_checks.CreatePostureCheckParams) { Create(rc, rc, PostureCheckLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.PostureCheck.Create, MapCreatePostureCheckToModel(params.PostureCheck)) + return MapCreate(ae.Managers.PostureCheck.Create, MapCreatePostureCheckToModel(params.PostureCheck), rc) }) } @@ -128,7 +129,7 @@ func (r *PostureCheckRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) func (r *PostureCheckRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params posture_checks.UpdatePostureCheckParams) { Update(rc, func(id string) error { - return ae.Managers.PostureCheck.Update(MapUpdatePostureCheckToModel(params.ID, params.PostureCheck), nil) + return ae.Managers.PostureCheck.Update(MapUpdatePostureCheckToModel(params.ID, params.PostureCheck), nil, rc.NewChangeContext()) }) } @@ -163,6 +164,6 @@ func (r *PostureCheckRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, fields.AddField(persistence.FieldPostureCheckProcessMultiHashes) } - return ae.Managers.PostureCheck.Update(check, fields.FilterMaps("tags")) + return ae.Managers.PostureCheck.Update(check, fields.FilterMaps("tags"), rc.NewChangeContext()) }) } diff --git a/controller/internal/routes/posture_check_type_api_model.go b/controller/internal/routes/posture_check_type_api_model.go index 28474326d..86240b45b 100644 --- a/controller/internal/routes/posture_check_type_api_model.go +++ b/controller/internal/routes/posture_check_type_api_model.go @@ -17,36 +17,21 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" - "github.com/openziti/fabric/controller/models" ) const EntityNamePostureCheckType = "posture-check-types" var PostureCheckTypeLinkFactory = NewBasicLinkFactory(EntityNamePostureCheckType) -func MapPostureCheckTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, postureCheckTypeModel models.Entity) (interface{}, error) { - postureCheckType, ok := postureCheckTypeModel.(*model.PostureCheckType) - - if !ok { - err := fmt.Errorf("entity is not a posture check type \"%s\"", postureCheckTypeModel.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel := MapPostureCheckTypeToRestModel(postureCheckType) - - return restModel, nil +func MapPostureCheckTypeToRestEntity(_ *env.AppEnv, _ *response.RequestContext, postureCheckType *model.PostureCheckType) (interface{}, error) { + return MapPostureCheckTypeToRestModel(postureCheckType), nil } func MapPostureCheckTypeToRestModel(postureCheckType *model.PostureCheckType) *rest_model.PostureCheckTypeDetail { - operatingSystems := []*rest_model.OperatingSystem{} for _, os := range postureCheckType.OperatingSystems { diff --git a/controller/internal/routes/posture_check_type_router.go b/controller/internal/routes/posture_check_type_router.go index e128a57df..92fe81d85 100644 --- a/controller/internal/routes/posture_check_type_router.go +++ b/controller/internal/routes/posture_check_type_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/posture_checks" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" ) @@ -52,9 +53,9 @@ func (r *PostureCheckTypeRouter) Register(ae *env.AppEnv) { } func (r *PostureCheckTypeRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.PostureCheckType, MapPostureCheckTypeToRestEntity) + ListWithHandler[*model.PostureCheckType](ae, rc, ae.Managers.PostureCheckType, MapPostureCheckTypeToRestEntity) } func (r *PostureCheckTypeRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.PostureCheckType, MapPostureCheckTypeToRestEntity) + DetailWithHandler[*model.PostureCheckType](ae, rc, ae.Managers.PostureCheckType, MapPostureCheckTypeToRestEntity) } diff --git a/controller/internal/routes/query_options.go b/controller/internal/routes/query_options.go index 74475f35c..7e8b4623a 100644 --- a/controller/internal/routes/query_options.go +++ b/controller/internal/routes/query_options.go @@ -25,7 +25,7 @@ import ( ) const ( - LimitMax = 500 + LimitMax = 500 ) // PublicQueryOptions represents external query options, which limits some query options (i.e. return all vs max limit). PublicQueryOptions @@ -43,7 +43,7 @@ func (qo *PublicQueryOptions) String() string { return fmt.Sprintf("[QueryOption Predicate: '%v', Sort: '%v', Paging: '%v']", qo.Predicate, qo.Sort, qo.Paging) } -func (qo *PublicQueryOptions) getFullQuery(store boltz.ListStore) (ast.Query, error) { +func (qo *PublicQueryOptions) getFullQuery(store boltz.Store) (ast.Query, error) { if qo.Predicate == "" { qo.Predicate = "true" } diff --git a/controller/internal/routes/router_api_model.go b/controller/internal/routes/router_api_model.go index 4838cc7e8..c0013956e 100644 --- a/controller/internal/routes/router_api_model.go +++ b/controller/internal/routes/router_api_model.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/go-openapi/strfmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -58,25 +57,8 @@ func MapPatchTransitRouterToModel(id string, router *rest_model.RouterPatch) *mo return ret } -func MapTransitRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - router, ok := e.(*model.TransitRouter) - - if !ok { - err := fmt.Errorf("entity is not a TransitRouter \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapTransitRouterToRestModel(ae, router) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapTransitRouterToRestEntity(ae *env.AppEnv, _ *response.RequestContext, router *model.TransitRouter) (interface{}, error) { + return MapTransitRouterToRestModel(ae, router) } func MapTransitRouterToRestModel(ae *env.AppEnv, router *model.TransitRouter) (*rest_model.RouterDetail, error) { diff --git a/controller/internal/routes/router_router.go b/controller/internal/routes/router_router.go index 13b05baf6..5404932b3 100644 --- a/controller/internal/routes/router_router.go +++ b/controller/internal/routes/router_router.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -94,16 +95,16 @@ func (r *TransitRouterRouter) Register(ae *env.AppEnv) { } func (r *TransitRouterRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.TransitRouter, MapTransitRouterToRestEntity) + ListWithHandler[*model.TransitRouter](ae, rc, ae.Managers.TransitRouter, MapTransitRouterToRestEntity) } func (r *TransitRouterRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.TransitRouter, MapTransitRouterToRestEntity) + DetailWithHandler[*model.TransitRouter](ae, rc, ae.Managers.TransitRouter, MapTransitRouterToRestEntity) } func (r *TransitRouterRouter) Create(ae *env.AppEnv, rc *response.RequestContext, router *rest_model.RouterCreate) { Create(rc, rc, TransitRouterLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.TransitRouter.Create, MapCreateRouterToModel(router)) + return MapCreate(ae.Managers.TransitRouter.Create, MapCreateRouterToModel(router), rc) }) } @@ -113,12 +114,12 @@ func (r *TransitRouterRouter) Delete(ae *env.AppEnv, rc *response.RequestContext func (r *TransitRouterRouter) Update(ae *env.AppEnv, rc *response.RequestContext, routerId string, router *rest_model.RouterUpdate) { Update(rc, func(id string) error { - return ae.Managers.TransitRouter.Update(MapUpdateTransitRouterToModel(routerId, router), false, nil) + return ae.Managers.TransitRouter.Update(MapUpdateTransitRouterToModel(routerId, router), false, nil, rc.NewChangeContext()) }) } func (r *TransitRouterRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, routerId string, router *rest_model.RouterPatch) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.TransitRouter.Update(MapPatchTransitRouterToModel(routerId, router), false, fields.FilterMaps("tags")) + return ae.Managers.TransitRouter.Update(MapPatchTransitRouterToModel(routerId, router), false, fields.FilterMaps("tags"), rc.NewChangeContext()) }) } diff --git a/controller/internal/routes/service_api_model.go b/controller/internal/routes/service_api_model.go index f0e164257..336273bc1 100644 --- a/controller/internal/routes/service_api_model.go +++ b/controller/internal/routes/service_api_model.go @@ -17,7 +17,6 @@ package routes import ( - "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" @@ -100,25 +99,8 @@ func MapPatchServiceToModel(id string, service *rest_model.ServicePatch) *model. return ret } -func MapServiceToRestEntity(ae *env.AppEnv, rc *response.RequestContext, e models.Entity) (interface{}, error) { - service, ok := e.(*model.ServiceDetail) - - if !ok { - err := fmt.Errorf("entity is not a Service \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapServiceToRestModel(ae, rc, service) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapServiceToRestEntity(ae *env.AppEnv, rc *response.RequestContext, service *model.ServiceDetail) (interface{}, error) { + return MapServiceToRestModel(ae, rc, service) } func MapServicesToRestEntity(ae *env.AppEnv, rc *response.RequestContext, es []*model.ServiceDetail) ([]interface{}, error) { diff --git a/controller/internal/routes/service_edge_router_policy_api_model.go b/controller/internal/routes/service_edge_router_policy_api_model.go index f11eb5edd..774f011d8 100644 --- a/controller/internal/routes/service_edge_router_policy_api_model.go +++ b/controller/internal/routes/service_edge_router_policy_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -102,25 +100,8 @@ func MapPatchServiceEdgeRouterPolicyToModel(id string, policy *rest_model.Servic return ret } -func MapServiceEdgeRouterPolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - policy, ok := e.(*model.ServiceEdgeRouterPolicy) - - if !ok { - err := fmt.Errorf("entity is not a ServiceEdgeRouterPolicy \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapServiceEdgeRouterPolicyToRestModel(ae, policy) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapServiceEdgeRouterPolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, policy *model.ServiceEdgeRouterPolicy) (interface{}, error) { + return MapServiceEdgeRouterPolicyToRestModel(ae, policy) } func MapServiceEdgeRouterPolicyToRestModel(ae *env.AppEnv, policy *model.ServiceEdgeRouterPolicy) (*rest_model.ServiceEdgeRouterPolicyDetail, error) { diff --git a/controller/internal/routes/service_edge_router_policy_router.go b/controller/internal/routes/service_edge_router_policy_router.go index 5954ffb44..c3bc790ee 100644 --- a/controller/internal/routes/service_edge_router_policy_router.go +++ b/controller/internal/routes/service_edge_router_policy_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/service_edge_router_policy" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -77,16 +78,16 @@ func (r *ServiceEdgeRouterPolicyRouter) Register(ae *env.AppEnv) { } func (r *ServiceEdgeRouterPolicyRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) + ListWithHandler[*model.ServiceEdgeRouterPolicy](ae, rc, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) } func (r *ServiceEdgeRouterPolicyRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) + DetailWithHandler[*model.ServiceEdgeRouterPolicy](ae, rc, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) } func (r *ServiceEdgeRouterPolicyRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params service_edge_router_policy.CreateServiceEdgeRouterPolicyParams) { Create(rc, rc, ServiceEdgeRouterPolicyLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.ServiceEdgeRouterPolicy.Create, MapCreateServiceEdgeRouterPolicyToModel(params.Policy)) + return MapCreate(ae.Managers.ServiceEdgeRouterPolicy.Create, MapCreateServiceEdgeRouterPolicyToModel(params.Policy), rc) }) } @@ -96,20 +97,20 @@ func (r *ServiceEdgeRouterPolicyRouter) Delete(ae *env.AppEnv, rc *response.Requ func (r *ServiceEdgeRouterPolicyRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params service_edge_router_policy.UpdateServiceEdgeRouterPolicyParams) { Update(rc, func(id string) error { - return ae.Managers.ServiceEdgeRouterPolicy.Update(MapUpdateServiceEdgeRouterPolicyToModel(params.ID, params.Policy), nil) + return ae.Managers.ServiceEdgeRouterPolicy.Update(MapUpdateServiceEdgeRouterPolicyToModel(params.ID, params.Policy), nil, rc.NewChangeContext()) }) } func (r *ServiceEdgeRouterPolicyRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params service_edge_router_policy.PatchServiceEdgeRouterPolicyParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.ServiceEdgeRouterPolicy.Update(MapPatchServiceEdgeRouterPolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags")) + return ae.Managers.ServiceEdgeRouterPolicy.Update(MapPatchServiceEdgeRouterPolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } func (r *ServiceEdgeRouterPolicyRouter) ListEdgeRouters(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.ServiceEdgeRouterPolicy, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + ListAssociationWithHandler[*model.ServiceEdgeRouterPolicy, *model.EdgeRouter](ae, rc, ae.Managers.ServiceEdgeRouterPolicy, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } func (r *ServiceEdgeRouterPolicyRouter) ListServices(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.ServiceEdgeRouterPolicy, ae.Managers.EdgeService, MapServiceToRestEntity) + ListAssociationWithHandler[*model.ServiceEdgeRouterPolicy, *model.ServiceDetail](ae, rc, ae.Managers.ServiceEdgeRouterPolicy, ae.Managers.EdgeService.GetDetailLister(), MapServiceToRestEntity) } diff --git a/controller/internal/routes/service_policy_api_model.go b/controller/internal/routes/service_policy_api_model.go index 11bcdfcaf..338cab5f2 100644 --- a/controller/internal/routes/service_policy_api_model.go +++ b/controller/internal/routes/service_policy_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/model" @@ -110,28 +108,11 @@ func MapPatchServicePolicyToModel(id string, policy *rest_model.ServicePolicyPat return ret } -func MapServicePolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - policy, ok := e.(*model.ServicePolicy) - - if !ok { - err := fmt.Errorf("entity is not a ServicePolicy \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapServicePolicyToRestModel(ae, policy) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapServicePolicyToRestEntity(ae *env.AppEnv, _ *response.RequestContext, policy *model.ServicePolicy) (interface{}, error) { + return MapServicePolicyToRestModel(ae, policy), nil } -func MapServicePolicyToRestModel(ae *env.AppEnv, policy *model.ServicePolicy) (*rest_model.ServicePolicyDetail, error) { +func MapServicePolicyToRestModel(ae *env.AppEnv, policy *model.ServicePolicy) *rest_model.ServicePolicyDetail { semantic := rest_model.Semantic(policy.Semantic) dialBindType := rest_model.DialBind(policy.PolicyType) @@ -148,5 +129,5 @@ func MapServicePolicyToRestModel(ae *env.AppEnv, policy *model.ServicePolicy) (* PostureCheckRolesDisplay: GetNamedPostureCheckRoles(ae.GetManagers().PostureCheck, policy.PostureCheckRoles), } - return ret, nil + return ret } diff --git a/controller/internal/routes/service_policy_router.go b/controller/internal/routes/service_policy_router.go index 41eb74285..2af0d25fe 100644 --- a/controller/internal/routes/service_policy_router.go +++ b/controller/internal/routes/service_policy_router.go @@ -21,6 +21,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_server/operations/service_policy" "github.com/openziti/edge/controller/env" "github.com/openziti/edge/controller/internal/permissions" + "github.com/openziti/edge/controller/model" "github.com/openziti/edge/controller/response" "github.com/openziti/fabric/controller/fields" ) @@ -81,16 +82,16 @@ func (r *ServicePolicyRouter) Register(ae *env.AppEnv) { } func (r *ServicePolicyRouter) List(ae *env.AppEnv, rc *response.RequestContext) { - ListWithHandler(ae, rc, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) + ListWithHandler[*model.ServicePolicy](ae, rc, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) } func (r *ServicePolicyRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { - DetailWithHandler(ae, rc, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) + DetailWithHandler[*model.ServicePolicy](ae, rc, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) } func (r *ServicePolicyRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params service_policy.CreateServicePolicyParams) { Create(rc, rc, ServicePolicyLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.ServicePolicy.Create, MapCreateServicePolicyToModel(params.Policy)) + return MapCreate(ae.Managers.ServicePolicy.Create, MapCreateServicePolicyToModel(params.Policy), rc) }) } @@ -100,24 +101,24 @@ func (r *ServicePolicyRouter) Delete(ae *env.AppEnv, rc *response.RequestContext func (r *ServicePolicyRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params service_policy.UpdateServicePolicyParams) { Update(rc, func(id string) error { - return ae.Managers.ServicePolicy.Update(MapUpdateServicePolicyToModel(params.ID, params.Policy), nil) + return ae.Managers.ServicePolicy.Update(MapUpdateServicePolicyToModel(params.ID, params.Policy), nil, rc.NewChangeContext()) }) } func (r *ServicePolicyRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params service_policy.PatchServicePolicyParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.ServicePolicy.Update(MapPatchServicePolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags")) + return ae.Managers.ServicePolicy.Update(MapPatchServicePolicyToModel(params.ID, params.Policy), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } func (r *ServicePolicyRouter) ListServices(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.ServicePolicy, ae.Managers.EdgeService, MapServiceToRestEntity) + ListAssociationWithHandler[*model.ServicePolicy, *model.ServiceDetail](ae, rc, ae.Managers.ServicePolicy, ae.Managers.EdgeService.GetDetailLister(), MapServiceToRestEntity) } func (r *ServicePolicyRouter) ListIdentities(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.ServicePolicy, ae.Managers.Identity, MapIdentityToRestEntity) + ListAssociationWithHandler[*model.ServicePolicy, *model.Identity](ae, rc, ae.Managers.ServicePolicy, ae.Managers.Identity, MapIdentityToRestEntity) } func (r *ServicePolicyRouter) ListPostureChecks(ae *env.AppEnv, rc *response.RequestContext) { - ListAssociationWithHandler(ae, rc, ae.Managers.ServicePolicy, ae.Managers.PostureCheck, MapPostureCheckToRestEntity) + ListAssociationWithHandler[*model.ServicePolicy, *model.PostureCheck](ae, rc, ae.Managers.ServicePolicy, ae.Managers.PostureCheck, MapPostureCheckToRestEntity) } diff --git a/controller/internal/routes/service_router.go b/controller/internal/routes/service_router.go index 9ea34006d..43a4b1bb6 100644 --- a/controller/internal/routes/service_router.go +++ b/controller/internal/routes/service_router.go @@ -21,6 +21,7 @@ import ( "github.com/michaelquigley/pfxlog" clientService "github.com/openziti/edge-api/rest_client_api_server/operations/service" managementService "github.com/openziti/edge-api/rest_management_api_server/operations/service" + "github.com/openziti/edge/controller/model" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/metrics" @@ -154,7 +155,7 @@ func (r *ServiceRouter) ListManagementServices(ae *env.AppEnv, rc *response.Requ return nil, err } - result, err := ae.Managers.EdgeService.BasePreparedListIndexed(cursorProvider, query) + result, err := ae.Managers.EdgeService.GetDetailLister().BasePreparedListIndexed(cursorProvider, query) if err != nil { return nil, err @@ -228,7 +229,7 @@ func (r *ServiceRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { func (r *ServiceRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params managementService.CreateServiceParams) { Create(rc, rc, ServiceLinkFactory, func() (string, error) { - return MapCreate(ae.Managers.EdgeService.Create, MapCreateServiceToModel(params.Service)) + return MapCreate(ae.Managers.EdgeService.Create, MapCreateServiceToModel(params.Service), rc) }) } @@ -238,26 +239,26 @@ func (r *ServiceRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *ServiceRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params managementService.UpdateServiceParams) { Update(rc, func(id string) error { - return ae.Managers.EdgeService.Update(MapUpdateServiceToModel(params.ID, params.Service), nil) + return ae.Managers.EdgeService.Update(MapUpdateServiceToModel(params.ID, params.Service), nil, rc.NewChangeContext()) }) } func (r *ServiceRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params managementService.PatchServiceParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.EdgeService.Update(MapPatchServiceToModel(params.ID, params.Service), fields.FilterMaps("tags")) + return ae.Managers.EdgeService.Update(MapPatchServiceToModel(params.ID, params.Service), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } func (r *ServiceRouter) listServiceEdgeRouterPolicies(ae *env.AppEnv, rc *response.RequestContext) { - r.listAssociations(ae, rc, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) + ListAssociationWithHandler[*model.Service, *model.ServiceEdgeRouterPolicy](ae, rc, ae.Managers.EdgeService, ae.Managers.ServiceEdgeRouterPolicy, MapServiceEdgeRouterPolicyToRestEntity) } func (r *ServiceRouter) listServicePolicies(ae *env.AppEnv, rc *response.RequestContext) { - r.listAssociations(ae, rc, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) + ListAssociationWithHandler[*model.Service, *model.ServicePolicy](ae, rc, ae.Managers.EdgeService, ae.Managers.ServicePolicy, MapServicePolicyToRestEntity) } func (r *ServiceRouter) listConfigs(ae *env.AppEnv, rc *response.RequestContext) { - r.listAssociations(ae, rc, ae.Managers.Config, MapConfigToRestEntity) + ListAssociationWithHandler[*model.Service, *model.Config](ae, rc, ae.Managers.EdgeService, ae.Managers.Config, MapConfigToRestEntity) } func (r *ServiceRouter) listManagementTerminators(ae *env.AppEnv, rc *response.RequestContext) { @@ -291,16 +292,12 @@ func (r *ServiceRouter) listClientTerminators(ae *env.AppEnv, rc *response.Reque ListTerminatorAssociations(ae, rc, ae.Managers.EdgeService, ae.Managers.Terminator, MapClientTerminatorToRestEntity) } -func (r *ServiceRouter) listAssociations(ae *env.AppEnv, rc *response.RequestContext, associationLoader models.EntityRetriever[models.Entity], mapper ModelToApiMapper) { - ListAssociationWithHandler(ae, rc, ae.Managers.EdgeService, associationLoader, mapper) -} - func (r *ServiceRouter) listIdentities(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from servicePolicies where anyOf(services) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.Identity, MapIdentityToRestEntity) + ListAssociationsWithFilter[*model.Identity](ae, rc, filterTemplate, ae.Managers.Identity, MapIdentityToRestEntity) } func (r *ServiceRouter) listEdgeRouters(ae *env.AppEnv, rc *response.RequestContext) { filterTemplate := `not isEmpty(from serviceEdgeRouterPolicies where anyOf(services) = "%v")` - ListAssociationsWithFilter(ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) + ListAssociationsWithFilter[*model.EdgeRouter](ae, rc, filterTemplate, ae.Managers.EdgeRouter, MapEdgeRouterToRestEntity) } diff --git a/controller/internal/routes/session_api_model.go b/controller/internal/routes/session_api_model.go index 0690fd545..c5e3ac808 100644 --- a/controller/internal/routes/session_api_model.go +++ b/controller/internal/routes/session_api_model.go @@ -17,8 +17,6 @@ package routes import ( - "fmt" - "github.com/google/uuid" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" @@ -65,25 +63,8 @@ func MapCreateSessionToModel(identityId, apiSessionId string, session *rest_mode return ret } -func MapSessionToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - session, ok := e.(*model.Session) - - if !ok { - err := fmt.Errorf("entity is not a Session \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapSessionToRestModel(ae, session) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapSessionToRestEntity(ae *env.AppEnv, _ *response.RequestContext, session *model.Session) (interface{}, error) { + return MapSessionToRestModel(ae, session) } func MapSessionToRestModel(ae *env.AppEnv, sessionModel *model.Session) (*rest_model.SessionManagementDetail, error) { diff --git a/controller/internal/routes/session_router.go b/controller/internal/routes/session_router.go index ccfae010e..6f647f85f 100644 --- a/controller/internal/routes/session_router.go +++ b/controller/internal/routes/session_router.go @@ -117,7 +117,7 @@ func (r *SessionRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { func (r *SessionRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { Delete(rc, func(rc *response.RequestContext, id string) error { - return ae.Managers.Session.DeleteForIdentity(id, rc.ApiSession.IdentityId) + return ae.Managers.Session.DeleteForIdentity(id, rc.ApiSession.IdentityId, rc.NewChangeContext()) }) } @@ -125,7 +125,7 @@ func (r *SessionRouter) Create(ae *env.AppEnv, rc *response.RequestContext, para start := time.Now() responder := &SessionRequestResponder{ae: ae, Responder: rc} CreateWithResponder(rc, responder, SessionLinkFactory, func() (string, error) { - return ae.Managers.Session.Create(MapCreateSessionToModel(rc.Identity.Id, rc.ApiSession.Id, params.Session)) + return ae.Managers.Session.Create(MapCreateSessionToModel(rc.Identity.Id, rc.ApiSession.Id, params.Session), rc.NewChangeContext()) }) r.createTimer.UpdateSince(start) } diff --git a/controller/internal/routes/terminator_api_model.go b/controller/internal/routes/terminator_api_model.go index 9d6ac5722..adf4f94f5 100644 --- a/controller/internal/routes/terminator_api_model.go +++ b/controller/internal/routes/terminator_api_model.go @@ -108,25 +108,8 @@ func (TerminatorModelMapper) ToApi(n *network.Network, _ api.RequestContext, ter return restModel, nil } -func MapTerminatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - terminator, ok := e.(*network.Terminator) - - if !ok { - err := fmt.Errorf("entity is not a Terminator \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapTerminatorToRestModel(ae.GetHostController().GetNetwork(), terminator) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapTerminatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, terminator *network.Terminator) (interface{}, error) { + return MapTerminatorToRestModel(ae.GetHostController().GetNetwork(), terminator) } func MapTerminatorToRestModel(n *network.Network, terminator *network.Terminator) (*rest_model.TerminatorDetail, error) { @@ -172,25 +155,8 @@ func MapTerminatorToRestModel(n *network.Network, terminator *network.Terminator return ret, nil } -func MapClientTerminatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, e models.Entity) (interface{}, error) { - terminator, ok := e.(*network.Terminator) - - if !ok { - err := fmt.Errorf("entity is not a Terminator \"%s\"", e.GetId()) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - - restModel, err := MapLimitedTerminatorToRestModel(ae, terminator) - - if err != nil { - err := fmt.Errorf("could not convert to API entity \"%s\": %s", e.GetId(), err) - log := pfxlog.Logger() - log.Error(err) - return nil, err - } - return restModel, nil +func MapClientTerminatorToRestEntity(ae *env.AppEnv, _ *response.RequestContext, terminator *network.Terminator) (interface{}, error) { + return MapLimitedTerminatorToRestModel(ae, terminator) } func MapLimitedTerminatorToRestModel(ae *env.AppEnv, terminator *network.Terminator) (*rest_model.TerminatorClientDetail, error) { diff --git a/controller/internal/routes/terminator_router.go b/controller/internal/routes/terminator_router.go index a4eaf5b57..7672e96ee 100644 --- a/controller/internal/routes/terminator_router.go +++ b/controller/internal/routes/terminator_router.go @@ -79,7 +79,7 @@ func (r *TerminatorRouter) Detail(ae *env.AppEnv, rc *response.RequestContext) { func (r *TerminatorRouter) Create(ae *env.AppEnv, rc *response.RequestContext, params terminator.CreateTerminatorParams) { Create(rc, rc, TerminatorLinkFactory, func() (string, error) { entity := MapCreateTerminatorToModel(params.Terminator) - err := ae.Managers.Terminator.Create(entity) + err := ae.Managers.Terminator.Create(entity, rc.NewChangeContext()) if err != nil { return "", err } @@ -93,12 +93,12 @@ func (r *TerminatorRouter) Delete(ae *env.AppEnv, rc *response.RequestContext) { func (r *TerminatorRouter) Update(ae *env.AppEnv, rc *response.RequestContext, params terminator.UpdateTerminatorParams) { Update(rc, func(id string) error { - return ae.Managers.Terminator.Update(MapUpdateTerminatorToModel(params.ID, params.Terminator), nil) + return ae.Managers.Terminator.Update(MapUpdateTerminatorToModel(params.ID, params.Terminator), nil, rc.NewChangeContext()) }) } func (r *TerminatorRouter) Patch(ae *env.AppEnv, rc *response.RequestContext, params terminator.PatchTerminatorParams) { Patch(rc, func(id string, fields fields.UpdatedFields) error { - return ae.Managers.Terminator.Update(MapPatchTerminatorToModel(params.ID, params.Terminator), fields.FilterMaps("tags")) + return ae.Managers.Terminator.Update(MapPatchTerminatorToModel(params.ID, params.Terminator), fields.FilterMaps("tags"), rc.NewChangeContext()) }) } diff --git a/controller/model/api_session_certificate_manager.go b/controller/model/api_session_certificate_manager.go index 4ce2ea4d5..f732bc062 100644 --- a/controller/model/api_session_certificate_manager.go +++ b/controller/model/api_session_certificate_manager.go @@ -20,7 +20,9 @@ import ( "crypto/x509" "fmt" "github.com/openziti/edge/controller/apierror" + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/internal/cert" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/models" "go.etcd.io/bbolt" "time" @@ -28,7 +30,7 @@ import ( func NewApiSessionCertificateManager(env Env) *ApiSessionCertificateManager { manager := &ApiSessionCertificateManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ApiSessionCertificate), + baseEntityManager: newBaseEntityManager[*ApiSessionCertificate, *persistence.ApiSessionCertificate](env, env.GetStores().ApiSessionCertificate), } manager.impl = manager @@ -36,18 +38,18 @@ func NewApiSessionCertificateManager(env Env) *ApiSessionCertificateManager { } type ApiSessionCertificateManager struct { - baseEntityManager + baseEntityManager[*ApiSessionCertificate, *persistence.ApiSessionCertificate] } -func (self *ApiSessionCertificateManager) newModelEntity() edgeEntity { +func (self *ApiSessionCertificateManager) newModelEntity() *ApiSessionCertificate { return &ApiSessionCertificate{} } -func (self *ApiSessionCertificateManager) Create(entity *ApiSessionCertificate) (string, error) { - return self.createEntity(entity) +func (self *ApiSessionCertificateManager) Create(entity *ApiSessionCertificate, ctx *change.Context) (string, error) { + return self.createEntity(entity, ctx.NewMutateContext()) } -func (self *ApiSessionCertificateManager) CreateFromCSR(apiSessionId string, lifespan time.Duration, csrPem []byte) (string, error) { +func (self *ApiSessionCertificateManager) CreateFromCSR(apiSessionId string, lifespan time.Duration, csrPem []byte, ctx *change.Context) (string, error) { notBefore := time.Now() notAfter := time.Now().Add(lifespan) @@ -88,31 +90,15 @@ func (self *ApiSessionCertificateManager) CreateFromCSR(apiSessionId string, lif PEM: string(certPem), } - return self.Create(entity) -} - -func (self *ApiSessionCertificateManager) Read(id string) (*ApiSessionCertificate, error) { - modelApiSessionCertificate := &ApiSessionCertificate{} - if err := self.readEntity(id, modelApiSessionCertificate); err != nil { - return nil, err - } - return modelApiSessionCertificate, nil -} - -func (self *ApiSessionCertificateManager) readInTx(tx *bbolt.Tx, id string) (*ApiSessionCertificate, error) { - modelApiSessionCertificate := &ApiSessionCertificate{} - if err := self.readEntityInTx(tx, id, modelApiSessionCertificate); err != nil { - return nil, err - } - return modelApiSessionCertificate, nil + return self.Create(entity, ctx) } func (self *ApiSessionCertificateManager) IsUpdated(_ string) bool { return false } -func (self *ApiSessionCertificateManager) Delete(id string) error { - return self.deleteEntity(id) +func (self *ApiSessionCertificateManager) Delete(id string, ctx *change.Context) error { + return self.deleteEntity(id, ctx) } func (self *ApiSessionCertificateManager) Query(tx *bbolt.Tx, query string) (*ApiSessionCertificateListResult, error) { diff --git a/controller/model/api_session_certificate_model.go b/controller/model/api_session_certificate_model.go index 2b876327c..8c1662648 100644 --- a/controller/model/api_session_certificate_model.go +++ b/controller/model/api_session_certificate_model.go @@ -23,9 +23,7 @@ import ( "github.com/openziti/foundation/v2/errorz" nfpem "github.com/openziti/foundation/v2/pem" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -53,8 +51,8 @@ func NewApiSessionCertificate(cert *x509.Certificate) *ApiSessionCertificate { return ret } -func (entity *ApiSessionCertificate) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - if !manager.GetEnv().GetStores().ApiSession.IsEntityPresent(tx, entity.ApiSessionId) { +func (entity *ApiSessionCertificate) toBoltEntity(tx *bbolt.Tx, env Env) (*persistence.ApiSessionCertificate, error) { + if !env.GetStores().ApiSession.IsEntityPresent(tx, entity.ApiSessionId) { return nil, errorz.NewFieldError("api session not found", "ApiSessionId", entity.ApiSessionId) } @@ -71,20 +69,15 @@ func (entity *ApiSessionCertificate) toBoltEntity(tx *bbolt.Tx, manager EntityMa return boltEntity, nil } -func (entity *ApiSessionCertificate) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *ApiSessionCertificate) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.ApiSessionCertificate, error) { + return entity.toBoltEntity(tx, env) } -func (entity *ApiSessionCertificate) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *ApiSessionCertificate) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.ApiSessionCertificate, error) { + return entity.toBoltEntity(tx, env) } -func (entity *ApiSessionCertificate) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error { - boltApiSessionCertificate, ok := boltEntity.(*persistence.ApiSessionCertificate) - if !ok { - return errors.Errorf("unexpected type %v when filling model ApiSessionCertificate", reflect.TypeOf(boltEntity)) - } - +func (entity *ApiSessionCertificate) fillFrom(env Env, tx *bbolt.Tx, boltApiSessionCertificate *persistence.ApiSessionCertificate) error { entity.FillCommon(boltApiSessionCertificate) entity.Subject = boltApiSessionCertificate.Subject entity.Fingerprint = boltApiSessionCertificate.Fingerprint @@ -93,12 +86,12 @@ func (entity *ApiSessionCertificate) fillFrom(manager EntityManager, tx *bbolt.T entity.PEM = boltApiSessionCertificate.PEM entity.ApiSessionId = boltApiSessionCertificate.ApiSessionId - boltApiSession, err := manager.GetEnv().GetStores().ApiSession.LoadOneById(tx, boltApiSessionCertificate.ApiSessionId) + boltApiSession, err := env.GetStores().ApiSession.LoadOneById(tx, boltApiSessionCertificate.ApiSessionId) if err != nil { return err } modelApiSession := &ApiSession{} - if err := modelApiSession.fillFrom(manager, tx, boltApiSession); err != nil { + if err := modelApiSession.fillFrom(env, tx, boltApiSession); err != nil { return err } entity.ApiSession = modelApiSession diff --git a/controller/model/api_session_heartbeats.go b/controller/model/api_session_heartbeats.go index 23f190799..88a8a3e4a 100644 --- a/controller/model/api_session_heartbeats.go +++ b/controller/model/api_session_heartbeats.go @@ -18,7 +18,6 @@ package model import ( "github.com/michaelquigley/pfxlog" - "github.com/openziti/edge/controller/persistence" "github.com/openziti/storage/boltz" cmap "github.com/orcaman/concurrent-map/v2" "sync/atomic" @@ -52,7 +51,7 @@ func NewHeartbeatCollector(env Env, batchSize int, updateInterval time.Duration, closeNotify: make(chan struct{}), } - env.GetStores().ApiSession.AddListener(boltz.EventDelete, collector.onApiSessionDelete) + env.GetStores().ApiSession.AddEntityIdListener(collector.Remove, boltz.EntityDeleted) collector.Start() @@ -142,15 +141,6 @@ func (self *HeartbeatCollector) flush() { } } -func (self *HeartbeatCollector) onApiSessionDelete(i ...interface{}) { - if len(i) > 0 { - apiSession := i[0].(*persistence.ApiSession) - if apiSession != nil && apiSession.Id != "" { - self.Remove(apiSession.Id) - } - } -} - func (self *HeartbeatCollector) Remove(id string) { self.apiSessionLastAccessedAtMap.Remove(id) } diff --git a/controller/model/api_session_manager.go b/controller/model/api_session_manager.go index d96135804..04079fbd4 100644 --- a/controller/model/api_session_manager.go +++ b/controller/model/api_session_manager.go @@ -21,6 +21,7 @@ import ( "github.com/lucsky/cuid" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" @@ -31,7 +32,7 @@ import ( func NewApiSessionManager(env Env) *ApiSessionManager { manager := &ApiSessionManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ApiSession), + baseEntityManager: newBaseEntityManager[*ApiSession, *persistence.ApiSession](env, env.GetStores().ApiSession), } manager.HeartbeatCollector = NewHeartbeatCollector(env, env.GetConfig().Api.ActivityUpdateBatchSize, env.GetConfig().Api.ActivityUpdateInterval, manager.heartbeatFlush) @@ -42,30 +43,25 @@ func NewApiSessionManager(env Env) *ApiSessionManager { } type ApiSessionManager struct { - baseEntityManager + baseEntityManager[*ApiSession, *persistence.ApiSession] HeartbeatCollector *HeartbeatCollector } -func (self *ApiSessionManager) newModelEntity() edgeEntity { +func (self *ApiSessionManager) newModelEntity() *ApiSession { return &ApiSession{} } func (self *ApiSessionManager) Create(ctx boltz.MutateContext, entity *ApiSession, sessionCerts []*ApiSessionCertificate) (string, error) { - if ctx == nil { - var apiSessionId string - err := self.env.GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { - ctx = boltz.NewMutateContext(tx) - var err error - apiSessionId, err = self.CreateInCtx(ctx, entity, sessionCerts) - return err - }) - if err != nil { - return "", err - } - return apiSessionId, nil + var apiSessionId string + err := self.env.GetDbProvider().GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + var err error + apiSessionId, err = self.CreateInCtx(ctx, entity, sessionCerts) + return err + }) + if err != nil { + return "", err } - - return self.CreateInCtx(ctx, entity, sessionCerts) + return apiSessionId, nil } func (self *ApiSessionManager) CreateInCtx(ctx boltz.MutateContext, entity *ApiSession, sessionCerts []*ApiSessionCertificate) (string, error) { @@ -117,25 +113,25 @@ func (self *ApiSessionManager) IsUpdated(_ string) bool { return false } -func (self *ApiSessionManager) Update(apiSession *ApiSession) error { - return self.updateEntity(apiSession, self) +func (self *ApiSessionManager) Update(apiSession *ApiSession, ctx *change.Context) error { + return self.updateEntity(apiSession, self, ctx.NewMutateContext()) } -func (self *ApiSessionManager) UpdateWithFieldChecker(apiSession *ApiSession, fieldChecker boltz.FieldChecker) error { - return self.updateEntity(apiSession, fieldChecker) +func (self *ApiSessionManager) UpdateWithFieldChecker(apiSession *ApiSession, fieldChecker boltz.FieldChecker, ctx *change.Context) error { + return self.updateEntity(apiSession, fieldChecker, ctx.NewMutateContext()) } -func (self *ApiSessionManager) MfaCompleted(apiSession *ApiSession) error { +func (self *ApiSessionManager) MfaCompleted(apiSession *ApiSession, ctx *change.Context) error { apiSession.MfaComplete = true - return self.updateEntity(apiSession, &OrFieldChecker{NewFieldChecker(persistence.FieldApiSessionMfaComplete), self}) + return self.updateEntity(apiSession, &OrFieldChecker{NewFieldChecker(persistence.FieldApiSessionMfaComplete), self}, ctx.NewMutateContext()) } -func (self *ApiSessionManager) Delete(id string) error { - return self.deleteEntity(id) +func (self *ApiSessionManager) Delete(id string, ctx *change.Context) error { + return self.deleteEntity(id, ctx) } -func (self *ApiSessionManager) DeleteBatch(id []string) error { - return self.deleteEntityBatch(id) +func (self *ApiSessionManager) DeleteBatch(id []string, ctx *change.Context) error { + return self.deleteEntityBatch(id, ctx) } func (self *ApiSessionManager) MarkActivityById(apiSessionId string) { @@ -173,12 +169,12 @@ func (self *ApiSessionManager) MarkActivityByTokens(tokens ...string) ([]string, } func (self *ApiSessionManager) heartbeatFlush(beats []*Heartbeat) { - err := self.GetDb().Batch(func(tx *bbolt.Tx) error { + changeCtx := change.New().SetSource("heartbeat.flush").SetChangeAuthorType("controller") + err := self.GetDb().Batch(changeCtx.NewMutateContext(), func(ctx boltz.MutateContext) error { store := self.Store.(persistence.ApiSessionStore) - mutCtx := boltz.NewMutateContext(tx) for _, beat := range beats { - err := store.Update(mutCtx, &persistence.ApiSession{ + err := store.Update(ctx, &persistence.ApiSession{ BaseExtEntity: boltz.BaseExtEntity{ Id: beat.ApiSessionId, }, @@ -279,10 +275,10 @@ func (self *ApiSessionManager) VisitFingerprintsForApiSession(tx *bbolt.Tx, iden return nil } -func (self *ApiSessionManager) DeleteByIdentityId(identityId string) error { - return self.GetEnv().GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { +func (self *ApiSessionManager) DeleteByIdentityId(identityId string, changeCtx *change.Context) error { + return self.GetEnv().GetDbProvider().GetDb().Update(changeCtx.NewMutateContext(), func(ctx boltz.MutateContext) error { query := fmt.Sprintf(`%s = "%s"`, persistence.FieldApiSessionIdentity, identityId) - return self.Store.DeleteWhere(boltz.NewMutateContext(tx), query) + return self.Store.DeleteWhere(ctx, query) }) } diff --git a/controller/model/api_session_model.go b/controller/model/api_session_model.go index d6cf1e8fe..417438ab9 100644 --- a/controller/model/api_session_model.go +++ b/controller/model/api_session_model.go @@ -22,9 +22,7 @@ import ( "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -43,8 +41,8 @@ type ApiSession struct { AuthenticatorId string } -func (entity *ApiSession) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - if !manager.GetEnv().GetStores().Identity.IsEntityPresent(tx, entity.IdentityId) { +func (entity *ApiSession) toBoltEntity(tx *bbolt.Tx, env Env) (*persistence.ApiSession, error) { + if !env.GetStores().Identity.IsEntityPresent(tx, entity.IdentityId) { return nil, errorz.NewFieldError("identity not found", "IdentityId", entity.IdentityId) } @@ -63,19 +61,15 @@ func (entity *ApiSession) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (bol return boltEntity, nil } -func (entity *ApiSession) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *ApiSession) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.ApiSession, error) { + return entity.toBoltEntity(tx, env) } -func (entity *ApiSession) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *ApiSession) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.ApiSession, error) { + return entity.toBoltEntity(tx, env) } -func (entity *ApiSession) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error { - boltApiSession, ok := boltEntity.(*persistence.ApiSession) - if !ok { - return errors.Errorf("unexpected type %v when filling model ApiSession", reflect.TypeOf(boltEntity)) - } +func (entity *ApiSession) fillFrom(env Env, tx *bbolt.Tx, boltApiSession *persistence.ApiSession) error { entity.FillCommon(boltApiSession) entity.Token = boltApiSession.Token entity.IdentityId = boltApiSession.IdentityId @@ -83,17 +77,17 @@ func (entity *ApiSession) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEnti entity.IPAddress = boltApiSession.IPAddress entity.MfaRequired = boltApiSession.MfaRequired entity.MfaComplete = boltApiSession.MfaComplete - entity.ExpiresAt = entity.UpdatedAt.Add(manager.GetEnv().GetConfig().Api.SessionTimeout) - entity.ExpirationDuration = manager.GetEnv().GetConfig().Api.SessionTimeout + entity.ExpiresAt = entity.UpdatedAt.Add(env.GetConfig().Api.SessionTimeout) + entity.ExpirationDuration = env.GetConfig().Api.SessionTimeout entity.LastActivityAt = boltApiSession.LastActivityAt entity.AuthenticatorId = boltApiSession.AuthenticatorId - boltIdentity, err := manager.GetEnv().GetStores().Identity.LoadOneById(tx, boltApiSession.IdentityId) + boltIdentity, err := env.GetStores().Identity.LoadOneById(tx, boltApiSession.IdentityId) if err != nil { return err } modelIdentity := &Identity{} - if err := modelIdentity.fillFrom(manager, tx, boltIdentity); err != nil { + if err := modelIdentity.fillFrom(env, tx, boltIdentity); err != nil { return err } entity.Identity = modelIdentity diff --git a/controller/model/auth_policy_manager.go b/controller/model/auth_policy_manager.go index 822ca1f2c..c7332d528 100644 --- a/controller/model/auth_policy_manager.go +++ b/controller/model/auth_policy_manager.go @@ -18,7 +18,9 @@ package model import ( "fmt" + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -31,7 +33,7 @@ import ( func NewAuthPolicyManager(env Env) *AuthPolicyManager { manager := &AuthPolicyManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().AuthPolicy), + baseEntityManager: newBaseEntityManager[*AuthPolicy, *persistence.AuthPolicy](env, env.GetStores().AuthPolicy), } manager.impl = manager @@ -41,14 +43,14 @@ func NewAuthPolicyManager(env Env) *AuthPolicyManager { } type AuthPolicyManager struct { - baseEntityManager + baseEntityManager[*AuthPolicy, *persistence.AuthPolicy] } -func (self *AuthPolicyManager) Create(entity *AuthPolicy) error { - return network.DispatchCreate[*AuthPolicy](self, entity) +func (self *AuthPolicyManager) Create(entity *AuthPolicy, ctx *change.Context) error { + return network.DispatchCreate[*AuthPolicy](self, entity, ctx) } -func (self *AuthPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*AuthPolicy]) error { +func (self *AuthPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*AuthPolicy], ctx boltz.MutateContext) error { entity := cmd.Entity if entity.Secondary.RequiredExtJwtSigner != nil { if err := self.verifyExtJwt(*entity.Secondary.RequiredExtJwtSigner, "secondary.requiredExtJwtSigner"); err != nil { @@ -62,19 +64,19 @@ func (self *AuthPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*Aut } } - _, err := self.createEntity(cmd.Entity) + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *AuthPolicyManager) Update(entity *AuthPolicy, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*AuthPolicy](self, entity, checker) +func (self *AuthPolicyManager) Update(entity *AuthPolicy, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*AuthPolicy](self, entity, checker, ctx) } -func (self *AuthPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*AuthPolicy]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) +func (self *AuthPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*AuthPolicy], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } -func (self *AuthPolicyManager) newModelEntity() edgeEntity { +func (self *AuthPolicyManager) newModelEntity() *AuthPolicy { return &AuthPolicy{} } diff --git a/controller/model/auth_policy_model.go b/controller/model/auth_policy_model.go index 11c023799..5e0422472 100644 --- a/controller/model/auth_policy_model.go +++ b/controller/model/auth_policy_model.go @@ -20,9 +20,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type AuthPolicy struct { @@ -64,11 +62,7 @@ type AuthPolicyUpdb struct { LockoutDurationMinutes int64 } -func (entity *AuthPolicy) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltAuthPolicy, ok := boltEntity.(*persistence.AuthPolicy) - if !ok { - return errors.Errorf("unexpected type %v when filling model ca", reflect.TypeOf(boltEntity)) - } +func (entity *AuthPolicy) fillFrom(_ Env, _ *bbolt.Tx, boltAuthPolicy *persistence.AuthPolicy) error { entity.FillCommon(boltAuthPolicy) entity.Name = boltAuthPolicy.Name entity.Primary = AuthPolicyPrimary{ @@ -98,7 +92,7 @@ func (entity *AuthPolicy) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity bolt return nil } -func (entity *AuthPolicy) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *AuthPolicy) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.AuthPolicy, error) { boltEntity := &persistence.AuthPolicy{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Name: entity.Name, @@ -130,6 +124,6 @@ func (entity *AuthPolicy) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz return boltEntity, nil } -func (entity *AuthPolicy) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntityForCreate(tx, manager) +func (entity *AuthPolicy) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.AuthPolicy, error) { + return entity.toBoltEntityForCreate(tx, env) } diff --git a/controller/model/authenticator.go b/controller/model/authenticator.go index 5f2f66852..9fe819211 100644 --- a/controller/model/authenticator.go +++ b/controller/model/authenticator.go @@ -19,6 +19,7 @@ package model import ( "crypto/x509" "encoding/json" + "github.com/openziti/fabric/controller/change" "net/http" ) @@ -66,16 +67,18 @@ type AuthContext interface { GetData() map[string]interface{} GetCerts() []*x509.Certificate GetHeaders() map[string]interface{} + GetChangeContext() *change.Context } type AuthContextHttp struct { - Method string - Data map[string]interface{} - Certs []*x509.Certificate - Headers map[string]interface{} + Method string + Data map[string]interface{} + Certs []*x509.Certificate + Headers map[string]interface{} + ChangeContext *change.Context } -func NewAuthContextHttp(request *http.Request, method string, data interface{}) AuthContext { +func NewAuthContextHttp(request *http.Request, method string, data interface{}, ctx *change.Context) AuthContext { //TODO: this is a giant hack to not deal w/ removing the AuthContext layer sigh, _ := json.Marshal(data) mapData := map[string]interface{}{} @@ -87,10 +90,11 @@ func NewAuthContextHttp(request *http.Request, method string, data interface{}) } return &AuthContextHttp{ - Method: method, - Data: mapData, - Certs: request.TLS.PeerCertificates, - Headers: headers, + Method: method, + Data: mapData, + Certs: request.TLS.PeerCertificates, + Headers: headers, + ChangeContext: ctx, } } @@ -110,6 +114,10 @@ func (context *AuthContextHttp) GetCerts() []*x509.Certificate { return context.Certs } +func (context *AuthContextHttp) GetChangeContext() *change.Context { + return context.ChangeContext +} + var _ AuthResult = &AuthResultBase{} type AuthResultBase struct { diff --git a/controller/model/authenticator_manager.go b/controller/model/authenticator_manager.go index b062e123a..c46b280f2 100644 --- a/controller/model/authenticator_manager.go +++ b/controller/model/authenticator_manager.go @@ -28,6 +28,7 @@ import ( "github.com/openziti/edge/eid" edgeCert "github.com/openziti/edge/internal/cert" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -47,13 +48,13 @@ import ( const updateUnrestricted = 1 type AuthenticatorManager struct { - baseEntityManager + baseEntityManager[*Authenticator, *persistence.Authenticator] authStore persistence.AuthenticatorStore } func NewAuthenticatorManager(env Env) *AuthenticatorManager { manager := &AuthenticatorManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Authenticator), + baseEntityManager: newBaseEntityManager[*Authenticator, *persistence.Authenticator](env, env.GetStores().Authenticator), authStore: env.GetStores().Authenticator, } @@ -64,7 +65,7 @@ func NewAuthenticatorManager(env Env) *AuthenticatorManager { return manager } -func (self *AuthenticatorManager) newModelEntity() edgeEntity { +func (self *AuthenticatorManager) newModelEntity() *Authenticator { return &Authenticator{} } @@ -106,11 +107,11 @@ func (self *AuthenticatorManager) Read(id string) (*Authenticator, error) { return modelEntity, nil } -func (self *AuthenticatorManager) Create(entity *Authenticator) error { - return network.DispatchCreate[*Authenticator](self, entity) +func (self *AuthenticatorManager) Create(entity *Authenticator, ctx *change.Context) error { + return network.DispatchCreate[*Authenticator](self, entity, ctx) } -func (self *AuthenticatorManager) ApplyCreate(cmd *command.CreateEntityCommand[*Authenticator]) error { +func (self *AuthenticatorManager) ApplyCreate(cmd *command.CreateEntityCommand[*Authenticator], ctx boltz.MutateContext) error { authenticator := cmd.Entity if authenticator.Method != persistence.MethodAuthenticatorUpdb && authenticator.Method != persistence.MethodAuthenticatorCert { return errorz.NewFieldError("method must be updb or cert", "method", authenticator.Method) @@ -165,12 +166,13 @@ func (self *AuthenticatorManager) ApplyCreate(cmd *command.CreateEntityCommand[* } } - _, err = self.createEntity(authenticator) + _, err = self.createEntity(authenticator, ctx) return err } -func (self *AuthenticatorManager) Update(entity *Authenticator, unrestricted bool, checker fields.UpdatedFields) error { +func (self *AuthenticatorManager) Update(entity *Authenticator, unrestricted bool, checker fields.UpdatedFields, ctx *change.Context) error { cmd := &command.UpdateEntityCommand[*Authenticator]{ + Context: ctx, Updater: self, Entity: entity, UpdatedFields: checker, @@ -181,7 +183,7 @@ func (self *AuthenticatorManager) Update(entity *Authenticator, unrestricted boo return self.Dispatch(cmd) } -func (self *AuthenticatorManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Authenticator]) error { +func (self *AuthenticatorManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Authenticator], ctx boltz.MutateContext) error { authenticator := cmd.Entity if updb := authenticator.ToUpdb(); updb != nil { if cmd.UpdatedFields == nil || cmd.UpdatedFields.IsUpdated("password") { @@ -207,7 +209,7 @@ func (self *AuthenticatorManager) ApplyUpdate(cmd *command.UpdateEntityCommand[* checker = &AndFieldChecker{first: self, second: cmd.UpdatedFields} } } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *AuthenticatorManager) getRootPool() *x509.CertPool { @@ -216,16 +218,15 @@ func (self *AuthenticatorManager) getRootPool() *x509.CertPool { roots.AppendCertsFromPEM(self.env.GetConfig().CaPems()) err := self.env.GetManagers().Ca.Stream("isVerified = true", func(ca *Ca, err error) error { - if ca == nil && err == nil { - return nil - } - if err != nil { //continue on err pfxlog.Logger().Errorf("error streaming cas for authentication: %vs", err) return nil } - roots.AppendCertsFromPEM([]byte(ca.CertPem)) + + if ca != nil { + roots.AppendCertsFromPEM([]byte(ca.CertPem)) + } return nil }) @@ -281,7 +282,7 @@ func (self *AuthenticatorManager) ReadByFingerprint(fingerprint string) (*Authen return authenticator, nil } -func (self *AuthenticatorManager) UpdateSelf(authenticatorSelf *AuthenticatorSelf) error { +func (self *AuthenticatorManager) UpdateSelf(authenticatorSelf *AuthenticatorSelf, ctx *change.Context) error { authenticator, err := self.ReadForIdentity(authenticatorSelf.IdentityId, authenticatorSelf.Id) if err != nil { @@ -315,10 +316,10 @@ func (self *AuthenticatorManager) UpdateSelf(authenticatorSelf *AuthenticatorSel updbAuth.Salt = "" authenticator.SubType = updbAuth - return self.Update(authenticator, false, nil) + return self.Update(authenticator, false, nil, ctx) } -func (self *AuthenticatorManager) PatchSelf(authenticatorSelf *AuthenticatorSelf, checker fields.UpdatedFields) error { +func (self *AuthenticatorManager) PatchSelf(authenticatorSelf *AuthenticatorSelf, checker fields.UpdatedFields, ctx *change.Context) error { if checker.IsUpdated("password") { checker.AddField("salt") } @@ -356,7 +357,7 @@ func (self *AuthenticatorManager) PatchSelf(authenticatorSelf *AuthenticatorSelf updbAuth.Salt = "" authenticator.SubType = updbAuth - return self.Update(authenticator, false, checker) + return self.Update(authenticator, false, checker, ctx) } func (self *AuthenticatorManager) HashPassword(password string) *HashedPassword { @@ -383,31 +384,14 @@ func (self *AuthenticatorManager) ReHashPassword(password string, salt []byte) * } } -func (self *AuthenticatorManager) ListForIdentity(identityId string, query ast.Query) (*AuthenticatorListQueryResult, error) { +func (self *AuthenticatorManager) ListForIdentity(identityId string, query ast.Query) (*models.EntityListResult[*Authenticator], error) { filterString := fmt.Sprintf(`identity = "%s"`, identityId) filter, err := ast.Parse(self.Store, filterString) if err != nil { return nil, err } query.SetPredicate(ast.NewAndExprNode(query.GetPredicate(), filter)) - result, err := self.BasePreparedList(query) - - if err != nil { - return nil, err - } - - var authenticators []*Authenticator - - for _, entity := range result.GetEntities() { - if auth, ok := entity.(*Authenticator); ok { - authenticators = append(authenticators, auth) - } - } - - return &AuthenticatorListQueryResult{ - EntityListResult: result, - Authenticators: authenticators, - }, nil + return self.BasePreparedList(query) } func (self *AuthenticatorManager) ReadForIdentity(identityId string, authenticatorId string) (*Authenticator, error) { @@ -424,7 +408,7 @@ func (self *AuthenticatorManager) ReadForIdentity(identityId string, authenticat return nil, nil } -func (self *AuthenticatorManager) ExtendCertForIdentity(identityId string, authenticatorId string, peerCerts []*x509.Certificate, csrPem string) ([]byte, error) { +func (self *AuthenticatorManager) ExtendCertForIdentity(identityId string, authenticatorId string, peerCerts []*x509.Certificate, csrPem string, ctx *change.Context) ([]byte, error) { authenticator, _ := self.Read(authenticatorId) if authenticator == nil { @@ -527,7 +511,7 @@ func (self *AuthenticatorManager) ExtendCertForIdentity(identityId string, authe err = self.env.GetManagers().Authenticator.Update(authenticatorCert.Authenticator, false, fields.UpdatedFieldsMap{ persistence.FieldAuthenticatorUnverifiedCertPem: struct{}{}, persistence.FieldAuthenticatorUnverifiedCertFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return nil, err @@ -536,7 +520,7 @@ func (self *AuthenticatorManager) ExtendCertForIdentity(identityId string, authe return newPemCert, nil } -func (self *AuthenticatorManager) VerifyExtendCertForIdentity(apiSessionId, identityId, authenticatorId string, verifyCertPem string) error { +func (self *AuthenticatorManager) VerifyExtendCertForIdentity(apiSessionId, identityId, authenticatorId string, verifyCertPem string, ctx *change.Context) error { authenticator, _ := self.Read(authenticatorId) if authenticator == nil { @@ -590,7 +574,7 @@ func (self *AuthenticatorManager) VerifyExtendCertForIdentity(apiSessionId, iden persistence.FieldAuthenticatorCertPem: struct{}{}, persistence.FieldAuthenticatorCertFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return err @@ -608,30 +592,28 @@ func (self *AuthenticatorManager) VerifyExtendCertForIdentity(apiSessionId, iden PEM: verifyCertPem, } - return self.env.GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - err = self.env.GetStores().ApiSessionCertificate.Create(ctx, sessionCert) - - if err != nil { + return self.env.GetDbProvider().GetDb().Update(ctx.NewMutateContext(), func(mutateCtx boltz.MutateContext) error { + if err = self.env.GetStores().ApiSessionCertificate.Create(mutateCtx, sessionCert); err != nil { return err } - - err = self.env.GetStores().ApiSessionCertificate.DeleteWhere(ctx, fmt.Sprintf("%s=\"%s\"", persistence.FieldApiSessionCertificateFingerprint, oldFingerprint)) - - return err + return self.env.GetStores().ApiSessionCertificate.DeleteWhere(mutateCtx, fmt.Sprintf("%s=\"%s\"", persistence.FieldApiSessionCertificateFingerprint, oldFingerprint)) }) } // ReEnroll converts the given authenticator `id` back to an enrollment of the same type with the same // constraints that expires at the time specified by `expiresAt`. The result is a string id of the new enrollment // or an error. -func (self *AuthenticatorManager) ReEnroll(id string, expiresAt time.Time) (string, error) { +func (self *AuthenticatorManager) ReEnroll(id string, expiresAt time.Time, ctx *change.Context) (string, error) { authenticator, err := self.Read(id) if err != nil { return "", err } + enrollmentId := eid.New() enrollment := &Enrollment{ + BaseEntity: models.BaseEntity{ + Id: enrollmentId, + }, IdentityId: &authenticator.IdentityId, Token: uuid.NewString(), } @@ -660,14 +642,12 @@ func (self *AuthenticatorManager) ReEnroll(id string, expiresAt time.Time) (stri return "", err } - enrollmentId, err := self.env.GetManagers().Enrollment.createEntity(enrollment) - - if err != nil { + if err = self.env.GetManagers().Enrollment.Create(enrollment, ctx); err != nil { return "", err } - if err = self.Delete(id); err != nil { - _ = self.env.GetManagers().Enrollment.Delete(enrollmentId) + if err = self.Delete(id, ctx); err != nil { + _ = self.env.GetManagers().Enrollment.Delete(enrollmentId, ctx) return "", err } @@ -817,6 +797,6 @@ type HashedPassword struct { } type AuthenticatorListQueryResult struct { - *models.EntityListResult[models.Entity] + *models.EntityListResult[*Authenticator] Authenticators []*Authenticator } diff --git a/controller/model/authenticator_mod_cert.go b/controller/model/authenticator_mod_cert.go index fcb88e7fa..d8526ef22 100644 --- a/controller/model/authenticator_mod_cert.go +++ b/controller/model/authenticator_mod_cert.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/internal/cert" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" nfpem "github.com/openziti/foundation/v2/pem" @@ -220,7 +221,7 @@ func (module *AuthModuleCert) Process(context AuthContext) (AuthResult, error) { } if authenticator.Method == persistence.MethodAuthenticatorCert { - module.ensureAuthenticatorCertPem(authenticator, clientCert) + module.ensureAuthenticatorCertPem(authenticator, clientCert, context.GetChangeContext()) } return &AuthResultBase{ @@ -322,7 +323,7 @@ func (module *AuthModuleCert) getClientCerts(ctx AuthContext) ([]*x509.Certifica // ensureAuthenticatorCertPem ensures that a client's certificate is stored in `cert` authenticators. Older versions // of Ziti did not store this information on enrollment. -func (module *AuthModuleCert) ensureAuthenticatorCertPem(authenticator *Authenticator, clientCert *x509.Certificate) { +func (module *AuthModuleCert) ensureAuthenticatorCertPem(authenticator *Authenticator, clientCert *x509.Certificate, ctx *change.Context) { if authCert, ok := authenticator.SubType.(*AuthenticatorCert); ok { if authCert.Pem == "" { certPem := pem.EncodeToMemory(&pem.Block{ @@ -331,7 +332,7 @@ func (module *AuthModuleCert) ensureAuthenticatorCertPem(authenticator *Authenti }) authCert.Pem = string(certPem) - if err := module.env.GetManagers().Authenticator.Update(authenticator, false, nil); err != nil { + if err := module.env.GetManagers().Authenticator.Update(authenticator, false, nil, ctx); err != nil { pfxlog.Logger().WithError(err).Errorf("error during cert auth attempting to update PEM") } } diff --git a/controller/model/authenticator_mod_ext_jwt.go b/controller/model/authenticator_mod_ext_jwt.go index d456448f9..87a60e6b4 100644 --- a/controller/model/authenticator_mod_ext_jwt.go +++ b/controller/model/authenticator_mod_ext_jwt.go @@ -56,9 +56,9 @@ func NewAuthModuleExtJwt(env Env) *AuthModuleExtJwt { signers: cmap.New[*signerRecord](), } - env.GetStores().ExternalJwtSigner.AddListener(boltz.EventCreate, ret.onExternalSignerCreate) - env.GetStores().ExternalJwtSigner.AddListener(boltz.EventUpdate, ret.onExternalSignerUpdate) - env.GetStores().ExternalJwtSigner.AddListener(boltz.EventDelete, ret.onExternalSignerDelete) + env.GetStores().ExternalJwtSigner.AddEntityEventListenerF(ret.addSigner, boltz.EntityCreatedAsync) + env.GetStores().ExternalJwtSigner.AddEntityEventListenerF(ret.onExternalSignerUpdate, boltz.EntityUpdatedAsync) + env.GetStores().ExternalJwtSigner.AddEntityEventListenerF(ret.onExternalSignerDelete, boltz.EntityDeletedAsync) ret.loadExistingSigners() @@ -496,19 +496,11 @@ func (a *AuthModuleExtJwt) onExternalSignerCreate(args ...interface{}) { a.addSigner(signer) } -func (a *AuthModuleExtJwt) onExternalSignerUpdate(args ...interface{}) { - signer, ok := args[0].(*persistence.ExternalJwtSigner) - - if !ok { - pfxlog.Logger().Errorf("error on external signature update for authentication module %T: expected %T got %T", a, signer, args[0]) - return - } - +func (a *AuthModuleExtJwt) onExternalSignerUpdate(signer *persistence.ExternalJwtSigner) { //read on update because patches can pass partial data err := a.env.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { var err error - signer, err = a.env.GetStores().ExternalJwtSigner.LoadOneById(tx, signer.Id) - + signer, _, err = a.env.GetStores().ExternalJwtSigner.FindById(tx, signer.Id) return err }) @@ -546,14 +538,7 @@ func (a *AuthModuleExtJwt) addSigner(signer *persistence.ExternalJwtSigner) { } -func (a *AuthModuleExtJwt) onExternalSignerDelete(args ...interface{}) { - signer, ok := args[0].(*persistence.ExternalJwtSigner) - - if !ok { - pfxlog.Logger().Errorf("error on external signature update for authentication module %T: expected %T got %T", a, signer, args[0]) - return - } - +func (a *AuthModuleExtJwt) onExternalSignerDelete(signer *persistence.ExternalJwtSigner) { logger := pfxlog.Logger().WithFields(map[string]interface{}{ "id": signer.Id, "name": signer.Name, diff --git a/controller/model/authenticator_mod_updb.go b/controller/model/authenticator_mod_updb.go index f9d5896f3..c2ab2b55d 100644 --- a/controller/model/authenticator_mod_updb.go +++ b/controller/model/authenticator_mod_updb.go @@ -123,7 +123,8 @@ func (module *AuthModuleUpdb) Process(context AuthContext) (AuthResult, error) { if authPolicy.Primary.Updb.MaxAttempts != persistence.UpdbUnlimitedAttemptsLimit && attempts > authPolicy.Primary.Updb.MaxAttempts { logger.WithField("attempts", attempts).WithField("maxAttempts", authPolicy.Primary.Updb.MaxAttempts).Error("updb auth failed, max attempts exceeded") - if err = module.env.GetManagers().Identity.Disable(authenticator.IdentityId, time.Duration(authPolicy.Primary.Updb.LockoutDurationMinutes)*time.Minute); err != nil { + duration := time.Duration(authPolicy.Primary.Updb.LockoutDurationMinutes) * time.Minute + if err = module.env.GetManagers().Identity.Disable(authenticator.IdentityId, duration, context.GetChangeContext()); err != nil { logger.WithError(err).Error("could not lock identity, unhandled error") } diff --git a/controller/model/authenticator_model.go b/controller/model/authenticator_model.go index 11bc2a59e..7f632ec67 100644 --- a/controller/model/authenticator_model.go +++ b/controller/model/authenticator_model.go @@ -22,7 +22,6 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" "reflect" ) @@ -52,11 +51,7 @@ func (entity *Authenticator) Fingerprints() []string { } } -func (entity *Authenticator) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltAuthenticator, ok := boltEntity.(*persistence.Authenticator) - if !ok { - return errors.Errorf("unexpected type %v when filling model authenticator", reflect.TypeOf(boltEntity)) - } +func (entity *Authenticator) fillFrom(_ Env, _ *bbolt.Tx, boltAuthenticator *persistence.Authenticator) error { entity.FillCommon(boltAuthenticator) entity.Method = boltAuthenticator.Type entity.IdentityId = boltAuthenticator.IdentityId @@ -87,7 +82,7 @@ func (entity *Authenticator) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity b return nil } -func (entity *Authenticator) toBoltEntity() (boltz.Entity, error) { +func (entity *Authenticator) toBoltEntity() (*persistence.Authenticator, error) { boltEntity := &persistence.Authenticator{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Type: entity.Method, @@ -134,11 +129,11 @@ func (entity *Authenticator) toBoltEntity() (boltz.Entity, error) { return boltEntity, nil } -func (entity *Authenticator) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *Authenticator) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.Authenticator, error) { return entity.toBoltEntity() } -func (entity *Authenticator) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *Authenticator) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.Authenticator, error) { return entity.toBoltEntity() } diff --git a/controller/model/base_manager.go b/controller/model/base_manager.go index 4408f0c7d..604b61877 100644 --- a/controller/model/base_manager.go +++ b/controller/model/base_manager.go @@ -18,129 +18,127 @@ package model import ( "github.com/michaelquigley/pfxlog" - "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/models" - "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) const annotationsBucketName = "annotations" -type EntityManager interface { - models.EntityRetriever[models.Entity] +type EntityManager[E models.Entity] interface { + models.EntityRetriever[E] command.EntityDeleter GetEnv() Env - newModelEntity() edgeEntity - readEntityInTx(tx *bbolt.Tx, id string, modelEntity edgeEntity) error + newModelEntity() E + readEntityInTx(tx *bbolt.Tx, id string, modelEntity E) error } -func newBaseEntityManager(env Env, store boltz.CrudStore) baseEntityManager { - return baseEntityManager{ - BaseEntityManager: models.BaseEntityManager{ +func newBaseEntityManager[ME edgeEntity[PE], PE boltz.ExtEntity](env Env, store boltz.EntityStore[PE]) baseEntityManager[ME, PE] { + return baseEntityManager[ME, PE]{ + BaseEntityManager: models.BaseEntityManager[PE]{ Store: store, }, env: env, } } -type baseEntityManager struct { - models.BaseEntityManager +type baseEntityManager[ME edgeEntity[PE], PE boltz.ExtEntity] struct { + models.BaseEntityManager[PE] env Env - impl EntityManager + impl EntityManager[ME] } -func (self *baseEntityManager) Dispatch(command command.Command) error { +func (self *baseEntityManager[ME, PE]) Dispatch(command command.Command) error { return self.env.GetManagers().Command.Dispatch(command) } -func (self *baseEntityManager) GetEntityTypeId() string { +func (self *baseEntityManager[ME, PE]) GetEntityTypeId() string { // default this to the store entity type and let individual controllers override it where // needed to avoid collisions (e.g. edge service/router) return self.GetStore().GetEntityType() } -func (self *baseEntityManager) GetStore() boltz.CrudStore { +func (self *baseEntityManager[ME, PE]) GetStore() boltz.EntityStore[PE] { return self.Store } -func (self *baseEntityManager) GetDb() boltz.Db { +func (self *baseEntityManager[ME, PE]) GetDb() boltz.Db { return self.env.GetDbProvider().GetDb() } -func (self *baseEntityManager) GetEnv() Env { +func (self *baseEntityManager[ME, PE]) GetEnv() Env { return self.env } -func (self *baseEntityManager) BaseLoad(id string) (models.Entity, error) { +func (self *baseEntityManager[ME, PE]) BaseLoad(id string) (ME, error) { entity := self.impl.newModelEntity() if err := self.readEntity(id, entity); err != nil { - return nil, err + return *new(ME), err } return entity, nil } -func (self *baseEntityManager) BaseLoadInTx(tx *bbolt.Tx, id string) (models.Entity, error) { +func (self *baseEntityManager[ME, PE]) BaseLoadInTx(tx *bbolt.Tx, id string) (ME, error) { entity := self.impl.newModelEntity() if err := self.readEntityInTx(tx, id, entity); err != nil { - return nil, err + return *new(ME), err } return entity, nil } -func (self *baseEntityManager) BaseList(query string) (*models.EntityListResult[models.Entity], error) { - result := &models.EntityListResult[models.Entity]{Loader: self} +func (self *baseEntityManager[ME, PE]) BaseList(query string) (*models.EntityListResult[ME], error) { + result := &models.EntityListResult[ME]{Loader: self} if err := self.ListWithHandler(query, result.Collect); err != nil { return nil, err } return result, nil } -func (self *baseEntityManager) BasePreparedList(query ast.Query) (*models.EntityListResult[models.Entity], error) { - result := &models.EntityListResult[models.Entity]{Loader: self} +func (self *baseEntityManager[ME, PE]) BasePreparedList(query ast.Query) (*models.EntityListResult[ME], error) { + result := &models.EntityListResult[ME]{Loader: self} if err := self.PreparedListWithHandler(query, result.Collect); err != nil { return nil, err } return result, nil } -func (self *baseEntityManager) BasePreparedListIndexed(cursorProvider ast.SetCursorProvider, query ast.Query) (*models.EntityListResult[models.Entity], error) { - result := &models.EntityListResult[models.Entity]{Loader: self} +func (self *baseEntityManager[ME, PE]) BasePreparedListIndexed(cursorProvider ast.SetCursorProvider, query ast.Query) (*models.EntityListResult[ME], error) { + result := &models.EntityListResult[ME]{Loader: self} if err := self.PreparedListIndexed(cursorProvider, query, result.Collect); err != nil { return nil, err } return result, nil } -func (self *baseEntityManager) PreparedListWithHandler(query ast.Query, resultHandler models.ListResultHandler) error { +func (self *baseEntityManager[ME, PE]) PreparedListWithHandler(query ast.Query, resultHandler models.ListResultHandler) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.PreparedListWithTx(tx, query, resultHandler) }) } -func (self *baseEntityManager) PreparedListIndexed(cursorProvider ast.SetCursorProvider, query ast.Query, resultHandler models.ListResultHandler) error { +func (self *baseEntityManager[ME, PE]) PreparedListIndexed(cursorProvider ast.SetCursorProvider, query ast.Query, resultHandler models.ListResultHandler) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.PreparedListIndexedWithTx(tx, cursorProvider, query, resultHandler) }) } -func (self *baseEntityManager) PreparedListAssociatedWithHandler(id string, association string, query ast.Query, handler models.ListResultHandler) error { +func (self *baseEntityManager[ME, PE]) PreparedListAssociatedWithHandler(id string, association string, query ast.Query, handler models.ListResultHandler) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.PreparedListAssociatedWithTx(tx, id, association, query, handler) }) } -func (self *baseEntityManager) createEntity(modelEntity edgeEntity) (string, error) { +func (self *baseEntityManager[ME, PE]) createEntity(modelEntity edgeEntity[PE], ctx boltz.MutateContext) (string, error) { var id string - err := self.GetDb().Update(func(tx *bbolt.Tx) error { + err := self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { var err error - id, err = self.createEntityInTx(boltz.NewMutateContext(tx), modelEntity) + id, err = self.createEntityInTx(ctx, modelEntity) return err }) if err != nil { @@ -149,7 +147,7 @@ func (self *baseEntityManager) createEntity(modelEntity edgeEntity) (string, err return id, nil } -func (self *baseEntityManager) createEntityInTx(ctx boltz.MutateContext, modelEntity edgeEntity) (string, error) { +func (self *baseEntityManager[ME, PE]) createEntityInTx(ctx boltz.MutateContext, modelEntity edgeEntity[PE]) (string, error) { if modelEntity == nil { return "", errors.Errorf("can't create %v with nil value", self.Store.GetEntityType()) } @@ -157,12 +155,12 @@ func (self *baseEntityManager) createEntityInTx(ctx boltz.MutateContext, modelEn modelEntity.SetId(eid.New()) } - boltEntity, err := modelEntity.toBoltEntityForCreate(ctx.Tx(), self.impl) + boltEntity, err := modelEntity.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return "", err } - if err = self.ValidateNameOnCreate(ctx, boltEntity); err != nil { + if err = self.ValidateNameOnCreate(ctx.Tx(), boltEntity); err != nil { return "", err } @@ -174,37 +172,22 @@ func (self *baseEntityManager) createEntityInTx(ctx boltz.MutateContext, modelEn return modelEntity.GetId(), nil } -func (self *baseEntityManager) updateEntityBatch(modelEntity edgeEntity, checker boltz.FieldChecker) error { - return self.GetDb().Batch(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - existing := self.GetStore().NewStoreEntity() - found, err := self.GetStore().BaseLoadOneById(tx, modelEntity.GetId(), existing) +func (self *baseEntityManager[ME, PE]) updateEntityBatch(modelEntity edgeEntity[PE], checker boltz.FieldChecker, changeCtx *change.Context) error { + return self.GetDb().Batch(changeCtx.NewMutateContext(), func(ctx boltz.MutateContext) error { + existing, found, err := self.GetStore().FindById(ctx.Tx(), modelEntity.GetId()) if err != nil { return err } if !found { return boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), "id", modelEntity.GetId()) } - boltEntity, err := modelEntity.toBoltEntityForUpdate(tx, self.impl, checker) + boltEntity, err := modelEntity.toBoltEntityForUpdate(ctx.Tx(), self.env, checker) if err != nil { return err } - // validate name for named entities - if namedEntity, ok := boltEntity.(boltz.NamedExtEntity); ok { - existingNamed := existing.(boltz.NamedExtEntity) - if (checker == nil || checker.IsUpdated("name")) && namedEntity.GetName() != existingNamed.GetName() { - if namedEntity.GetName() == "" { - return errorz.NewFieldError("name is required", "name", namedEntity.GetName()) - } - if nameIndexStore, ok := self.GetStore().(persistence.NameIndexedStore); ok { - if nameIndexStore.GetNameIndex().Read(ctx.Tx(), []byte(namedEntity.GetName())) != nil { - return errorz.NewFieldError("name is must be unique", "name", namedEntity.GetName()) - } - } else { - pfxlog.Logger().Errorf("batch: entity of type %v is named, but store doesn't have name index", reflect.TypeOf(boltEntity)) - } - } + if err = self.ValidateNameOnUpdate(ctx, boltEntity, existing, checker); err != nil { + return nil } if err := self.GetStore().Update(ctx, boltEntity, checker); err != nil { @@ -215,37 +198,23 @@ func (self *baseEntityManager) updateEntityBatch(modelEntity edgeEntity, checker }) } -func (self *baseEntityManager) updateEntity(modelEntity edgeEntity, checker boltz.FieldChecker) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - existing := self.GetStore().NewStoreEntity() - found, err := self.GetStore().BaseLoadOneById(tx, modelEntity.GetId(), existing) +func (self *baseEntityManager[ME, PE]) updateEntity(modelEntity ME, checker boltz.FieldChecker, ctx boltz.MutateContext) error { + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + existing, found, err := self.GetStore().FindById(ctx.Tx(), modelEntity.GetId()) if err != nil { return err } if !found { return boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), "id", modelEntity.GetId()) } - boltEntity, err := modelEntity.toBoltEntityForUpdate(tx, self.impl, checker) + + boltEntity, err := modelEntity.toBoltEntityForUpdate(ctx.Tx(), self.env, checker) if err != nil { return err } - // validate name for named entities - if namedEntity, ok := boltEntity.(boltz.NamedExtEntity); ok { - existingNamed := existing.(boltz.NamedExtEntity) - if (checker == nil || checker.IsUpdated("name")) && namedEntity.GetName() != existingNamed.GetName() { - if namedEntity.GetName() == "" { - return errorz.NewFieldError("name is required", "name", namedEntity.GetName()) - } - if nameIndexStore, ok := self.GetStore().(persistence.NameIndexedStore); ok { - if nameIndexStore.GetNameIndex().Read(ctx.Tx(), []byte(namedEntity.GetName())) != nil { - return errorz.NewFieldError("name is must be unique", "name", namedEntity.GetName()) - } - } else { - pfxlog.Logger().Errorf("entity of type %v is named, but store doesn't have name index", reflect.TypeOf(boltEntity)) - } - } + if err = self.ValidateNameOnUpdate(ctx, boltEntity, existing, checker); err != nil { + return nil } if err := self.GetStore().Update(ctx, boltEntity, checker); err != nil { @@ -256,15 +225,34 @@ func (self *baseEntityManager) updateEntity(modelEntity edgeEntity, checker bolt }) } -func (self *baseEntityManager) readEntity(id string, modelEntity edgeEntity) error { +func (self *baseEntityManager[ME, PE]) Read(id string) (ME, error) { + modelEntity := self.impl.newModelEntity() + err := self.GetDb().View(func(tx *bbolt.Tx) error { + return self.readEntityInTx(tx, id, modelEntity) + }) + if err != nil { + return *new(ME), err + } + return modelEntity, nil +} + +func (self *baseEntityManager[ME, PE]) readInTx(tx *bbolt.Tx, id string) (ME, error) { + modelEntity := self.impl.newModelEntity() + if err := self.readEntityInTx(tx, id, modelEntity); err != nil { + return *new(ME), err + } + return modelEntity, nil +} + +func (self *baseEntityManager[ME, PE]) readEntity(id string, modelEntity ME) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.readEntityInTx(tx, id, modelEntity) }) } -func (self *baseEntityManager) readEntityInTx(tx *bbolt.Tx, id string, modelEntity edgeEntity) error { - boltEntity := self.GetStore().NewStoreEntity() - found, err := self.GetStore().BaseLoadOneById(tx, id, boltEntity) +func (self *baseEntityManager[ME, PE]) readEntityInTx(tx *bbolt.Tx, id string, modelEntity ME) error { + boltEntity := self.GetStore().GetEntityStrategy().NewEntity() + found, err := self.GetStore().LoadEntity(tx, id, boltEntity) if err != nil { return err } @@ -272,16 +260,16 @@ func (self *baseEntityManager) readEntityInTx(tx *bbolt.Tx, id string, modelEnti return boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), "id", id) } - return modelEntity.fillFrom(self.impl, tx, boltEntity) + return modelEntity.fillFrom(self.env, tx, boltEntity) } -func (self *baseEntityManager) readEntityWithIndex(name string, key []byte, index boltz.ReadIndex, modelEntity edgeEntity) error { +func (self *baseEntityManager[ME, PE]) readEntityWithIndex(name string, key []byte, index boltz.ReadIndex, modelEntity ME) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.readEntityInTxWithIndex(name, tx, key, index, modelEntity) }) } -func (self *baseEntityManager) readEntityInTxWithIndex(name string, tx *bbolt.Tx, key []byte, index boltz.ReadIndex, modelEntity edgeEntity) error { +func (self *baseEntityManager[ME, PE]) readEntityInTxWithIndex(name string, tx *bbolt.Tx, key []byte, index boltz.ReadIndex, modelEntity ME) error { id := index.Read(tx, key) if id == nil { return boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), name, string(key)) @@ -289,7 +277,7 @@ func (self *baseEntityManager) readEntityInTxWithIndex(name string, tx *bbolt.Tx return self.readEntityInTx(tx, string(id), modelEntity) } -func (self *baseEntityManager) readEntityByQuery(query string) (models.Entity, error) { +func (self *baseEntityManager[ME, PE]) readEntityByQuery(query string) (models.Entity, error) { result, err := self.BaseList(query) if err != nil { return nil, err @@ -300,31 +288,31 @@ func (self *baseEntityManager) readEntityByQuery(query string) (models.Entity, e return nil, nil } -func (self *baseEntityManager) Delete(id string) error { +func (self *baseEntityManager[ME, PE]) Delete(id string, ctx *change.Context) error { cmd := &command.DeleteEntityCommand{ + Context: ctx, Deleter: self.impl, // needs to be impl, otherwise we will miss overrides to GetEntityTypeId Id: id, } return self.Dispatch(cmd) } -func (self *baseEntityManager) ApplyDelete(cmd *command.DeleteEntityCommand) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) +func (self *baseEntityManager[ME, PE]) ApplyDelete(cmd *command.DeleteEntityCommand, ctx boltz.MutateContext) error { + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { return self.Store.DeleteById(ctx, cmd.Id) }) } -func (self *baseEntityManager) deleteEntity(id string) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - return self.GetStore().DeleteById(boltz.NewMutateContext(tx), id) +func (self *baseEntityManager[ME, PE]) deleteEntity(id string, changeCtx *change.Context) error { + return self.GetDb().Update(changeCtx.NewMutateContext(), func(ctx boltz.MutateContext) error { + return self.GetStore().DeleteById(ctx, id) }) } -func (self *baseEntityManager) deleteEntityBatch(ids []string) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { +func (self *baseEntityManager[ME, PE]) deleteEntityBatch(ids []string, changeCtx *change.Context) error { + return self.GetDb().Update(changeCtx.NewMutateContext(), func(ctx boltz.MutateContext) error { for _, id := range ids { - if err := self.GetStore().DeleteById(boltz.NewMutateContext(tx), id); err != nil { + if err := self.GetStore().DeleteById(ctx, id); err != nil { return err } } @@ -332,13 +320,13 @@ func (self *baseEntityManager) deleteEntityBatch(ids []string) error { }) } -func (self *baseEntityManager) ListWithHandler(queryString string, resultHandler models.ListResultHandler) error { +func (self *baseEntityManager[ME, PE]) ListWithHandler(queryString string, resultHandler models.ListResultHandler) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.ListWithTx(tx, queryString, resultHandler) }) } -func (self *baseEntityManager) queryRoleAttributes(index boltz.SetReadIndex, queryString string) ([]string, *models.QueryMetaData, error) { +func (self *baseEntityManager[ME, PE]) queryRoleAttributes(index boltz.SetReadIndex, queryString string) ([]string, *models.QueryMetaData, error) { query, err := ast.Parse(self.env.GetStores().Index, queryString) if err != nil { return nil, nil, err @@ -365,13 +353,13 @@ func (self *baseEntityManager) queryRoleAttributes(index boltz.SetReadIndex, que return results, qmd, nil } -func (self *baseEntityManager) iterateRelatedEntities(id, field string, f func(tx *bbolt.Tx, relatedId string) error) error { +func (self *baseEntityManager[ME, PE]) iterateRelatedEntities(id, field string, f func(tx *bbolt.Tx, relatedId string) error) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.iterateRelatedEntitiesInTx(tx, id, field, f) }) } -func (self *baseEntityManager) iterateRelatedEntitiesInTx(tx *bbolt.Tx, id, field string, f func(tx *bbolt.Tx, relatedId string) error) error { +func (self *baseEntityManager[ME, PE]) iterateRelatedEntitiesInTx(tx *bbolt.Tx, id, field string, f func(tx *bbolt.Tx, relatedId string) error) error { cursor := self.Store.GetRelatedEntitiesCursor(tx, id, field, true) for cursor.IsValid() { key := cursor.Current() @@ -383,7 +371,7 @@ func (self *baseEntityManager) iterateRelatedEntitiesInTx(tx *bbolt.Tx, id, fiel return nil } -func (self *baseEntityManager) Annotate(ctx boltz.MutateContext, entityId string, key, value string) error { +func (self *baseEntityManager[ME, PE]) Annotate(ctx boltz.MutateContext, entityId string, key, value string) error { entityBucket := self.GetStore().GetEntityBucket(ctx.Tx(), []byte(entityId)) if entityBucket == nil { return boltz.NewNotFoundError(self.GetStore().GetEntityType(), "id", entityId) @@ -393,7 +381,7 @@ func (self *baseEntityManager) Annotate(ctx boltz.MutateContext, entityId string return annotationsBucket.GetError() } -func (self *baseEntityManager) GetAnnotation(entityId string, key string) (*string, error) { +func (self *baseEntityManager[ME, PE]) GetAnnotation(entityId string, key string) (*string, error) { var result *string err := self.GetDb().View(func(tx *bbolt.Tx) error { entityBucket := self.GetStore().GetEntityBucket(tx, []byte(entityId)) diff --git a/controller/model/base_model.go b/controller/model/base_model.go index bbfdb6604..7786973c5 100644 --- a/controller/model/base_model.go +++ b/controller/model/base_model.go @@ -22,9 +22,9 @@ import ( "go.etcd.io/bbolt" ) -type edgeEntity interface { +type edgeEntity[PE boltz.ExtEntity] interface { models.Entity - fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error - toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) - toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) + fillFrom(env Env, tx *bbolt.Tx, boltEntity PE) error + toBoltEntityForCreate(tx *bbolt.Tx, env Env) (PE, error) + toBoltEntityForUpdate(tx *bbolt.Tx, env Env, checker boltz.FieldChecker) (PE, error) } diff --git a/controller/model/ca_manager.go b/controller/model/ca_manager.go index 1e0882f1b..ab9d0b01a 100644 --- a/controller/model/ca_manager.go +++ b/controller/model/ca_manager.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -33,7 +34,7 @@ import ( func NewCaManager(env Env) *CaManager { manager := &CaManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Ca), + baseEntityManager: newBaseEntityManager[*Ca, *persistence.Ca](env, env.GetStores().Ca), } manager.impl = manager @@ -43,30 +44,30 @@ func NewCaManager(env Env) *CaManager { } type CaManager struct { - baseEntityManager + baseEntityManager[*Ca, *persistence.Ca] } -func (self *CaManager) newModelEntity() edgeEntity { +func (self *CaManager) newModelEntity() *Ca { return &Ca{} } -func (self *CaManager) Create(entity *Ca) error { - return network.DispatchCreate[*Ca](self, entity) +func (self *CaManager) Create(entity *Ca, ctx *change.Context) error { + return network.DispatchCreate[*Ca](self, entity, ctx) } -func (self *CaManager) ApplyCreate(cmd *command.CreateEntityCommand[*Ca]) error { - _, err := self.createEntity(cmd.Entity) +func (self *CaManager) ApplyCreate(cmd *command.CreateEntityCommand[*Ca], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *CaManager) Update(entity *Ca, checker fields.UpdatedFields) error { +func (self *CaManager) Update(entity *Ca, checker fields.UpdatedFields, ctx *change.Context) error { if checker != nil { checker.RemoveFields(persistence.FieldCaIsVerified) } - return network.DispatchUpdate[*Ca](self, entity, checker) + return network.DispatchUpdate[*Ca](self, entity, checker, ctx) } -func (self *CaManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Ca]) error { +func (self *CaManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Ca], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = self // isVerified should only be set by the Verified method. We remove isVerified @@ -79,7 +80,7 @@ func (self *CaManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Ca]) error } } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *CaManager) Read(id string) (*Ca, error) { @@ -109,12 +110,12 @@ func (self *CaManager) IsUpdated(field string) bool { strings.HasPrefix(field, persistence.FieldCaExternalIdClaim+".") } -func (self *CaManager) Verified(ca *Ca) error { +func (self *CaManager) Verified(ca *Ca, ctx *change.Context) error { ca.IsVerified = true checker := &fields.UpdatedFieldsMap{ persistence.FieldCaIsVerified: struct{}{}, } - return network.DispatchUpdate[*Ca](self, ca, checker) + return network.DispatchUpdate[*Ca](self, ca, checker, ctx) } func (self *CaManager) Query(query string) (*CaListResult, error) { diff --git a/controller/model/ca_model.go b/controller/model/ca_model.go index e15aa2d8c..6753866f5 100644 --- a/controller/model/ca_model.go +++ b/controller/model/ca_model.go @@ -30,7 +30,6 @@ import ( "github.com/pkg/errors" "go.etcd.io/bbolt" "net/url" - "reflect" ) type Ca struct { @@ -59,11 +58,7 @@ type ExternalIdClaim struct { type ExternalIdFieldType string -func (entity *Ca) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltCa, ok := boltEntity.(*persistence.Ca) - if !ok { - return errors.Errorf("unexpected type %v when filling model ca", reflect.TypeOf(boltEntity)) - } +func (entity *Ca) fillFrom(_ Env, _ *bbolt.Tx, boltCa *persistence.Ca) error { entity.FillCommon(boltCa) entity.Name = boltCa.Name entity.Fingerprint = boltCa.Fingerprint @@ -89,7 +84,7 @@ func (entity *Ca) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity return nil } -func (entity *Ca) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { +func (entity *Ca) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.Ca, error) { if entity.IdentityNameFormat == "" { entity.IdentityNameFormat = DefaultCaIdentityNameFormat } @@ -137,7 +132,7 @@ func (entity *Ca) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (bo } query := fmt.Sprintf(`fingerprint = "%v"`, fp) - queryResults, _, err := manager.GetEnv().GetStores().Ca.QueryIds(tx, query) + queryResults, _, err := env.GetStores().Ca.QueryIds(tx, query) if err != nil { return nil, err @@ -174,7 +169,7 @@ func (entity *Ca) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (bo return boltEntity, nil } -func (entity *Ca) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *Ca) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.Ca, error) { if entity.IdentityNameFormat == "" { entity.IdentityNameFormat = DefaultCaIdentityNameFormat } diff --git a/controller/model/config_manager.go b/controller/model/config_manager.go index 134c3a514..355cd6d73 100644 --- a/controller/model/config_manager.go +++ b/controller/model/config_manager.go @@ -18,7 +18,9 @@ package model import ( "encoding/json" + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -31,7 +33,7 @@ import ( func NewConfigManager(env Env) *ConfigManager { manager := &ConfigManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Config), + baseEntityManager: newBaseEntityManager[*Config, *persistence.Config](env, env.GetStores().Config), } manager.impl = manager @@ -41,32 +43,32 @@ func NewConfigManager(env Env) *ConfigManager { } type ConfigManager struct { - baseEntityManager + baseEntityManager[*Config, *persistence.Config] } -func (self *ConfigManager) newModelEntity() edgeEntity { +func (self *ConfigManager) newModelEntity() *Config { return &Config{} } -func (self *ConfigManager) Create(entity *Config) error { - return network.DispatchCreate[*Config](self, entity) +func (self *ConfigManager) Create(entity *Config, ctx *change.Context) error { + return network.DispatchCreate[*Config](self, entity, ctx) } -func (self *ConfigManager) ApplyCreate(cmd *command.CreateEntityCommand[*Config]) error { - _, err := self.createEntity(cmd.Entity) +func (self *ConfigManager) ApplyCreate(cmd *command.CreateEntityCommand[*Config], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *ConfigManager) Update(entity *Config, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*Config](self, entity, checker) +func (self *ConfigManager) Update(entity *Config, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*Config](self, entity, checker, ctx) } -func (self *ConfigManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Config]) error { +func (self *ConfigManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Config], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = self if cmd.UpdatedFields != nil { checker = &AndFieldChecker{first: self, second: cmd.UpdatedFields} } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *ConfigManager) Read(id string) (*Config, error) { diff --git a/controller/model/config_model.go b/controller/model/config_model.go index 735a8147f..501c77bdd 100644 --- a/controller/model/config_model.go +++ b/controller/model/config_model.go @@ -22,10 +22,8 @@ import ( "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "github.com/xeipuuv/gojsonschema" "go.etcd.io/bbolt" - "reflect" ) type Config struct { @@ -35,24 +33,24 @@ type Config struct { Data map[string]interface{} } -func (entity *Config) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { +func (entity *Config) toBoltEntity(tx *bbolt.Tx, env Env) (*persistence.Config, error) { if entity.TypeId != "" { providedType := entity.TypeId - configTypeStore := manager.GetEnv().GetStores().ConfigType + configTypeStore := env.GetStores().ConfigType if !configTypeStore.IsEntityPresent(tx, entity.TypeId) { return nil, errorz.NewFieldError("invalid config type", persistence.FieldConfigType, providedType) } } if entity.TypeId == "" { - currentConfig, err := manager.GetEnv().GetManagers().Config.readInTx(tx, entity.Id) + currentConfig, err := env.GetManagers().Config.readInTx(tx, entity.Id) if err != nil { return nil, err } entity.TypeId = currentConfig.TypeId } - if configType, _ := manager.GetEnv().GetManagers().ConfigType.readInTx(tx, entity.TypeId); configType != nil && len(configType.Schema) > 0 { + if configType, _ := env.GetManagers().ConfigType.readInTx(tx, entity.TypeId); configType != nil && len(configType.Schema) > 0 { compileSchema, err := configType.GetCompiledSchema() if err != nil { return nil, err @@ -75,23 +73,18 @@ func (entity *Config) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.E }, nil } -func (entity *Config) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { +func (entity *Config) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.Config, error) { if entity.TypeId == "" { return nil, errorz.NewFieldError("config type must be specified", persistence.FieldConfigType, entity.TypeId) } - return entity.toBoltEntity(tx, manager) + return entity.toBoltEntity(tx, env) } -func (entity *Config) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *Config) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.Config, error) { + return entity.toBoltEntity(tx, env) } -func (entity *Config) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltConfig, ok := boltEntity.(*persistence.Config) - if !ok { - return errors.Errorf("unexpected type %v when filling model config", reflect.TypeOf(boltEntity)) - } - +func (entity *Config) fillFrom(_ Env, _ *bbolt.Tx, boltConfig *persistence.Config) error { entity.FillCommon(boltConfig) entity.Name = boltConfig.Name entity.TypeId = boltConfig.Type diff --git a/controller/model/config_type_manager.go b/controller/model/config_type_manager.go index e33bef9c4..8d993b582 100644 --- a/controller/model/config_type_manager.go +++ b/controller/model/config_type_manager.go @@ -19,12 +19,15 @@ package model import ( "encoding/json" "github.com/michaelquigley/pfxlog" + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/storage/boltz" "go.etcd.io/bbolt" "google.golang.org/protobuf/proto" ) @@ -35,7 +38,7 @@ const ( func NewConfigTypeManager(env Env) *ConfigTypeManager { manager := &ConfigTypeManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ConfigType), + baseEntityManager: newBaseEntityManager[*ConfigType, *persistence.ConfigType](env, env.GetStores().ConfigType), } manager.impl = manager @@ -45,28 +48,28 @@ func NewConfigTypeManager(env Env) *ConfigTypeManager { } type ConfigTypeManager struct { - baseEntityManager + baseEntityManager[*ConfigType, *persistence.ConfigType] } -func (self *ConfigTypeManager) newModelEntity() edgeEntity { +func (self *ConfigTypeManager) newModelEntity() *ConfigType { return &ConfigType{} } -func (self *ConfigTypeManager) Create(entity *ConfigType) error { - return network.DispatchCreate[*ConfigType](self, entity) +func (self *ConfigTypeManager) Create(entity *ConfigType, ctx *change.Context) error { + return network.DispatchCreate[*ConfigType](self, entity, ctx) } -func (self *ConfigTypeManager) ApplyCreate(cmd *command.CreateEntityCommand[*ConfigType]) error { - _, err := self.createEntity(cmd.Entity) +func (self *ConfigTypeManager) ApplyCreate(cmd *command.CreateEntityCommand[*ConfigType], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *ConfigTypeManager) Update(entity *ConfigType, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*ConfigType](self, entity, checker) +func (self *ConfigTypeManager) Update(entity *ConfigType, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*ConfigType](self, entity, checker, ctx) } -func (self *ConfigTypeManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ConfigType]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) +func (self *ConfigTypeManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ConfigType], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *ConfigTypeManager) Read(id string) (*ConfigType, error) { diff --git a/controller/model/config_type_model.go b/controller/model/config_type_model.go index 498c54b68..2c4a443fa 100644 --- a/controller/model/config_type_model.go +++ b/controller/model/config_type_model.go @@ -25,7 +25,6 @@ import ( "github.com/pkg/errors" "github.com/xeipuuv/gojsonschema" "go.etcd.io/bbolt" - "reflect" ) type ConfigType struct { @@ -43,7 +42,7 @@ func (entity *ConfigType) GetCompiledSchema() (*gojsonschema.Schema, error) { return schemaLoader.Compile(entitySchemaLoader) } -func (entity *ConfigType) toBoltEntity() (boltz.Entity, error) { +func (entity *ConfigType) toBoltEntity() (*persistence.ConfigType, error) { if entity.Name == ConfigTypeAll { return nil, errorz.NewFieldError(fmt.Sprintf("%v is a keyword and may not be used as a config type name", entity.Name), "name", entity.Name) } @@ -63,20 +62,15 @@ func (entity *ConfigType) toBoltEntity() (boltz.Entity, error) { }, nil } -func (entity *ConfigType) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *ConfigType) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.ConfigType, error) { return entity.toBoltEntity() } -func (entity *ConfigType) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ConfigType) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.ConfigType, error) { return entity.toBoltEntity() } -func (entity *ConfigType) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltConfigType, ok := boltEntity.(*persistence.ConfigType) - if !ok { - return errors.Errorf("unexpected type %v when filling model configType", reflect.TypeOf(boltEntity)) - } - +func (entity *ConfigType) fillFrom(_ Env, _ *bbolt.Tx, boltConfigType *persistence.ConfigType) error { entity.FillCommon(boltConfigType) entity.Name = boltConfigType.Name entity.Schema = boltConfigType.Schema diff --git a/controller/model/create_terminator_cmd.go b/controller/model/create_terminator_cmd.go index 12626f351..817c2d9f2 100644 --- a/controller/model/create_terminator_cmd.go +++ b/controller/model/create_terminator_cmd.go @@ -5,29 +5,34 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/edge_common" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/network" "github.com/openziti/fabric/pb/cmd_pb" + "github.com/openziti/storage/boltz" "github.com/pkg/errors" "go.etcd.io/bbolt" "strings" ) type CreateEdgeTerminatorCmd struct { - Env Env - Entity *network.Terminator + Env Env + Entity *network.Terminator + Context *change.Context } -func (self *CreateEdgeTerminatorCmd) Apply() error { +func (self *CreateEdgeTerminatorCmd) Apply(ctx boltz.MutateContext) error { createCmd := &command.CreateEntityCommand[*network.Terminator]{ Creator: self.Env.GetManagers().Terminator, Entity: self.Entity, PostCreateHook: self.validateTerminatorIdentity, + Context: self.Context, } - return self.Env.GetManagers().Terminator.ApplyCreate(createCmd) + return self.Env.GetManagers().Terminator.ApplyCreate(createCmd, ctx) } -func (self *CreateEdgeTerminatorCmd) validateTerminatorIdentity(tx *bbolt.Tx, terminator *network.Terminator) error { +func (self *CreateEdgeTerminatorCmd) validateTerminatorIdentity(ctx boltz.MutateContext, terminator *network.Terminator) error { + tx := ctx.Tx() session, err := self.getTerminatorSession(tx, terminator, "") if err != nil { return err @@ -57,6 +62,10 @@ func (self *CreateEdgeTerminatorCmd) validateTerminatorIdentity(tx *bbolt.Tx, te return nil } +func (self *CreateEdgeTerminatorCmd) GetChangeContext() *change.Context { + return self.Context +} + type terminator interface { GetId() string GetInstanceId() string @@ -103,6 +112,7 @@ func (self *CreateEdgeTerminatorCmd) Encode() ([]byte, error) { } cmd := &edge_cmd_pb.CreateEdgeTerminatorCommand{ TerminatorData: terminatorData, + Ctx: ContextToProtobuf(self.Context), } return cmd_pb.EncodeProtobuf(cmd) } @@ -111,5 +121,6 @@ func (self *CreateEdgeTerminatorCmd) Decode(env Env, msg *edge_cmd_pb.CreateEdge var err error self.Env = env self.Entity, err = env.GetManagers().Terminator.Unmarshall(msg.TerminatorData) + self.Context = ProtobufToContext(msg.Ctx) return err } diff --git a/controller/model/edge_router_manager.go b/controller/model/edge_router_manager.go index cc50f465f..e2a20d963 100644 --- a/controller/model/edge_router_manager.go +++ b/controller/model/edge_router_manager.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/openziti/edge/eid" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/network" @@ -41,7 +42,7 @@ import ( func NewEdgeRouterManager(env Env) *EdgeRouterManager { manager := &EdgeRouterManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().EdgeRouter), + baseEntityManager: newBaseEntityManager[*EdgeRouter, *persistence.EdgeRouter](env, env.GetStores().EdgeRouter), allowedFieldsChecker: fields.UpdatedFieldsMap{ persistence.FieldName: struct{}{}, persistence.FieldEdgeRouterIsTunnelerEnabled: struct{}{}, @@ -63,7 +64,7 @@ func NewEdgeRouterManager(env Env) *EdgeRouterManager { } type EdgeRouterManager struct { - baseEntityManager + baseEntityManager[*EdgeRouter, *persistence.EdgeRouter] allowedFieldsChecker fields.UpdatedFieldsMap } @@ -71,11 +72,11 @@ func (self *EdgeRouterManager) GetEntityTypeId() string { return "edgeRouters" } -func (self *EdgeRouterManager) newModelEntity() edgeEntity { +func (self *EdgeRouterManager) newModelEntity() *EdgeRouter { return &EdgeRouter{} } -func (self *EdgeRouterManager) Create(edgeRouter *EdgeRouter) error { +func (self *EdgeRouterManager) Create(edgeRouter *EdgeRouter, ctx *change.Context) error { if edgeRouter.Id == "" { edgeRouter.Id = eid.New() } @@ -90,23 +91,23 @@ func (self *EdgeRouterManager) Create(edgeRouter *EdgeRouter) error { manager: self, edgeRouter: edgeRouter, enrollment: enrollment, + ctx: ctx, } return self.Dispatch(cmd) } -func (self *EdgeRouterManager) ApplyCreate(cmd *CreateEdgeRouterCmd) error { +func (self *EdgeRouterManager) ApplyCreate(cmd *CreateEdgeRouterCmd, ctx boltz.MutateContext) error { edgeRouter := cmd.edgeRouter enrollment := cmd.enrollment - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - boltEdgeRouter, err := edgeRouter.toBoltEntityForCreate(tx, self.impl) + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + boltEdgeRouter, err := edgeRouter.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return err } - if err = self.ValidateNameOnCreate(ctx, boltEdgeRouter); err != nil { + if err = self.ValidateNameOnCreate(ctx.Tx(), boltEdgeRouter); err != nil { return err } @@ -124,11 +125,12 @@ func (self *EdgeRouterManager) ApplyCreate(cmd *CreateEdgeRouterCmd) error { }) } -func (self *EdgeRouterManager) Update(entity *EdgeRouter, unrestricted bool, checker fields.UpdatedFields) error { +func (self *EdgeRouterManager) Update(entity *EdgeRouter, unrestricted bool, checker fields.UpdatedFields, ctx *change.Context) error { cmd := &command.UpdateEntityCommand[*EdgeRouter]{ Updater: self, Entity: entity, UpdatedFields: checker, + Context: ctx, } if unrestricted { cmd.Flags = updateUnrestricted @@ -136,7 +138,7 @@ func (self *EdgeRouterManager) Update(entity *EdgeRouter, unrestricted bool, che return self.Dispatch(cmd) } -func (self *EdgeRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*EdgeRouter]) error { +func (self *EdgeRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*EdgeRouter], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = cmd.UpdatedFields if cmd.Flags != updateUnrestricted { if checker == nil { @@ -145,7 +147,7 @@ func (self *EdgeRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Edg checker = &AndFieldChecker{first: self.allowedFieldsChecker, second: cmd.UpdatedFields} } } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *EdgeRouterManager) Read(id string) (*EdgeRouter, error) { @@ -289,12 +291,14 @@ func (self *EdgeRouterManager) collectEnrollmentsInTx(tx *bbolt.Tx, id string, c // ReEnroll creates a new JWT enrollment for an existing edge router. If the edge router already exists // with a JWT, a new JWT is created. If the edge router was already enrolled, all record of the enrollment is // reset and the edge router is disconnected forcing the edge router to complete enrollment before connecting. -func (self *EdgeRouterManager) ReEnroll(router *EdgeRouter) error { +func (self *EdgeRouterManager) ReEnroll(router *EdgeRouter, ctx *change.Context) error { log := pfxlog.Logger().WithField("routerId", router.Id) log.Info("attempting to set edge router state to unenrolled") enrollment := &Enrollment{ - BaseEntity: models.BaseEntity{}, + BaseEntity: models.BaseEntity{ + Id: eid.New(), + }, Method: MethodEnrollEdgeRouterOtt, EdgeRouterId: &router.Id, } @@ -303,29 +307,21 @@ func (self *EdgeRouterManager) ReEnroll(router *EdgeRouter) error { return fmt.Errorf("unable to fill jwt info for re-enrolling edge router: %v", err) } - err := self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - if id, err := self.GetEnv().GetManagers().Enrollment.createEntityInTx(ctx, enrollment); err != nil { - return fmt.Errorf("could not create enrollment for re-enrolling edge router: %v", err) - } else { - log.WithField("enrollmentId", id).Infof("edge router re-enrollment entity created") - } - router.Fingerprint = nil - router.CertPem = nil - router.IsVerified = false - - return nil - }) - - if err != nil { - return fmt.Errorf("unabled to alter db for re-enrolling edge router: %v", err) + if err := self.env.GetManagers().Enrollment.Create(enrollment, ctx); err != nil { + return errors.Wrap(err, "could not create enrollment for re-enrolling edge router") + } else { + log.WithField("enrollmentId", enrollment.Id).Infof("edge router re-enrollment entity created") } + router.Fingerprint = nil + router.CertPem = nil + router.IsVerified = false + if err := self.Update(router, true, fields.UpdatedFieldsMap{ db.FieldRouterFingerprint: struct{}{}, persistence.FieldEdgeRouterCertPEM: struct{}{}, persistence.FieldEdgeRouterIsVerified: struct{}{}, - }); err != nil { + }, ctx); err != nil { log.WithError(err).Error("unable to patch re-enrolling edge router") return errors.Wrap(err, "unable to patch re-enrolling edge router") } @@ -348,7 +344,7 @@ type ExtendedCerts struct { RawServerCert []byte } -func (self *EdgeRouterManager) ExtendEnrollment(router *EdgeRouter, clientCsrPem []byte, serverCertCsrPem []byte) (*ExtendedCerts, error) { +func (self *EdgeRouterManager) ExtendEnrollment(router *EdgeRouter, clientCsrPem []byte, serverCertCsrPem []byte, ctx *change.Context) (*ExtendedCerts, error) { enrollmentModule := self.env.GetEnrollRegistry().GetByMethod("erott").(*EnrollModuleEr) clientCertRaw, err := enrollmentModule.ProcessClientCsrPem(clientCsrPem, router.Id) @@ -381,7 +377,7 @@ func (self *EdgeRouterManager) ExtendEnrollment(router *EdgeRouter, clientCsrPem err = self.Update(router, true, &fields.UpdatedFieldsMap{ persistence.FieldEdgeRouterCertPEM: struct{}{}, db.FieldRouterFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return nil, err @@ -393,7 +389,7 @@ func (self *EdgeRouterManager) ExtendEnrollment(router *EdgeRouter, clientCsrPem }, nil } -func (self *EdgeRouterManager) ExtendEnrollmentWithVerify(router *EdgeRouter, clientCsrPem []byte, serverCertCsrPem []byte) (*ExtendedCerts, error) { +func (self *EdgeRouterManager) ExtendEnrollmentWithVerify(router *EdgeRouter, clientCsrPem []byte, serverCertCsrPem []byte, ctx *change.Context) (*ExtendedCerts, error) { enrollmentModule := self.env.GetEnrollRegistry().GetByMethod("erott").(*EnrollModuleEr) clientCertRaw, err := enrollmentModule.ProcessClientCsrPem(clientCsrPem, router.Id) @@ -426,7 +422,7 @@ func (self *EdgeRouterManager) ExtendEnrollmentWithVerify(router *EdgeRouter, cl err = self.Update(router, true, &fields.UpdatedFieldsMap{ persistence.FieldEdgeRouterUnverifiedCertPEM: struct{}{}, persistence.FieldEdgeRouterUnverifiedFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return nil, err @@ -442,7 +438,7 @@ func (self *EdgeRouterManager) ReadOneByUnverifiedFingerprint(fingerprint string return self.ReadOneByQuery(fmt.Sprintf(`%s = "%v"`, persistence.FieldEdgeRouterUnverifiedFingerprint, fingerprint)) } -func (self *EdgeRouterManager) ExtendEnrollmentVerify(router *EdgeRouter) error { +func (self *EdgeRouterManager) ExtendEnrollmentVerify(router *EdgeRouter, ctx *change.Context) error { if router.UnverifiedFingerprint != nil && router.UnverifiedCertPem != nil { router.Fingerprint = router.UnverifiedFingerprint router.CertPem = router.UnverifiedCertPem @@ -455,7 +451,7 @@ func (self *EdgeRouterManager) ExtendEnrollmentVerify(router *EdgeRouter) error persistence.FieldCaCertPem: struct{}{}, persistence.FieldEdgeRouterUnverifiedCertPEM: struct{}{}, persistence.FieldEdgeRouterUnverifiedFingerprint: struct{}{}, - }) + }, ctx) } return errors.New("no outstanding verification necessary") @@ -558,10 +554,11 @@ type CreateEdgeRouterCmd struct { manager *EdgeRouterManager edgeRouter *EdgeRouter enrollment *Enrollment + ctx *change.Context } -func (self *CreateEdgeRouterCmd) Apply() error { - return self.manager.ApplyCreate(self) +func (self *CreateEdgeRouterCmd) Apply(ctx boltz.MutateContext) error { + return self.manager.ApplyCreate(self, ctx) } func (self *CreateEdgeRouterCmd) Encode() ([]byte, error) { @@ -578,6 +575,7 @@ func (self *CreateEdgeRouterCmd) Encode() ([]byte, error) { cmd := &edge_cmd_pb.CreateEdgeRouterCmd{ EdgeRouter: edgeRouterMsg, Enrollment: enrollment, + Ctx: ContextToProtobuf(self.ctx), } return cmd_pb.EncodeProtobuf(cmd) @@ -597,6 +595,11 @@ func (self *CreateEdgeRouterCmd) Decode(env Env, msg *edge_cmd_pb.CreateEdgeRout self.edgeRouter = edgeRouter self.enrollment = enrollment + self.ctx = ProtobufToContext(msg.Ctx) return nil } + +func (self *CreateEdgeRouterCmd) GetChangeContext() *change.Context { + return self.ctx +} diff --git a/controller/model/edge_router_manager_test.go b/controller/model/edge_router_manager_test.go index 4d569bb89..c0fe326d8 100644 --- a/controller/model/edge_router_manager_test.go +++ b/controller/model/edge_router_manager_test.go @@ -2,6 +2,7 @@ package model import ( "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "go.etcd.io/bbolt" "testing" ) @@ -20,7 +21,7 @@ func (ctx *TestContext) testGetEdgeRoutersForServiceAndIdentity(*testing.T) { identity := ctx.requireNewIdentity(false) service := ctx.requireNewService() service.RoleAttributes = []string{eid.New()} - ctx.NoError(ctx.managers.EdgeService.Update(service, nil)) + ctx.NoError(ctx.managers.EdgeService.Update(service, nil, change.New().SetSource("test"))) ctx.requireNewEdgeRouterPolicy(ss("#all"), ss("#all")) @@ -37,7 +38,7 @@ func (ctx *TestContext) testGetEdgeRoutersForServiceAndIdentity(*testing.T) { ctx.False(ctx.managers.EdgeRouter.IsSharedEdgeRouterPresent(identity.Id, service.Id)) serp.EdgeRouterRoles = []string{"@" + edgeRouter.Id} - ctx.NoError(ctx.managers.ServiceEdgeRouterPolicy.Update(serp, nil)) + ctx.NoError(ctx.managers.ServiceEdgeRouterPolicy.Update(serp, nil, change.New().SetSource("test"))) // should be accessible if we limit to our specific router ctx.True(ctx.isEdgeRouterAccessible(edgeRouter.Id, identity.Id, service.Id)) diff --git a/controller/model/edge_router_model.go b/controller/model/edge_router_model.go index be3c34aa3..ef31c18a8 100644 --- a/controller/model/edge_router_model.go +++ b/controller/model/edge_router_model.go @@ -17,14 +17,11 @@ package model import ( - "github.com/openziti/foundation/v2/versions" - "reflect" - "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/db" "github.com/openziti/fabric/controller/models" + "github.com/openziti/foundation/v2/versions" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" ) @@ -46,7 +43,11 @@ type EdgeRouter struct { Disabled bool } -func (entity *EdgeRouter) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (self *EdgeRouter) GetName() string { + return self.Name +} + +func (entity *EdgeRouter) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.EdgeRouter, error) { boltEntity := &persistence.EdgeRouter{ Router: db.Router{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), @@ -64,7 +65,7 @@ func (entity *EdgeRouter) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz return boltEntity, nil } -func (entity *EdgeRouter) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *EdgeRouter) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.EdgeRouter, error) { return &persistence.EdgeRouter{ Router: db.Router{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), @@ -84,12 +85,7 @@ func (entity *EdgeRouter) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz. }, nil } -func (entity *EdgeRouter) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltEdgeRouter, ok := boltEntity.(*persistence.EdgeRouter) - if !ok { - return errors.Errorf("unexpected type %v when filling model edge router", reflect.TypeOf(boltEntity)) - } - +func (entity *EdgeRouter) fillFrom(_ Env, _ *bbolt.Tx, boltEdgeRouter *persistence.EdgeRouter) error { entity.FillCommon(boltEdgeRouter) entity.Name = boltEdgeRouter.Name entity.RoleAttributes = boltEdgeRouter.RoleAttributes diff --git a/controller/model/edge_router_policy_manager.go b/controller/model/edge_router_policy_manager.go index c69a11bc3..f8e3ad095 100644 --- a/controller/model/edge_router_policy_manager.go +++ b/controller/model/edge_router_policy_manager.go @@ -17,18 +17,20 @@ package model import ( + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" - "go.etcd.io/bbolt" + "github.com/openziti/storage/boltz" "google.golang.org/protobuf/proto" ) func NewEdgeRouterPolicyManager(env Env) *EdgeRouterPolicyManager { manager := &EdgeRouterPolicyManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().EdgeRouterPolicy), + baseEntityManager: newBaseEntityManager[*EdgeRouterPolicy, *persistence.EdgeRouterPolicy](env, env.GetStores().EdgeRouterPolicy), } manager.impl = manager @@ -38,44 +40,28 @@ func NewEdgeRouterPolicyManager(env Env) *EdgeRouterPolicyManager { } type EdgeRouterPolicyManager struct { - baseEntityManager + baseEntityManager[*EdgeRouterPolicy, *persistence.EdgeRouterPolicy] } -func (self *EdgeRouterPolicyManager) newModelEntity() edgeEntity { +func (self *EdgeRouterPolicyManager) newModelEntity() *EdgeRouterPolicy { return &EdgeRouterPolicy{} } -func (self *EdgeRouterPolicyManager) Create(entity *EdgeRouterPolicy) error { - return network.DispatchCreate[*EdgeRouterPolicy](self, entity) +func (self *EdgeRouterPolicyManager) Create(entity *EdgeRouterPolicy, ctx *change.Context) error { + return network.DispatchCreate[*EdgeRouterPolicy](self, entity, ctx) } -func (self *EdgeRouterPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*EdgeRouterPolicy]) error { - _, err := self.createEntity(cmd.Entity) +func (self *EdgeRouterPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*EdgeRouterPolicy], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *EdgeRouterPolicyManager) Update(entity *EdgeRouterPolicy, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*EdgeRouterPolicy](self, entity, checker) +func (self *EdgeRouterPolicyManager) Update(entity *EdgeRouterPolicy, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*EdgeRouterPolicy](self, entity, checker, ctx) } -func (self *EdgeRouterPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*EdgeRouterPolicy]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) -} - -func (self *EdgeRouterPolicyManager) Read(id string) (*EdgeRouterPolicy, error) { - modelEntity := &EdgeRouterPolicy{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - -func (self *EdgeRouterPolicyManager) readInTx(tx *bbolt.Tx, id string) (*EdgeRouterPolicy, error) { - modelEntity := &EdgeRouterPolicy{} - if err := self.readEntityInTx(tx, id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil +func (self *EdgeRouterPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*EdgeRouterPolicy], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *EdgeRouterPolicyManager) Marshall(entity *EdgeRouterPolicy) ([]byte, error) { diff --git a/controller/model/edge_router_policy_model.go b/controller/model/edge_router_policy_model.go index 806950e9e..b88e3f5ce 100644 --- a/controller/model/edge_router_policy_model.go +++ b/controller/model/edge_router_policy_model.go @@ -20,9 +20,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type EdgeRouterPolicy struct { @@ -33,7 +31,7 @@ type EdgeRouterPolicy struct { EdgeRouterRoles []string } -func (entity *EdgeRouterPolicy) toBoltEntity() (boltz.Entity, error) { +func (entity *EdgeRouterPolicy) toBoltEntity() (*persistence.EdgeRouterPolicy, error) { return &persistence.EdgeRouterPolicy{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Name: entity.Name, @@ -43,19 +41,15 @@ func (entity *EdgeRouterPolicy) toBoltEntity() (boltz.Entity, error) { }, nil } -func (entity *EdgeRouterPolicy) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *EdgeRouterPolicy) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.EdgeRouterPolicy, error) { return entity.toBoltEntity() } -func (entity *EdgeRouterPolicy) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *EdgeRouterPolicy) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.EdgeRouterPolicy, error) { return entity.toBoltEntity() } -func (entity *EdgeRouterPolicy) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltEdgeRouterPolicy, ok := boltEntity.(*persistence.EdgeRouterPolicy) - if !ok { - return errors.Errorf("unexpected type %v when filling model edge router policy", reflect.TypeOf(boltEntity)) - } +func (entity *EdgeRouterPolicy) fillFrom(_ Env, _ *bbolt.Tx, boltEdgeRouterPolicy *persistence.EdgeRouterPolicy) error { entity.FillCommon(boltEdgeRouterPolicy) entity.Name = boltEdgeRouterPolicy.Name entity.Semantic = boltEdgeRouterPolicy.Semantic diff --git a/controller/model/edge_service_manager.go b/controller/model/edge_service_manager.go index 858d0b115..de3bedf14 100644 --- a/controller/model/edge_service_manager.go +++ b/controller/model/edge_service_manager.go @@ -20,6 +20,7 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/db" "github.com/openziti/fabric/controller/fields" @@ -33,9 +34,11 @@ import ( func NewEdgeServiceManager(env Env) *EdgeServiceManager { manager := &EdgeServiceManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().EdgeService), + baseEntityManager: newBaseEntityManager[*Service, *persistence.EdgeService](env, env.GetStores().EdgeService), + detailLister: &ServiceDetailLister{}, } manager.impl = manager + manager.detailLister.manager = manager network.RegisterManagerDecoder[*Service](env.GetHostController().GetNetwork().Managers, manager) @@ -43,43 +46,40 @@ func NewEdgeServiceManager(env Env) *EdgeServiceManager { } type EdgeServiceManager struct { - baseEntityManager + baseEntityManager[*Service, *persistence.EdgeService] + detailLister *ServiceDetailLister +} + +func (self *EdgeServiceManager) GetDetailLister() *ServiceDetailLister { + return self.detailLister } func (self *EdgeServiceManager) GetEntityTypeId() string { return "edgeServices" } -func (self *EdgeServiceManager) newModelEntity() edgeEntity { - return &ServiceDetail{} +func (self *EdgeServiceManager) newModelEntity() *Service { + return &Service{} } -func (self *EdgeServiceManager) Create(entity *Service) error { - return network.DispatchCreate[*Service](self, entity) +func (self *EdgeServiceManager) Create(entity *Service, ctx *change.Context) error { + return network.DispatchCreate[*Service](self, entity, ctx) } -func (self *EdgeServiceManager) ApplyCreate(cmd *command.CreateEntityCommand[*Service]) error { - _, err := self.createEntity(cmd.Entity) +func (self *EdgeServiceManager) ApplyCreate(cmd *command.CreateEntityCommand[*Service], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *EdgeServiceManager) Update(entity *Service, checker fields.UpdatedFields) error { +func (self *EdgeServiceManager) Update(entity *Service, checker fields.UpdatedFields, ctx *change.Context) error { if checker != nil { checker = checker.RemoveFields("encryptionRequired") } - return network.DispatchUpdate[*Service](self, entity, checker) + return network.DispatchUpdate[*Service](self, entity, checker, ctx) } -func (self *EdgeServiceManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Service]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) -} - -func (self *EdgeServiceManager) Read(id string) (*Service, error) { - entity := &Service{} - if err := self.readEntity(id, entity); err != nil { - return nil, err - } - return entity, nil +func (self *EdgeServiceManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Service], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *EdgeServiceManager) ReadByName(name string) (*Service, error) { @@ -93,7 +93,16 @@ func (self *EdgeServiceManager) ReadByName(name string) (*Service, error) { func (self *EdgeServiceManager) readInTx(tx *bbolt.Tx, id string) (*ServiceDetail, error) { entity := &ServiceDetail{} - if err := self.readEntityInTx(tx, id, entity); err != nil { + boltEntity := self.GetStore().GetEntityStrategy().NewEntity() + found, err := self.GetStore().LoadEntity(tx, id, boltEntity) + if err != nil { + return nil, err + } + if !found { + return nil, boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), "id", id) + } + + if err = entity.fillFrom(self.env, tx, boltEntity); err != nil { return nil, err } return entity, nil @@ -369,3 +378,39 @@ func (self *EdgeServiceManager) GetPolicyPostureChecks(identityId, serviceId str return policyIdToChecks } + +type ServiceDetailLister struct { + manager *EdgeServiceManager +} + +func (self *ServiceDetailLister) GetListStore() boltz.Store { + return self.manager.GetListStore() +} + +func (self *ServiceDetailLister) BaseLoadInTx(tx *bbolt.Tx, id string) (*ServiceDetail, error) { + return self.manager.readInTx(tx, id) +} + +func (self *ServiceDetailLister) BasePreparedList(query ast.Query) (*models.EntityListResult[*ServiceDetail], error) { + result := &models.EntityListResult[*ServiceDetail]{ + Loader: self, + } + + if err := self.manager.PreparedListWithHandler(query, result.Collect); err != nil { + return nil, err + } + + return result, nil +} + +func (self *ServiceDetailLister) BasePreparedListIndexed(cursorProvider ast.SetCursorProvider, query ast.Query) (*models.EntityListResult[*ServiceDetail], error) { + result := &models.EntityListResult[*ServiceDetail]{ + Loader: self, + } + + if err := self.manager.PreparedListIndexed(cursorProvider, query, result.Collect); err != nil { + return nil, err + } + + return result, nil +} diff --git a/controller/model/edge_service_model.go b/controller/model/edge_service_model.go index 2b824e05c..69fc44158 100644 --- a/controller/model/edge_service_model.go +++ b/controller/model/edge_service_model.go @@ -23,9 +23,7 @@ import ( "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type Service struct { @@ -37,8 +35,8 @@ type Service struct { EncryptionRequired bool `json:"encryptionRequired"` } -func (entity *Service) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - if err := entity.validateConfigs(tx, manager); err != nil { +func (entity *Service) toBoltEntity(tx *bbolt.Tx, env Env) (*persistence.EdgeService, error) { + if err := entity.validateConfigs(tx, env); err != nil { return nil, err } @@ -55,13 +53,13 @@ func (entity *Service) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz. return edgeService, nil } -func (entity *Service) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *Service) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.EdgeService, error) { + return entity.toBoltEntity(tx, env) } -func (entity *Service) validateConfigs(tx *bbolt.Tx, manager EntityManager) error { +func (entity *Service) validateConfigs(tx *bbolt.Tx, env Env) error { typeMap := map[string]*persistence.Config{} - configStore := manager.GetEnv().GetStores().Config + configStore := env.GetStores().Config for _, id := range entity.Configs { config, _ := configStore.LoadOneById(tx, id) if config == nil { @@ -70,7 +68,7 @@ func (entity *Service) validateConfigs(tx *bbolt.Tx, manager EntityManager) erro conflictConfig, found := typeMap[config.Type] if found { configTypeName := "" - if configType, _ := manager.GetEnv().GetStores().ConfigType.LoadOneById(tx, config.Type); configType != nil { + if configType, _ := env.GetStores().ConfigType.LoadOneById(tx, config.Type); configType != nil { configTypeName = configType.Name } msg := fmt.Sprintf("duplicate configs named %v and %v found for config type %v. Only one config of a given typed is allowed per service ", @@ -82,15 +80,11 @@ func (entity *Service) validateConfigs(tx *bbolt.Tx, manager EntityManager) erro return nil } -func (entity *Service) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *Service) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.EdgeService, error) { + return entity.toBoltEntity(tx, env) } -func (entity *Service) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltService, ok := boltEntity.(*persistence.EdgeService) - if !ok { - return errors.Errorf("unexpected type %v when filling model service", reflect.TypeOf(boltEntity)) - } +func (entity *Service) fillFrom(_ Env, _ *bbolt.Tx, boltService *persistence.EdgeService) error { entity.FillCommon(boltService) entity.Name = boltService.Name entity.TerminatorStrategy = boltService.TerminatorStrategy @@ -111,19 +105,15 @@ type ServiceDetail struct { EncryptionRequired bool `json:"encryptionRequired"` } -func (entity *ServiceDetail) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *ServiceDetail) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.EdgeService, error) { panic("should never be called") } -func (entity *ServiceDetail) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ServiceDetail) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.EdgeService, error) { panic("should never be called") } -func (entity *ServiceDetail) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltService, ok := boltEntity.(*persistence.EdgeService) - if !ok { - return errors.Errorf("unexpected type %v when filling model service", reflect.TypeOf(boltEntity)) - } +func (entity *ServiceDetail) fillFrom(_ Env, _ *bbolt.Tx, boltService *persistence.EdgeService) error { entity.FillCommon(boltService) entity.Name = boltService.Name entity.TerminatorStrategy = boltService.TerminatorStrategy diff --git a/controller/model/enrollment.go b/controller/model/enrollment.go index 1b8084f4b..2c5a4b122 100644 --- a/controller/model/enrollment.go +++ b/controller/model/enrollment.go @@ -22,6 +22,7 @@ import ( "github.com/go-openapi/runtime" "github.com/openziti/edge/controller/apierror" fabricApiError "github.com/openziti/fabric/controller/apierror" + "github.com/openziti/fabric/controller/change" "io" "net/http" "strings" @@ -72,15 +73,17 @@ type EnrollmentContext interface { GetCerts() []*x509.Certificate GetHeaders() map[string]interface{} GetMethod() string + GetChangeContext() *change.Context } type EnrollmentContextHttp struct { - Headers map[string]interface{} - Parameters map[string]interface{} - Data interface{} - Certs []*x509.Certificate - Token string - Method string + Headers map[string]interface{} + Parameters map[string]interface{} + Data interface{} + Certs []*x509.Certificate + Token string + Method string + ChangeContext *change.Context } func (context *EnrollmentContextHttp) GetToken() string { @@ -127,7 +130,11 @@ func (context *EnrollmentContextHttp) GetHeaders() map[string]interface{} { return context.Headers } -func (context *EnrollmentContextHttp) FillFromHttpRequest(request *http.Request) error { +func (context *EnrollmentContextHttp) GetChangeContext() *change.Context { + return context.ChangeContext +} + +func (context *EnrollmentContextHttp) FillFromHttpRequest(request *http.Request, changeCtx *change.Context) error { queryValues := request.URL.Query() parameters := map[string]interface{}{} @@ -179,6 +186,7 @@ func (context *EnrollmentContextHttp) FillFromHttpRequest(request *http.Request) context.Data = enrollData context.Certs = request.TLS.PeerCertificates context.Headers = headers + context.ChangeContext = changeCtx return nil } diff --git a/controller/model/enrollment_manager.go b/controller/model/enrollment_manager.go index 726d8f672..ec5af2a32 100644 --- a/controller/model/enrollment_manager.go +++ b/controller/model/enrollment_manager.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/internal/cert" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -37,13 +38,13 @@ import ( ) type EnrollmentManager struct { - baseEntityManager + baseEntityManager[*Enrollment, *persistence.Enrollment] enrollmentStore persistence.EnrollmentStore } func NewEnrollmentManager(env Env) *EnrollmentManager { manager := &EnrollmentManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Enrollment), + baseEntityManager: newBaseEntityManager[*Enrollment, *persistence.Enrollment](env, env.GetStores().Enrollment), enrollmentStore: env.GetStores().Enrollment, } @@ -55,13 +56,18 @@ func NewEnrollmentManager(env Env) *EnrollmentManager { return manager } -func (self *EnrollmentManager) Create(entity *Enrollment) error { - return network.DispatchCreate[*Enrollment](self, entity) +func (self *EnrollmentManager) Create(entity *Enrollment, ctx *change.Context) error { + return network.DispatchCreate[*Enrollment](self, entity, ctx) } -func (self *EnrollmentManager) ApplyCreate(cmd *command.CreateEntityCommand[*Enrollment]) error { +func (self *EnrollmentManager) ApplyCreate(cmd *command.CreateEntityCommand[*Enrollment], ctx boltz.MutateContext) error { model := cmd.Entity + if model.EdgeRouterId != nil || model.TransitRouterId != nil { + _, err := self.createEntity(model, ctx) + return err + } + if model.IdentityId == nil { return apierror.NewBadRequestFieldError(*errorz.NewFieldError("identity not found", "identityId", model.IdentityId)) } @@ -115,19 +121,19 @@ func (self *EnrollmentManager) ApplyCreate(cmd *command.CreateEntityCommand[*Enr return err } - _, err = self.createEntity(model) + _, err = self.createEntity(model, ctx) return err } -func (self *EnrollmentManager) Update(entity *Enrollment, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*Enrollment](self, entity, checker) +func (self *EnrollmentManager) Update(entity *Enrollment, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*Enrollment](self, entity, checker, ctx) } -func (self *EnrollmentManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Enrollment]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) +func (self *EnrollmentManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Enrollment], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } -func (self *EnrollmentManager) newModelEntity() edgeEntity { +func (self *EnrollmentManager) newModelEntity() *Enrollment { return &Enrollment{} } @@ -187,7 +193,7 @@ func (self *EnrollmentManager) ReadByToken(token string) (*Enrollment, error) { return nil } - return enrollment.fillFrom(self, tx, boltEntity) + return enrollment.fillFrom(self.env, tx, boltEntity) }) if err != nil { @@ -197,11 +203,12 @@ func (self *EnrollmentManager) ReadByToken(token string) (*Enrollment, error) { return enrollment, nil } -func (self *EnrollmentManager) ReplaceWithAuthenticator(enrollmentId string, authenticator *Authenticator) error { +func (self *EnrollmentManager) ReplaceWithAuthenticator(enrollmentId string, authenticator *Authenticator, ctx *change.Context) error { return self.Dispatch(&ReplaceEnrollmentWithAuthenticatorCmd{ manager: self, enrollmentId: enrollmentId, authenticator: authenticator, + ctx: ctx, }) } @@ -225,10 +232,8 @@ func (self *EnrollmentManager) GetClientCertChain(certRaw []byte) (string, error return string(clientChainPem), nil } -func (self *EnrollmentManager) ApplyReplaceEncoderWithAuthenticatorCommand(cmd *ReplaceEnrollmentWithAuthenticatorCmd) error { - return self.env.GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - +func (self *EnrollmentManager) ApplyReplaceEncoderWithAuthenticatorCommand(cmd *ReplaceEnrollmentWithAuthenticatorCmd, ctx boltz.MutateContext) error { + return self.env.GetDbProvider().GetDb().Update(ctx, func(ctx boltz.MutateContext) error { err := self.env.GetStores().Enrollment.DeleteById(ctx, cmd.enrollmentId) if err != nil { return err @@ -255,7 +260,7 @@ func (self *EnrollmentManager) Read(id string) (*Enrollment, error) { return entity, nil } -func (self *EnrollmentManager) RefreshJwt(id string, expiresAt time.Time) error { +func (self *EnrollmentManager) RefreshJwt(id string, expiresAt time.Time, ctx *change.Context) error { enrollment, err := self.Read(id) if err != nil { @@ -274,17 +279,15 @@ func (self *EnrollmentManager) RefreshJwt(id string, expiresAt time.Time) error return errorz.NewFieldError("must be after the current date and time", "expiresAt", expiresAt) } - if err := enrollment.FillJwtInfoWithExpiresAt(self.env, *enrollment.IdentityId, expiresAt); err != nil { + if err = enrollment.FillJwtInfoWithExpiresAt(self.env, *enrollment.IdentityId, expiresAt); err != nil { return err } - err = self.Update(enrollment, fields.UpdatedFieldsMap{ + return self.Update(enrollment, fields.UpdatedFieldsMap{ persistence.FieldEnrollmentJwt: struct{}{}, persistence.FieldEnrollmentExpiresAt: struct{}{}, persistence.FieldEnrollmentIssuedAt: struct{}{}, - }) - - return err + }, ctx) } func (self *EnrollmentManager) Query(query string) ([]*Enrollment, error) { @@ -366,13 +369,14 @@ func (self *EnrollmentManager) Unmarshall(bytes []byte) (*Enrollment, error) { } type ReplaceEnrollmentWithAuthenticatorCmd struct { + ctx *change.Context manager *EnrollmentManager enrollmentId string authenticator *Authenticator } -func (self *ReplaceEnrollmentWithAuthenticatorCmd) Apply() error { - return self.manager.ApplyReplaceEncoderWithAuthenticatorCommand(self) +func (self *ReplaceEnrollmentWithAuthenticatorCmd) Apply(ctx boltz.MutateContext) error { + return self.manager.ApplyReplaceEncoderWithAuthenticatorCommand(self, ctx) } func (self *ReplaceEnrollmentWithAuthenticatorCmd) Encode() ([]byte, error) { @@ -382,6 +386,7 @@ func (self *ReplaceEnrollmentWithAuthenticatorCmd) Encode() ([]byte, error) { } cmd := &edge_cmd_pb.ReplaceEnrollmentWithAuthenticatorCmd{ + Ctx: ContextToProtobuf(self.ctx), EnrollmentId: self.enrollmentId, Authenticator: authMsg, } @@ -389,6 +394,7 @@ func (self *ReplaceEnrollmentWithAuthenticatorCmd) Encode() ([]byte, error) { } func (self *ReplaceEnrollmentWithAuthenticatorCmd) Decode(env Env, msg *edge_cmd_pb.ReplaceEnrollmentWithAuthenticatorCmd) error { + self.ctx = ProtobufToContext(msg.Ctx) self.manager = env.GetManagers().Enrollment self.enrollmentId = msg.EnrollmentId authenticator, err := env.GetManagers().Authenticator.ProtobufToAuthenticator(msg.Authenticator) @@ -398,3 +404,7 @@ func (self *ReplaceEnrollmentWithAuthenticatorCmd) Decode(env Env, msg *edge_cmd self.authenticator = authenticator return nil } + +func (self *ReplaceEnrollmentWithAuthenticatorCmd) GetChangeContext() *change.Context { + return self.ctx +} diff --git a/controller/model/enrollment_mod_ca.go b/controller/model/enrollment_mod_ca.go index 6ab0e203c..45f588ea4 100644 --- a/controller/model/enrollment_mod_ca.go +++ b/controller/model/enrollment_mod_ca.go @@ -201,7 +201,7 @@ func (module *EnrollModuleCa) completeCertAuthenticatorEnrollment(log *logrus.En }, } - _, authenticatorId, err := module.env.GetManagers().Identity.CreateWithAuthenticator(identity, newAuthenticator) + _, authenticatorId, err := module.env.GetManagers().Identity.CreateWithAuthenticator(identity, newAuthenticator, context.GetChangeContext()) if err != nil { log.WithError(err).Error("failed to create identity with authenticator") @@ -264,7 +264,7 @@ func (module *EnrollModuleCa) completeExternalIdEnrollment(log *logrus.Entry, co identity.ExternalId = &externalId - if err = module.env.GetManagers().Identity.Create(identity); 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 } @@ -281,13 +281,16 @@ func (module *EnrollModuleCa) completeExternalIdEnrollment(log *logrus.Entry, co } // getIdentityName returns a unique identity name based taking into account: -// 1) the requested name from the enrolling identity -// 2) the name formatting requirements determined by the enrolling CA -// 3) the uniqueness of the name that is a result of 1 and 2 // -// The requested name is only used if the CA's name format allows it to be used. +// 1. the requested name from the enrolling identity // -// If the resulting name is not unique a six digit zero-padded numerical suffix is appended (i.e. 000001). +// 2. the name formatting requirements determined by the enrolling CA +// +// 3. the uniqueness of the name that is a result of 1 and 2 +// +// The requested name is only used if the CA's name format allows it to be used. +// +// If the resulting name is not unique a six digit zero-padded numerical suffix is appended (i.e. 000001). func (module *EnrollModuleCa) getIdentityName(ca *Ca, enrollmentCert *x509.Certificate, requestedName string, identityId string) string { formatter := NewIdentityNameFormatter(ca, enrollmentCert, requestedName, identityId) nameFormat := ca.IdentityNameFormat diff --git a/controller/model/enrollment_mod_erott.go b/controller/model/enrollment_mod_erott.go index 57e2571d3..5f1bf2a08 100644 --- a/controller/model/enrollment_mod_erott.go +++ b/controller/model/enrollment_mod_erott.go @@ -127,11 +127,11 @@ func (module *EnrollModuleEr) Process(context EnrollmentContext) (*EnrollmentRes edgeRouter.CertPem = &clientCertPemStr edgeRouter.IsVerified = true edgeRouter.Fingerprint = &clientCertFingerprint - if err := module.env.GetManagers().EdgeRouter.Update(edgeRouter, true, nil); err != nil { + if err := module.env.GetManagers().EdgeRouter.Update(edgeRouter, true, nil, context.GetChangeContext()); err != nil { return nil, fmt.Errorf("could not update edge router: %s", err) } - if err := module.env.GetManagers().Enrollment.Delete(enrollment.Id); err != nil { + if err := module.env.GetManagers().Enrollment.Delete(enrollment.Id, context.GetChangeContext()); err != nil { return nil, fmt.Errorf("could not delete enrollment: %s", err) } diff --git a/controller/model/enrollment_mod_ott.go b/controller/model/enrollment_mod_ott.go index 839c99c66..8c019b468 100644 --- a/controller/model/enrollment_mod_ott.go +++ b/controller/model/enrollment_mod_ott.go @@ -108,7 +108,7 @@ func (module *EnrollModuleOtt) Process(ctx EnrollmentContext) (*EnrollmentResult }, } - err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator) + err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator, ctx.GetChangeContext()) if err != nil { return nil, err diff --git a/controller/model/enrollment_mod_ottca.go b/controller/model/enrollment_mod_ottca.go index 347fe1085..130fdd9a2 100644 --- a/controller/model/enrollment_mod_ottca.go +++ b/controller/model/enrollment_mod_ottca.go @@ -134,7 +134,7 @@ func (module *EnrollModuleOttCa) Process(ctx EnrollmentContext) (*EnrollmentResu }, } - err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator) + err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator, ctx.GetChangeContext()) if err != nil { return nil, err diff --git a/controller/model/enrollment_mod_trott.go b/controller/model/enrollment_mod_trott.go index 51ed951fa..745995af8 100644 --- a/controller/model/enrollment_mod_trott.go +++ b/controller/model/enrollment_mod_trott.go @@ -133,11 +133,11 @@ func (module *EnrollModuleRouterOtt) Process(context EnrollmentContext) (*Enroll txRouter.IsVerified = true txRouter.Fingerprint = &cltFp - if err := module.env.GetManagers().TransitRouter.Update(txRouter, true, nil); err != nil { + if err := module.env.GetManagers().TransitRouter.Update(txRouter, true, nil, context.GetChangeContext()); err != nil { return nil, fmt.Errorf("could not update edge router: %s", err) } - if err := module.env.GetManagers().Enrollment.Delete(enrollment.Id); err != nil { + if err := module.env.GetManagers().Enrollment.Delete(enrollment.Id, context.GetChangeContext()); err != nil { return nil, fmt.Errorf("could not delete enrollment: %s", err) } diff --git a/controller/model/enrollment_mod_updb.go b/controller/model/enrollment_mod_updb.go index d01710d51..794ec4eb9 100644 --- a/controller/model/enrollment_mod_updb.go +++ b/controller/model/enrollment_mod_updb.go @@ -94,7 +94,7 @@ func (module *EnrollModuleUpdb) Process(ctx EnrollmentContext) (*EnrollmentResul }, } - err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator) + err = module.env.GetManagers().Enrollment.ReplaceWithAuthenticator(enrollment.Id, newAuthenticator, ctx.GetChangeContext()) if err != nil { return nil, err diff --git a/controller/model/enrollment_model.go b/controller/model/enrollment_model.go index 9589823a5..3f15c3552 100644 --- a/controller/model/enrollment_model.go +++ b/controller/model/enrollment_model.go @@ -25,9 +25,7 @@ import ( "github.com/openziti/foundation/v2/errorz" "github.com/openziti/sdk-golang/ziti/config" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -90,11 +88,7 @@ func (entity *Enrollment) FillJwtInfoWithExpiresAt(env Env, subject string, expi return nil } -func (entity *Enrollment) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltEnrollment, ok := boltEntity.(*persistence.Enrollment) - if !ok { - return errors.Errorf("unexpected type %v when filling model authenticator", reflect.TypeOf(boltEntity)) - } +func (entity *Enrollment) fillFrom(_ Env, _ *bbolt.Tx, boltEnrollment *persistence.Enrollment) error { entity.FillCommon(boltEnrollment) entity.Method = boltEnrollment.Method entity.IdentityId = boltEnrollment.IdentityId @@ -110,7 +104,7 @@ func (entity *Enrollment) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity bolt return nil } -func (entity *Enrollment) toBoltEntity(manager EntityManager) (boltz.Entity, error) { +func (entity *Enrollment) toBoltEntity(env Env) (*persistence.Enrollment, error) { if entity.Method == persistence.MethodEnrollOttCa { if entity.CaId == nil || *entity.CaId == "" { apiErr := errorz.NewNotFound() @@ -119,7 +113,7 @@ func (entity *Enrollment) toBoltEntity(manager EntityManager) (boltz.Entity, err return nil, apiErr } - ca, _ := manager.GetEnv().GetManagers().Ca.Read(*entity.CaId) + ca, _ := env.GetManagers().Ca.Read(*entity.CaId) if ca == nil { apiErr := errorz.NewNotFound() @@ -146,10 +140,10 @@ func (entity *Enrollment) toBoltEntity(manager EntityManager) (boltz.Entity, err return boltEntity, nil } -func (entity *Enrollment) toBoltEntityForCreate(_ *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - return entity.toBoltEntity(manager) +func (entity *Enrollment) toBoltEntityForCreate(_ *bbolt.Tx, env Env) (*persistence.Enrollment, error) { + return entity.toBoltEntity(env) } -func (entity *Enrollment) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(manager) +func (entity *Enrollment) toBoltEntityForUpdate(_ *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.Enrollment, error) { + return entity.toBoltEntity(env) } diff --git a/controller/model/external_jwt_signer_manager.go b/controller/model/external_jwt_signer_manager.go index 9399b8d9b..024d103f4 100644 --- a/controller/model/external_jwt_signer_manager.go +++ b/controller/model/external_jwt_signer_manager.go @@ -17,12 +17,15 @@ package model import ( + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" "github.com/openziti/storage/ast" + "github.com/openziti/storage/boltz" "github.com/pkg/errors" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" @@ -30,7 +33,7 @@ import ( func NewExternalJwtSignerManager(env Env) *ExternalJwtSignerManager { manager := &ExternalJwtSignerManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ExternalJwtSigner), + baseEntityManager: newBaseEntityManager[*ExternalJwtSigner, *persistence.ExternalJwtSigner](env, env.GetStores().ExternalJwtSigner), } manager.impl = manager @@ -40,36 +43,28 @@ func NewExternalJwtSignerManager(env Env) *ExternalJwtSignerManager { } type ExternalJwtSignerManager struct { - baseEntityManager + baseEntityManager[*ExternalJwtSigner, *persistence.ExternalJwtSigner] } -func (self *ExternalJwtSignerManager) newModelEntity() edgeEntity { +func (self *ExternalJwtSignerManager) newModelEntity() *ExternalJwtSigner { return &ExternalJwtSigner{} } -func (self *ExternalJwtSignerManager) Create(entity *ExternalJwtSigner) error { - return network.DispatchCreate[*ExternalJwtSigner](self, entity) +func (self *ExternalJwtSignerManager) Create(entity *ExternalJwtSigner, ctx *change.Context) error { + return network.DispatchCreate[*ExternalJwtSigner](self, entity, ctx) } -func (self *ExternalJwtSignerManager) ApplyCreate(cmd *command.CreateEntityCommand[*ExternalJwtSigner]) error { - _, err := self.createEntity(cmd.Entity) +func (self *ExternalJwtSignerManager) ApplyCreate(cmd *command.CreateEntityCommand[*ExternalJwtSigner], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *ExternalJwtSignerManager) Update(entity *ExternalJwtSigner, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*ExternalJwtSigner](self, entity, checker) +func (self *ExternalJwtSignerManager) Update(entity *ExternalJwtSigner, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*ExternalJwtSigner](self, entity, checker, ctx) } -func (self *ExternalJwtSignerManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ExternalJwtSigner]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) -} - -func (self *ExternalJwtSignerManager) Read(id string) (*ExternalJwtSigner, error) { - modelEntity := &ExternalJwtSigner{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil +func (self *ExternalJwtSignerManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ExternalJwtSigner], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *ExternalJwtSignerManager) Marshall(entity *ExternalJwtSigner) ([]byte, error) { @@ -156,12 +151,7 @@ func (self *ExternalJwtSignerManager) PublicQuery(query ast.Query) (*ListExtJwtS result := &ListExtJwtSignerResult{ manager: self, QueryMetaData: entityResult.QueryMetaData, - } - - for _, entity := range entityResult.Entities { - if extJwtSigner, ok := entity.(*ExternalJwtSigner); ok { - result.ExtJwtSigners = append(result.ExtJwtSigners, extJwtSigner) - } + ExtJwtSigners: entityResult.Entities, } return result, nil diff --git a/controller/model/external_jwt_signer_model.go b/controller/model/external_jwt_signer_model.go index d22a661a0..2aefdf150 100644 --- a/controller/model/external_jwt_signer_model.go +++ b/controller/model/external_jwt_signer_model.go @@ -22,9 +22,7 @@ import ( "github.com/openziti/fabric/controller/models" nfpem "github.com/openziti/foundation/v2/pem" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -47,7 +45,7 @@ type ExternalJwtSigner struct { NotBefore time.Time } -func (entity *ExternalJwtSigner) toBoltEntity() (boltz.Entity, error) { +func (entity *ExternalJwtSigner) toBoltEntity() (*persistence.ExternalJwtSigner, error) { signer := &persistence.ExternalJwtSigner{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Name: entity.Name, @@ -80,19 +78,15 @@ func (entity *ExternalJwtSigner) toBoltEntity() (boltz.Entity, error) { return signer, nil } -func (entity *ExternalJwtSigner) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *ExternalJwtSigner) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.ExternalJwtSigner, error) { return entity.toBoltEntity() } -func (entity *ExternalJwtSigner) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ExternalJwtSigner) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.ExternalJwtSigner, error) { return entity.toBoltEntity() } -func (entity *ExternalJwtSigner) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltExternalJwtSigner, ok := boltEntity.(*persistence.ExternalJwtSigner) - if !ok { - return errors.Errorf("unexpected type %v when filling model ExternalJwtSigner", reflect.TypeOf(boltEntity)) - } +func (entity *ExternalJwtSigner) fillFrom(_ Env, _ *bbolt.Tx, boltExternalJwtSigner *persistence.ExternalJwtSigner) error { entity.FillCommon(boltExternalJwtSigner) entity.Name = boltExternalJwtSigner.Name entity.CommonName = boltExternalJwtSigner.CommonName diff --git a/controller/model/identity_manager.go b/controller/model/identity_manager.go index b1e009b52..ee538fcb5 100644 --- a/controller/model/identity_manager.go +++ b/controller/model/identity_manager.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/eid" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -52,14 +53,14 @@ const ( ) type IdentityManager struct { - baseEntityManager + baseEntityManager[*Identity, *persistence.Identity] updateSdkInfoTimer metrics.Timer identityStatusMap *identityStatusMap } func NewIdentityManager(env Env) *IdentityManager { manager := &IdentityManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Identity), + baseEntityManager: newBaseEntityManager[*Identity, *persistence.Identity](env, env.GetStores().Identity), updateSdkInfoTimer: env.GetMetricsRegistry().Timer("identity.update-sdk-info"), identityStatusMap: newIdentityStatusMap(IdentityActiveIntervalSeconds * time.Second), } @@ -67,24 +68,25 @@ func NewIdentityManager(env Env) *IdentityManager { network.RegisterManagerDecoder[*Identity](env.GetHostController().GetNetwork().GetManagers(), manager) RegisterCommand(env, &CreateIdentityWithEnrollmentsCmd{}, &edge_cmd_pb.CreateIdentityWithEnrollmentsCmd{}) + RegisterCommand(env, &UpdateServiceConfigsCmd{}, &edge_cmd_pb.UpdateServiceConfigsCmd{}) return manager } -func (self *IdentityManager) newModelEntity() edgeEntity { +func (self *IdentityManager) newModelEntity() *Identity { return &Identity{} } -func (self *IdentityManager) Create(entity *Identity) error { - return network.DispatchCreate[*Identity](self, entity) +func (self *IdentityManager) Create(entity *Identity, ctx *change.Context) error { + return network.DispatchCreate[*Identity](self, entity, ctx) } -func (self *IdentityManager) ApplyCreate(cmd *command.CreateEntityCommand[*Identity]) error { - _, err := self.createEntity(cmd.Entity) +func (self *IdentityManager) ApplyCreate(cmd *command.CreateEntityCommand[*Identity], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *IdentityManager) CreateWithEnrollments(identityModel *Identity, enrollmentsModels []*Enrollment) error { +func (self *IdentityManager) CreateWithEnrollments(identityModel *Identity, enrollmentsModels []*Enrollment, ctx *change.Context) error { if identityModel.Id == "" { identityModel.Id = eid.New() } @@ -100,18 +102,18 @@ func (self *IdentityManager) CreateWithEnrollments(identityModel *Identity, enro manager: self, identity: identityModel, enrollments: enrollmentsModels, + ctx: ctx, } return self.Dispatch(cmd) } -func (self *IdentityManager) ApplyCreateWithEnrollments(cmd *CreateIdentityWithEnrollmentsCmd) error { +func (self *IdentityManager) ApplyCreateWithEnrollments(cmd *CreateIdentityWithEnrollmentsCmd, ctx boltz.MutateContext) error { identityModel := cmd.identity enrollmentsModels := cmd.enrollments - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - boltEntity, err := identityModel.toBoltEntityForCreate(tx, self.impl) + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + boltEntity, err := identityModel.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return err } @@ -135,30 +137,22 @@ func (self *IdentityManager) ApplyCreateWithEnrollments(cmd *CreateIdentityWithE }) } -func (self *IdentityManager) Update(entity *Identity, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*Identity](self, entity, checker) +func (self *IdentityManager) Update(entity *Identity, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*Identity](self, entity, checker, ctx) } -func (self *IdentityManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Identity]) error { +func (self *IdentityManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Identity], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = self if cmd.UpdatedFields != nil { checker = &AndFieldChecker{first: self, second: cmd.UpdatedFields} } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *IdentityManager) IsUpdated(field string) bool { return field != persistence.FieldIdentityAuthenticators && field != persistence.FieldIdentityEnrollments && field != persistence.FieldIdentityIsDefaultAdmin } -func (self *IdentityManager) Read(id string) (*Identity, error) { - entity := &Identity{} - if err := self.readEntity(id, entity); err != nil { - return nil, err - } - return entity, nil -} - func (self *IdentityManager) ReadByName(name string) (*Identity, error) { entity := &Identity{} nameIndex := self.env.GetStores().Identity.GetNameIndex() @@ -168,14 +162,6 @@ func (self *IdentityManager) ReadByName(name string) (*Identity, error) { return entity, nil } -func (self *IdentityManager) readInTx(tx *bbolt.Tx, id string) (*Identity, error) { - identity := &Identity{} - if err := self.readEntityInTx(tx, id, identity); err != nil { - return nil, err - } - return identity, nil -} - func (self *IdentityManager) ReadDefaultAdmin() (*Identity, error) { return self.ReadOneByQuery("isDefaultAdmin = true") } @@ -253,11 +239,12 @@ func (self *IdentityManager) InitializeDefaultAdmin(username, password, name str }, } - if err = self.Create(defaultAdmin); err != nil { + ctx := change.New().SetSource("cli.init").SetChangeAuthorType("cli") + if err = self.Create(defaultAdmin, ctx); err != nil { return err } - if err = self.env.GetManagers().Authenticator.Create(authenticator); err != nil { + if err = self.env.GetManagers().Authenticator.Create(authenticator, ctx); err != nil { return err } @@ -331,7 +318,7 @@ func (self *IdentityManager) collectEnrollmentsInTx(tx *bbolt.Tx, id string, col return nil } -func (self *IdentityManager) CreateWithAuthenticator(identity *Identity, authenticator *Authenticator) (string, string, error) { +func (self *IdentityManager) CreateWithAuthenticator(identity *Identity, authenticator *Authenticator, ctx *change.Context) (string, string, error) { if identity.Id == "" { identity.Id = eid.New() } @@ -357,9 +344,8 @@ func (self *IdentityManager) CreateWithAuthenticator(identity *Identity, authent return "", "", apiErr } - err = self.env.GetDbProvider().GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - boltIdentity, err := identity.toBoltEntityForCreate(tx, self) + err = self.env.GetDbProvider().GetDb().Update(ctx.NewMutateContext(), func(ctx boltz.MutateContext) error { + boltIdentity, err := identity.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return err @@ -369,7 +355,7 @@ func (self *IdentityManager) CreateWithAuthenticator(identity *Identity, authent return err } - boltAuthenticator, err := authenticator.toBoltEntityForCreate(tx, self.env.GetManagers().Authenticator) + boltAuthenticator, err := authenticator.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return err @@ -391,7 +377,7 @@ func (self *IdentityManager) CreateWithAuthenticator(identity *Identity, authent func (self *IdentityManager) GetServiceConfigs(id string) ([]ServiceConfig, error) { var result []ServiceConfig - err := self.GetDb().Update(func(tx *bbolt.Tx) error { + err := self.GetDb().View(func(tx *bbolt.Tx) error { configs, err := self.env.GetStores().Identity.GetServiceConfigs(tx, id) if err != nil { return err @@ -407,24 +393,47 @@ func (self *IdentityManager) GetServiceConfigs(id string) ([]ServiceConfig, erro return result, nil } -func (self *IdentityManager) AssignServiceConfigs(id string, serviceConfigs []ServiceConfig) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - boltServiceConfigs, err := toBoltServiceConfigs(tx, self, serviceConfigs) - if err != nil { - return err - } - return self.env.GetStores().Identity.AssignServiceConfigs(tx, id, boltServiceConfigs...) - }) +func (self *IdentityManager) AssignServiceConfigs(id string, serviceConfigs []ServiceConfig, ctx *change.Context) error { + cmd := &UpdateServiceConfigsCmd{ + manager: self, + identityId: id, + add: true, + serviceConfigs: serviceConfigs, + ctx: ctx, + } + return self.Dispatch(cmd) } -func (self *IdentityManager) RemoveServiceConfigs(id string, serviceConfigs []ServiceConfig) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - boltServiceConfigs, err := toBoltServiceConfigs(tx, self, serviceConfigs) +func (self *IdentityManager) RemoveServiceConfigs(id string, serviceConfigs []ServiceConfig, ctx *change.Context) error { + cmd := &UpdateServiceConfigsCmd{ + manager: self, + identityId: id, + add: false, + serviceConfigs: serviceConfigs, + ctx: ctx, + } + return self.Dispatch(cmd) +} + +func (self *IdentityManager) ApplyUpdateServiceConfigs(cmd *UpdateServiceConfigsCmd, ctx boltz.MutateContext) error { + if cmd.add { + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + boltServiceConfigs, err := toBoltServiceConfigs(ctx.Tx(), self.env, cmd.serviceConfigs) + if err != nil { + return err + } + return self.env.GetStores().Identity.AssignServiceConfigs(ctx.Tx(), cmd.identityId, boltServiceConfigs...) + }) + } + + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + boltServiceConfigs, err := toBoltServiceConfigs(ctx.Tx(), self.env, cmd.serviceConfigs) if err != nil { return err } - return self.env.GetStores().Identity.RemoveServiceConfigs(tx, id, boltServiceConfigs...) + return self.env.GetStores().Identity.RemoveServiceConfigs(ctx.Tx(), cmd.identityId, boltServiceConfigs...) }) + } func (self *IdentityManager) QueryRoleAttributes(queryString string) ([]string, *models.QueryMetaData, error) { @@ -432,7 +441,7 @@ func (self *IdentityManager) QueryRoleAttributes(queryString string) ([]string, return self.queryRoleAttributes(index, queryString) } -func (self *IdentityManager) PatchInfo(identity *Identity) error { +func (self *IdentityManager) PatchInfo(identity *Identity, changeCtx *change.Context) error { start := time.Now() checker := boltz.MapFieldChecker{ persistence.FieldIdentityEnvInfoArch: struct{}{}, @@ -447,7 +456,7 @@ func (self *IdentityManager) PatchInfo(identity *Identity) error { persistence.FieldIdentitySdkInfoAppVersion: struct{}{}, } - err := self.updateEntityBatch(identity, checker) + err := self.updateEntityBatch(identity, checker, changeCtx) self.updateSdkInfoTimer.UpdateSince(start) @@ -498,7 +507,7 @@ func (self *IdentityManager) ReadByExternalId(externalId string) (*Identity, err return identity, nil } -func (self *IdentityManager) Disable(identityId string, duration time.Duration) error { +func (self *IdentityManager) Disable(identityId string, duration time.Duration, ctx *change.Context) error { if duration < 0 { duration = 0 } @@ -522,16 +531,16 @@ func (self *IdentityManager) Disable(identityId string, duration time.Duration) }, DisabledAt: &lockedAt, DisabledUntil: lockedUntil, - }, fieldMap) + }, fieldMap, ctx) if err != nil { return err } - return self.GetEnv().GetManagers().ApiSession.DeleteByIdentityId(identityId) + return self.GetEnv().GetManagers().ApiSession.DeleteByIdentityId(identityId, ctx) } -func (self *IdentityManager) Enable(identityId string) error { +func (self *IdentityManager) Enable(identityId string, ctx *change.Context) error { fieldMap := fields.UpdatedFieldsMap{ persistence.FieldIdentityDisabledAt: struct{}{}, persistence.FieldIdentityDisabledUntil: struct{}{}, @@ -543,7 +552,7 @@ func (self *IdentityManager) Enable(identityId string) error { }, DisabledAt: nil, DisabledUntil: nil, - }, fieldMap) + }, fieldMap, ctx) } func (self *IdentityManager) IdentityToProtobuf(entity *Identity) (*edge_cmd_pb.Identity, error) { @@ -697,10 +706,11 @@ type CreateIdentityWithEnrollmentsCmd struct { manager *IdentityManager identity *Identity enrollments []*Enrollment + ctx *change.Context } -func (self *CreateIdentityWithEnrollmentsCmd) Apply() error { - return self.manager.ApplyCreateWithEnrollments(self) +func (self *CreateIdentityWithEnrollmentsCmd) Apply(ctx boltz.MutateContext) error { + return self.manager.ApplyCreateWithEnrollments(self, ctx) } func (self *CreateIdentityWithEnrollmentsCmd) Encode() ([]byte, error) { @@ -711,6 +721,7 @@ func (self *CreateIdentityWithEnrollmentsCmd) Encode() ([]byte, error) { cmd := &edge_cmd_pb.CreateIdentityWithEnrollmentsCmd{ Identity: identityMsg, + Ctx: ContextToProtobuf(self.ctx), } for _, enrollment := range self.enrollments { @@ -732,7 +743,7 @@ func (self *CreateIdentityWithEnrollmentsCmd) Decode(env Env, msg *edge_cmd_pb.C return err } self.identity = identity - + self.ctx = ProtobufToContext(msg.Ctx) for _, enrollmentMsg := range msg.Enrollments { enrollment, err := self.manager.GetEnv().GetManagers().Enrollment.ProtobufToEnrollment(enrollmentMsg) if err != nil { @@ -744,6 +755,10 @@ func (self *CreateIdentityWithEnrollmentsCmd) Decode(env Env, msg *edge_cmd_pb.C return nil } +func (self *CreateIdentityWithEnrollmentsCmd) GetChangeContext() *change.Context { + return self.ctx +} + type identityStatusMap struct { identityIdToStatus cmap.ConcurrentMap[string, *status] initOnce sync.Once @@ -794,3 +809,53 @@ func (statusMap *identityStatusMap) start() { } }() } + +type UpdateServiceConfigsCmd struct { + manager *IdentityManager + identityId string + add bool + serviceConfigs []ServiceConfig + ctx *change.Context +} + +func (self *UpdateServiceConfigsCmd) Apply(ctx boltz.MutateContext) error { + return self.manager.ApplyUpdateServiceConfigs(self, ctx) +} + +func (self *UpdateServiceConfigsCmd) Encode() ([]byte, error) { + cmd := &edge_cmd_pb.UpdateServiceConfigsCmd{ + IdentityId: self.identityId, + Add: self.add, + Ctx: ContextToProtobuf(self.ctx), + } + + for _, serviceConfig := range self.serviceConfigs { + cmd.ServiceConfigs = append(cmd.ServiceConfigs, &edge_cmd_pb.UpdateServiceConfigsCmd_ServiceConfig{ + ServiceId: serviceConfig.Service, + ConfigId: serviceConfig.Config, + }) + } + + return cmd_pb.EncodeProtobuf(cmd) +} + +func (self *UpdateServiceConfigsCmd) Decode(env Env, msg *edge_cmd_pb.UpdateServiceConfigsCmd) error { + self.manager = env.GetManagers().Identity + + self.identityId = msg.IdentityId + self.add = msg.Add + self.ctx = ProtobufToContext(msg.Ctx) + + for _, serviceConfig := range msg.ServiceConfigs { + self.serviceConfigs = append(self.serviceConfigs, ServiceConfig{ + Service: serviceConfig.ServiceId, + Config: serviceConfig.ConfigId, + }) + } + + return nil +} + +func (self *UpdateServiceConfigsCmd) GetChangeContext() *change.Context { + return self.ctx +} diff --git a/controller/model/identity_model.go b/controller/model/identity_model.go index 0670745ca..bd9fe5000 100644 --- a/controller/model/identity_model.go +++ b/controller/model/identity_model.go @@ -22,9 +22,7 @@ import ( "github.com/openziti/foundation/v2/errorz" "github.com/openziti/sdk-golang/ziti" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -66,8 +64,8 @@ type Identity struct { DisabledUntil *time.Time } -func (entity *Identity) toBoltEntityForCreate(_ *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - identityType, err := manager.GetEnv().GetManagers().IdentityType.ReadByIdOrName(entity.IdentityTypeId) +func (entity *Identity) toBoltEntityForCreate(_ *bbolt.Tx, env Env) (*persistence.Identity, error) { + identityType, err := env.GetManagers().IdentityType.ReadByIdOrName(entity.IdentityTypeId) if err != nil && !boltz.IsErrNotFoundErr(err) { return nil, err @@ -173,9 +171,9 @@ func fillPersistenceInfo(identity *persistence.Identity, envInfo *EnvInfo, sdkIn } } -func (entity *Identity) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { +func (entity *Identity) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, checker boltz.FieldChecker) (*persistence.Identity, error) { if checker == nil || checker.IsUpdated("type") { - identityType, err := manager.GetEnv().GetManagers().IdentityType.ReadByIdOrName(entity.IdentityTypeId) + identityType, err := env.GetManagers().IdentityType.ReadByIdOrName(entity.IdentityTypeId) if err != nil && !boltz.IsErrNotFoundErr(err) { return nil, err @@ -208,14 +206,15 @@ func (entity *Identity) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManage IsAdmin: entity.IsAdmin, } - _, currentType := manager.GetStore().GetSymbol(persistence.FieldIdentityType).Eval(tx, []byte(entity.Id)) + identityStore := env.GetManagers().Identity.GetStore() + _, currentType := identityStore.GetSymbol(persistence.FieldIdentityType).Eval(tx, []byte(entity.Id)) if string(currentType) == persistence.RouterIdentityType { if (checker == nil || checker.IsUpdated("identityTypeId")) && entity.IdentityTypeId != persistence.RouterIdentityType { fieldErr := errorz.NewFieldError("may not change type of router identities", "typeId", entity.IdentityTypeId) return nil, errorz.NewFieldApiError(fieldErr) } - _, currentName := manager.GetStore().GetSymbol(persistence.FieldName).Eval(tx, []byte(entity.Id)) + _, currentName := identityStore.GetSymbol(persistence.FieldName).Eval(tx, []byte(entity.Id)) if (checker == nil || checker.IsUpdated(persistence.FieldName)) && string(currentName) != entity.Name { fieldErr := errorz.NewFieldError("may not change name of router identities", "name", entity.Name) return nil, errorz.NewFieldApiError(fieldErr) @@ -230,11 +229,7 @@ func (entity *Identity) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManage return boltEntity, nil } -func (entity *Identity) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error { - boltIdentity, ok := boltEntity.(*persistence.Identity) - if !ok { - return errors.Errorf("unexpected type %v when filling model identity", reflect.TypeOf(boltEntity)) - } +func (entity *Identity) fillFrom(env Env, _ *bbolt.Tx, boltIdentity *persistence.Identity) error { entity.FillCommon(boltIdentity) entity.Name = boltIdentity.Name entity.IdentityTypeId = boltIdentity.IdentityTypeId @@ -242,7 +237,7 @@ func (entity *Identity) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity entity.IsDefaultAdmin = boltIdentity.IsDefaultAdmin entity.IsAdmin = boltIdentity.IsAdmin entity.RoleAttributes = boltIdentity.RoleAttributes - entity.HasHeartbeat = manager.GetEnv().GetManagers().Identity.IsActive(entity.Id) + entity.HasHeartbeat = env.GetManagers().Identity.IsActive(entity.Id) entity.DefaultHostingPrecedence = boltIdentity.DefaultHostingPrecedence entity.DefaultHostingCost = boltIdentity.DefaultHostingCost entity.ServiceHostingPrecedences = boltIdentity.ServiceHostingPrecedences @@ -262,9 +257,9 @@ type ServiceConfig struct { Config string } -func toBoltServiceConfigs(tx *bbolt.Tx, manager EntityManager, serviceConfigs []ServiceConfig) ([]persistence.ServiceConfig, error) { - serviceStore := manager.GetEnv().GetStores().EdgeService - configStore := manager.GetEnv().GetStores().Config +func toBoltServiceConfigs(tx *bbolt.Tx, env Env, serviceConfigs []ServiceConfig) ([]persistence.ServiceConfig, error) { + serviceStore := env.GetStores().EdgeService + configStore := env.GetStores().Config var boltServiceConfigs []persistence.ServiceConfig for _, serviceConfig := range serviceConfigs { diff --git a/controller/model/identity_type_manager.go b/controller/model/identity_type_manager.go index 033212de7..fc7651c41 100644 --- a/controller/model/identity_type_manager.go +++ b/controller/model/identity_type_manager.go @@ -17,12 +17,13 @@ package model import ( + "github.com/openziti/edge/controller/persistence" "github.com/openziti/storage/boltz" ) func NewIdentityTypeManager(env Env) *IdentityTypeManager { manager := &IdentityTypeManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().IdentityType), + baseEntityManager: newBaseEntityManager[*IdentityType, *persistence.IdentityType](env, env.GetStores().IdentityType), } manager.impl = manager @@ -30,21 +31,13 @@ func NewIdentityTypeManager(env Env) *IdentityTypeManager { } type IdentityTypeManager struct { - baseEntityManager + baseEntityManager[*IdentityType, *persistence.IdentityType] } -func (self *IdentityTypeManager) newModelEntity() edgeEntity { +func (self *IdentityTypeManager) newModelEntity() *IdentityType { return &IdentityType{} } -func (self *IdentityTypeManager) Read(id string) (*IdentityType, error) { - modelEntity := &IdentityType{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - func (self *IdentityTypeManager) ReadByIdOrName(idOrName string) (*IdentityType, error) { modelEntity := &IdentityType{} err := self.readEntity(idOrName, modelEntity) diff --git a/controller/model/identity_type_model.go b/controller/model/identity_type_model.go index 2014786c2..9eb808866 100644 --- a/controller/model/identity_type_model.go +++ b/controller/model/identity_type_model.go @@ -20,9 +20,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) const ( @@ -34,26 +32,22 @@ type IdentityType struct { Name string `json:"name"` } -func (entity *IdentityType) toBoltEntity() (boltz.Entity, error) { +func (entity *IdentityType) toBoltEntity() (*persistence.IdentityType, error) { return &persistence.IdentityType{ Name: entity.Name, BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), }, nil } -func (entity *IdentityType) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *IdentityType) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.IdentityType, error) { return entity.toBoltEntity() } -func (entity *IdentityType) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *IdentityType) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.IdentityType, error) { return entity.toBoltEntity() } -func (entity *IdentityType) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltIdentityType, ok := boltEntity.(*persistence.IdentityType) - if !ok { - return errors.Errorf("unexpected type %v when filling model IdentityType", reflect.TypeOf(boltEntity)) - } +func (entity *IdentityType) fillFrom(_ Env, _ *bbolt.Tx, boltIdentityType *persistence.IdentityType) error { entity.FillCommon(boltIdentityType) entity.Name = boltIdentityType.Name return nil diff --git a/controller/model/mfa_manager.go b/controller/model/mfa_manager.go index 85e53e189..114661846 100644 --- a/controller/model/mfa_manager.go +++ b/controller/model/mfa_manager.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -43,7 +44,7 @@ const ( func NewMfaManager(env Env) *MfaManager { manager := &MfaManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Mfa), + baseEntityManager: newBaseEntityManager[*Mfa, *persistence.Mfa](env, env.GetStores().Mfa), } manager.impl = manager @@ -53,14 +54,14 @@ func NewMfaManager(env Env) *MfaManager { } type MfaManager struct { - baseEntityManager + baseEntityManager[*Mfa, *persistence.Mfa] } -func (self *MfaManager) newModelEntity() edgeEntity { +func (self *MfaManager) newModelEntity() *Mfa { return &Mfa{} } -func (self *MfaManager) CreateForIdentity(identity *Identity) (string, error) { +func (self *MfaManager) CreateForIdentity(identity *Identity, ctx *change.Context) (string, error) { secretBytes := make([]byte, 10) _, _ = rand.Read(secretBytes) secret := base32.StdEncoding.EncodeToString(secretBytes) @@ -79,22 +80,21 @@ func (self *MfaManager) CreateForIdentity(identity *Identity) (string, error) { RecoveryCodes: recoveryCodes, } - err = self.Create(mfa) + err = self.Create(mfa, ctx) if err != nil { return "", err } return mfa.Id, err } -func (self *MfaManager) Create(entity *Mfa) error { - return network.DispatchCreate[*Mfa](self, entity) +func (self *MfaManager) Create(entity *Mfa, ctx *change.Context) error { + return network.DispatchCreate[*Mfa](self, entity, ctx) } -func (self *MfaManager) ApplyCreate(cmd *command.CreateEntityCommand[*Mfa]) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) +func (self *MfaManager) ApplyCreate(cmd *command.CreateEntityCommand[*Mfa], ctx boltz.MutateContext) error { + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { result := &MfaListResult{manager: self} - err := self.ListWithTx(tx, fmt.Sprintf(`identity = "%s"`, cmd.Entity.IdentityId), result.collect) + err := self.ListWithTx(ctx.Tx(), fmt.Sprintf(`identity = "%s"`, cmd.Entity.IdentityId), result.collect) if err != nil { return err @@ -110,32 +110,16 @@ func (self *MfaManager) ApplyCreate(cmd *command.CreateEntityCommand[*Mfa]) erro }) } -func (self *MfaManager) Update(entity *Mfa, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*Mfa](self, entity, checker) +func (self *MfaManager) Update(entity *Mfa, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*Mfa](self, entity, checker, ctx) } -func (self *MfaManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Mfa]) error { +func (self *MfaManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*Mfa], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = self if cmd.UpdatedFields != nil { checker = &AndFieldChecker{first: self, second: cmd.UpdatedFields} } - return self.updateEntity(cmd.Entity, checker) -} - -func (self *MfaManager) Read(id string) (*Mfa, error) { - modelMfa := &Mfa{} - if err := self.readEntity(id, modelMfa); err != nil { - return nil, err - } - return modelMfa, nil -} - -func (self *MfaManager) readInTx(tx *bbolt.Tx, id string) (*Mfa, error) { - modelMfa := &Mfa{} - if err := self.readEntityInTx(tx, id, modelMfa); err != nil { - return nil, err - } - return modelMfa, nil + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *MfaManager) IsUpdated(field string) bool { @@ -171,12 +155,12 @@ func (self *MfaManager) ReadOneByIdentityId(identityId string) (*Mfa, error) { return resultList.Mfas[0], nil } -func (self *MfaManager) Verify(mfa *Mfa, code string) (bool, error) { +func (self *MfaManager) Verify(mfa *Mfa, code string, ctx *change.Context) (bool, error) { //check recovery codes for i, recoveryCode := range mfa.RecoveryCodes { if recoveryCode == code { mfa.RecoveryCodes = append(mfa.RecoveryCodes[:i], mfa.RecoveryCodes[i+1:]...) - if err := self.Update(mfa, nil); err != nil { + if err := self.Update(mfa, nil, ctx); err != nil { return false, err } return true, nil @@ -197,7 +181,7 @@ func (self *MfaManager) VerifyTOTP(mfa *Mfa, code string) (bool, error) { return otp.Authenticate(code) } -func (self *MfaManager) DeleteForIdentity(identity *Identity, code string) error { +func (self *MfaManager) DeleteForIdentity(identity *Identity, code string, ctx *change.Context) error { mfa, err := self.ReadOneByIdentityId(identity.Id) if err != nil { @@ -210,14 +194,14 @@ func (self *MfaManager) DeleteForIdentity(identity *Identity, code string) error if mfa.IsVerified { //if MFA is enabled require a valid code - valid, err := self.Verify(mfa, code) + valid, err := self.Verify(mfa, code, ctx) if err != nil || !valid { return apierror.NewInvalidMfaTokenError() } } - if err = self.Delete(mfa.Id); err != nil { + if err = self.Delete(mfa.Id, ctx); err != nil { return err } @@ -243,7 +227,7 @@ func (self *MfaManager) GetProvisioningUrl(mfa *Mfa) string { return otcConfig.ProvisionURIWithIssuer(mfa.Identity.Name, "ziti.dev") } -func (self *MfaManager) RecreateRecoveryCodes(mfa *Mfa) error { +func (self *MfaManager) RecreateRecoveryCodes(mfa *Mfa, ctx *change.Context) error { newCodes, err := self.generateRecoveryCodes() if err != nil { return err @@ -251,7 +235,7 @@ func (self *MfaManager) RecreateRecoveryCodes(mfa *Mfa) error { mfa.RecoveryCodes = newCodes - return self.Update(mfa, nil) + return self.Update(mfa, nil, ctx) } func (self *MfaManager) generateRecoveryCodes() ([]string, error) { @@ -313,9 +297,8 @@ func (self *MfaManager) Unmarshall(bytes []byte) (*Mfa, error) { } // DeleteAllForIdentity is meant for administrators to remove all MFAs (enrolled or not) from an identity -func (self *MfaManager) DeleteAllForIdentity(id string) error { - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) +func (self *MfaManager) DeleteAllForIdentity(id string, ctx *change.Context) error { + return self.GetDb().Update(ctx.NewMutateContext(), func(ctx boltz.MutateContext) error { return self.Store.DeleteWhere(ctx, fmt.Sprintf("identity = \"%s\"", id)) }) } diff --git a/controller/model/mfa_model.go b/controller/model/mfa_model.go index 6fdb6fa24..6844f310b 100644 --- a/controller/model/mfa_model.go +++ b/controller/model/mfa_model.go @@ -21,9 +21,7 @@ import ( "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) const ( @@ -40,8 +38,8 @@ type Mfa struct { RecoveryCodes []string } -func (entity *Mfa) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - if !manager.GetEnv().GetStores().Identity.IsEntityPresent(tx, entity.IdentityId) { +func (entity *Mfa) toBoltEntity(tx *bbolt.Tx, env Env) (*persistence.Mfa, error) { + if !env.GetStores().Identity.IsEntityPresent(tx, entity.IdentityId) { return nil, errorz.NewFieldError("identity not found", "IdentityId", entity.IdentityId) } @@ -56,30 +54,26 @@ func (entity *Mfa) toBoltEntity(tx *bbolt.Tx, manager EntityManager) (boltz.Enti return boltEntity, nil } -func (entity *Mfa) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *Mfa) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.Mfa, error) { + return entity.toBoltEntity(tx, env) } -func (entity *Mfa) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntity(tx, manager) +func (entity *Mfa) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.Mfa, error) { + return entity.toBoltEntity(tx, env) } -func (entity *Mfa) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error { - boltMfa, ok := boltEntity.(*persistence.Mfa) - if !ok { - return errors.Errorf("unexpected type %v when filling model Mfa", reflect.TypeOf(boltEntity)) - } +func (entity *Mfa) fillFrom(env Env, tx *bbolt.Tx, boltMfa *persistence.Mfa) error { entity.FillCommon(boltMfa) entity.IsVerified = boltMfa.IsVerified entity.IdentityId = boltMfa.IdentityId entity.RecoveryCodes = boltMfa.RecoveryCodes entity.Secret = boltMfa.Secret - boltIdentity, err := manager.GetEnv().GetStores().Identity.LoadOneById(tx, boltMfa.IdentityId) + boltIdentity, err := env.GetStores().Identity.LoadOneById(tx, boltMfa.IdentityId) if err != nil { return err } modelIdentity := &Identity{} - if err := modelIdentity.fillFrom(manager, tx, boltIdentity); err != nil { + if err = modelIdentity.fillFrom(env, tx, boltIdentity); err != nil { return err } entity.Identity = modelIdentity diff --git a/controller/model/pbutils.go b/controller/model/pbutils.go index b40da93d5..7ae9ea21a 100644 --- a/controller/model/pbutils.go +++ b/controller/model/pbutils.go @@ -17,6 +17,8 @@ package model import ( + "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "google.golang.org/protobuf/types/known/timestamppb" "time" ) @@ -36,3 +38,23 @@ func pbTimeToTimePtr(pb *timestamppb.Timestamp) *time.Time { result := pb.AsTime() return &result } + +func ContextToProtobuf(context *change.Context) *edge_cmd_pb.ChangeContext { + if context == nil { + return nil + } + return &edge_cmd_pb.ChangeContext{ + Attributes: context.Attributes, + RaftIndex: context.RaftIndex, + } +} + +func ProtobufToContext(context *edge_cmd_pb.ChangeContext) *change.Context { + if context == nil { + return nil + } + return &change.Context{ + Attributes: context.Attributes, + RaftIndex: context.RaftIndex, + } +} diff --git a/controller/model/posture_check_manager.go b/controller/model/posture_check_manager.go index e1da8a5ce..a01fed630 100644 --- a/controller/model/posture_check_manager.go +++ b/controller/model/posture_check_manager.go @@ -21,6 +21,7 @@ import ( lru "github.com/hashicorp/golang-lru/v2" "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" @@ -42,51 +43,49 @@ func NewPostureCheckManager(env Env) *PostureCheckManager { panic(err) } manager := &PostureCheckManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().PostureCheck), + baseEntityManager: newBaseEntityManager[*PostureCheck, *persistence.PostureCheck](env, env.GetStores().PostureCheck), cache: cache, } manager.impl = manager network.RegisterManagerDecoder[*PostureCheck](env.GetHostController().GetNetwork().GetManagers(), manager) - evictF := func(i ...interface{}) { - postureCheck := i[0].(*persistence.PostureCheck) - manager.cache.Remove(postureCheck.Id) + evictF := func(postureCheckId string) { + manager.cache.Remove(postureCheckId) } - manager.Store.AddListener(boltz.EventUpdate, evictF) - manager.Store.AddListener(boltz.EventDelete, evictF) + manager.Store.AddEntityIdListener(evictF, boltz.EntityUpdated, boltz.EntityDeleted) return manager } type PostureCheckManager struct { - baseEntityManager + baseEntityManager[*PostureCheck, *persistence.PostureCheck] cache *lru.Cache[string, *PostureCheck] } -func (self *PostureCheckManager) newModelEntity() edgeEntity { +func (self *PostureCheckManager) newModelEntity() *PostureCheck { return &PostureCheck{} } -func (self *PostureCheckManager) Create(entity *PostureCheck) error { - return network.DispatchCreate[*PostureCheck](self, entity) +func (self *PostureCheckManager) Create(entity *PostureCheck, ctx *change.Context) error { + return network.DispatchCreate[*PostureCheck](self, entity, ctx) } -func (self *PostureCheckManager) ApplyCreate(cmd *command.CreateEntityCommand[*PostureCheck]) error { - _, err := self.createEntity(cmd.Entity) +func (self *PostureCheckManager) ApplyCreate(cmd *command.CreateEntityCommand[*PostureCheck], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *PostureCheckManager) Update(entity *PostureCheck, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*PostureCheck](self, entity, checker) +func (self *PostureCheckManager) Update(entity *PostureCheck, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*PostureCheck](self, entity, checker, ctx) } -func (self *PostureCheckManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*PostureCheck]) error { +func (self *PostureCheckManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*PostureCheck], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = self if cmd.UpdatedFields != nil { checker = &AndFieldChecker{first: self, second: cmd.UpdatedFields} } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *PostureCheckManager) Read(id string) (*PostureCheck, error) { diff --git a/controller/model/posture_check_model.go b/controller/model/posture_check_model.go index 0b058407c..0170e33d7 100644 --- a/controller/model/posture_check_model.go +++ b/controller/model/posture_check_model.go @@ -22,9 +22,7 @@ import ( "github.com/openziti/edge/pb/edge_cmd_pb" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "time" ) @@ -39,8 +37,8 @@ type PostureCheck struct { type PostureCheckSubType interface { TypeId() string - toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (persistence.PostureCheckSubType, error) - fillFrom(manager EntityManager, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error + toBoltEntityForCreate(tx *bbolt.Tx, env Env) (persistence.PostureCheckSubType, error) + fillFrom(env Env, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error Evaluate(apiSessionId string, pd *PostureData) bool FailureValues(_ string, pd *PostureData) PostureCheckFailureValues GetTimeoutSeconds() int64 @@ -85,11 +83,7 @@ func newSubType(typeId string) PostureCheckSubType { return nil } -func (entity *PostureCheck) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEntity boltz.Entity) error { - boltPostureCheck, ok := boltEntity.(*persistence.PostureCheck) - if !ok { - return errors.Errorf("unexpected type %v when filling model posture check", reflect.TypeOf(boltEntity)) - } +func (entity *PostureCheck) fillFrom(env Env, tx *bbolt.Tx, boltPostureCheck *persistence.PostureCheck) error { entity.FillCommon(boltPostureCheck) entity.Name = boltPostureCheck.Name entity.TypeId = boltPostureCheck.TypeId @@ -102,7 +96,7 @@ func (entity *PostureCheck) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEn return fmt.Errorf("cannot create posture check subtype [%v]", entity.TypeId) } - if err := subType.fillFrom(manager, tx, boltPostureCheck, boltPostureCheck.SubType); err != nil { + if err := subType.fillFrom(env, tx, boltPostureCheck, boltPostureCheck.SubType); err != nil { return fmt.Errorf("error filling posture check subType [%v]: %v", entity.TypeId, err) } @@ -111,7 +105,7 @@ func (entity *PostureCheck) fillFrom(manager EntityManager, tx *bbolt.Tx, boltEn return nil } -func (entity *PostureCheck) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { +func (entity *PostureCheck) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.PostureCheck, error) { boltEntity := &persistence.PostureCheck{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Name: entity.Name, @@ -121,15 +115,15 @@ func (entity *PostureCheck) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityMa } var err error - if boltEntity.SubType, err = entity.SubType.toBoltEntityForCreate(tx, manager); err != nil { + if boltEntity.SubType, err = entity.SubType.toBoltEntityForCreate(tx, env); err != nil { return nil, fmt.Errorf("error converting to bolt posture check subType [%v] for create: %v", entity.TypeId, err) } return boltEntity, nil } -func (entity *PostureCheck) toBoltEntityForUpdate(tx *bbolt.Tx, manager EntityManager, _ boltz.FieldChecker) (boltz.Entity, error) { - return entity.toBoltEntityForCreate(tx, manager) +func (entity *PostureCheck) toBoltEntityForUpdate(tx *bbolt.Tx, env Env, _ boltz.FieldChecker) (*persistence.PostureCheck, error) { + return entity.toBoltEntityForCreate(tx, env) } func (entity *PostureCheck) Evaluate(apiSessionId string, pd *PostureData) (bool, *PostureCheckFailure) { diff --git a/controller/model/posture_check_model_mac.go b/controller/model/posture_check_model_mac.go index b4ffd3534..1d677a49a 100644 --- a/controller/model/posture_check_model_mac.go +++ b/controller/model/posture_check_model_mac.go @@ -96,7 +96,7 @@ func newPostureCheckMacAddresses() PostureCheckSubType { return &PostureCheckMacAddresses{} } -func (p *PostureCheckMacAddresses) fillFrom(_ EntityManager, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckMacAddresses) fillFrom(_ Env, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckMacAddresses) if subCheck == nil { @@ -107,7 +107,7 @@ func (p *PostureCheckMacAddresses) fillFrom(_ EntityManager, tx *bbolt.Tx, check return nil } -func (p *PostureCheckMacAddresses) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckMacAddresses) toBoltEntityForCreate(*bbolt.Tx, Env) (persistence.PostureCheckSubType, error) { return &persistence.PostureCheckMacAddresses{ MacAddresses: p.MacAddresses, }, nil diff --git a/controller/model/posture_check_model_mfa.go b/controller/model/posture_check_model_mfa.go index 0fb9e598c..b4e47ee54 100644 --- a/controller/model/posture_check_model_mfa.go +++ b/controller/model/posture_check_model_mfa.go @@ -316,7 +316,7 @@ func newPostureCheckMfa() PostureCheckSubType { return &PostureCheckMfa{} } -func (p *PostureCheckMfa) fillFrom(_ EntityManager, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckMfa) fillFrom(_ Env, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckMfa) if subCheck == nil { @@ -331,7 +331,7 @@ func (p *PostureCheckMfa) fillFrom(_ EntityManager, tx *bbolt.Tx, check *persist return nil } -func (p *PostureCheckMfa) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckMfa) toBoltEntityForCreate(*bbolt.Tx, Env) (persistence.PostureCheckSubType, error) { return &persistence.PostureCheckMfa{ TimeoutSeconds: p.TimeoutSeconds, PromptOnWake: p.PromptOnWake, diff --git a/controller/model/posture_check_model_os.go b/controller/model/posture_check_model_os.go index 57aecdc06..1500d2e46 100644 --- a/controller/model/posture_check_model_os.go +++ b/controller/model/posture_check_model_os.go @@ -148,7 +148,7 @@ func newPostureCheckOperatingSystem() PostureCheckSubType { return &PostureCheckOperatingSystem{} } -func (p *PostureCheckOperatingSystem) fillFrom(_ EntityManager, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckOperatingSystem) fillFrom(_ Env, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckOperatingSystem) if subCheck == nil { @@ -178,7 +178,7 @@ func (p *PostureCheckOperatingSystem) validateOsVersions() error { return nil } -func (p *PostureCheckOperatingSystem) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckOperatingSystem) toBoltEntityForCreate(*bbolt.Tx, Env) (persistence.PostureCheckSubType, error) { ret := &persistence.PostureCheckOperatingSystem{ OperatingSystems: []persistence.OperatingSystem{}, } diff --git a/controller/model/posture_check_model_process.go b/controller/model/posture_check_model_process.go index 0254f5c19..896d44ea9 100644 --- a/controller/model/posture_check_model_process.go +++ b/controller/model/posture_check_model_process.go @@ -148,7 +148,7 @@ func newPostureCheckProcess() PostureCheckSubType { return &PostureCheckProcess{} } -func (p *PostureCheckProcess) fillFrom(_ EntityManager, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckProcess) fillFrom(_ Env, tx *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckProcess) if subCheck == nil { @@ -163,7 +163,7 @@ func (p *PostureCheckProcess) fillFrom(_ EntityManager, tx *bbolt.Tx, check *per return nil } -func (p *PostureCheckProcess) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckProcess) toBoltEntityForCreate(*bbolt.Tx, Env) (persistence.PostureCheckSubType, error) { return &persistence.PostureCheckProcess{ OperatingSystem: p.OsType, Path: p.Path, diff --git a/controller/model/posture_check_model_process_multi.go b/controller/model/posture_check_model_process_multi.go index f5eca9899..520f80242 100644 --- a/controller/model/posture_check_model_process_multi.go +++ b/controller/model/posture_check_model_process_multi.go @@ -184,7 +184,7 @@ func newPostureCheckProcessMulti() PostureCheckSubType { return &PostureCheckProcessMulti{} } -func (p *PostureCheckProcessMulti) fillFrom(_ EntityManager, _ *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckProcessMulti) fillFrom(_ Env, _ *bbolt.Tx, check *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckProcessMulti) if subCheck == nil { @@ -208,7 +208,7 @@ func (p *PostureCheckProcessMulti) fillFrom(_ EntityManager, _ *bbolt.Tx, check return nil } -func (p *PostureCheckProcessMulti) toBoltEntityForCreate(_ *bbolt.Tx, _ EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckProcessMulti) toBoltEntityForCreate(_ *bbolt.Tx, _ Env) (persistence.PostureCheckSubType, error) { ret := &persistence.PostureCheckProcessMulti{ Semantic: p.Semantic, } diff --git a/controller/model/posture_check_model_windows_domain.go b/controller/model/posture_check_model_windows_domain.go index d88fb7893..1006ac5d2 100644 --- a/controller/model/posture_check_model_windows_domain.go +++ b/controller/model/posture_check_model_windows_domain.go @@ -102,7 +102,7 @@ func newPostureCheckWindowsDomains() PostureCheckSubType { return &PostureCheckDomains{} } -func (p *PostureCheckDomains) fillFrom(_ EntityManager, _ *bbolt.Tx, _ *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { +func (p *PostureCheckDomains) fillFrom(_ Env, _ *bbolt.Tx, _ *persistence.PostureCheck, subType persistence.PostureCheckSubType) error { subCheck := subType.(*persistence.PostureCheckWindowsDomains) if subCheck == nil { @@ -113,7 +113,7 @@ func (p *PostureCheckDomains) fillFrom(_ EntityManager, _ *bbolt.Tx, _ *persiste return nil } -func (p *PostureCheckDomains) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (persistence.PostureCheckSubType, error) { +func (p *PostureCheckDomains) toBoltEntityForCreate(*bbolt.Tx, Env) (persistence.PostureCheckSubType, error) { return &persistence.PostureCheckWindowsDomains{ Domains: p.Domains, }, nil diff --git a/controller/model/posture_check_type_manager.go b/controller/model/posture_check_type_manager.go index 8033eb504..05ac9a450 100644 --- a/controller/model/posture_check_type_manager.go +++ b/controller/model/posture_check_type_manager.go @@ -16,35 +16,20 @@ package model +import "github.com/openziti/edge/controller/persistence" + func NewPostureCheckTypeManager(env Env) *PostureCheckTypeManager { manager := &PostureCheckTypeManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().PostureCheckType), + baseEntityManager: newBaseEntityManager[*PostureCheckType, *persistence.PostureCheckType](env, env.GetStores().PostureCheckType), } manager.impl = manager return manager } type PostureCheckTypeManager struct { - baseEntityManager + baseEntityManager[*PostureCheckType, *persistence.PostureCheckType] } -func (self *PostureCheckTypeManager) newModelEntity() edgeEntity { +func (self *PostureCheckTypeManager) newModelEntity() *PostureCheckType { return &PostureCheckType{} } - -func (self *PostureCheckTypeManager) Read(id string) (*PostureCheckType, error) { - modelEntity := &PostureCheckType{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - -func (self *PostureCheckTypeManager) ReadByName(name string) (*PostureCheckType, error) { - modelPostureCheckType := &PostureCheckType{} - nameIndex := self.env.GetStores().PostureCheckType.GetNameIndex() - if err := self.readEntityWithIndex("name", []byte(name), nameIndex, modelPostureCheckType); err != nil { - return nil, err - } - return modelPostureCheckType, nil -} diff --git a/controller/model/posture_check_type_model.go b/controller/model/posture_check_type_model.go index 2d024f665..b3ca91c5f 100644 --- a/controller/model/posture_check_type_model.go +++ b/controller/model/posture_check_type_model.go @@ -20,9 +20,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type PostureCheckType struct { @@ -31,7 +29,7 @@ type PostureCheckType struct { OperatingSystems []OperatingSystem } -func (entity *PostureCheckType) toBoltEntity() (boltz.Entity, error) { +func (entity *PostureCheckType) toBoltEntity() (*persistence.PostureCheckType, error) { var operatingSystems []persistence.OperatingSystem for _, os := range entity.OperatingSystems { @@ -41,27 +39,22 @@ func (entity *PostureCheckType) toBoltEntity() (boltz.Entity, error) { }) } - return &persistence.PostureCheckOs{ + return &persistence.PostureCheckType{ Name: entity.Name, OperatingSystems: operatingSystems, BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), }, nil } -func (entity *PostureCheckType) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *PostureCheckType) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.PostureCheckType, error) { return entity.toBoltEntity() } -func (entity *PostureCheckType) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *PostureCheckType) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.PostureCheckType, error) { return entity.toBoltEntity() } -func (entity *PostureCheckType) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltPostureCheckType, ok := boltEntity.(*persistence.PostureCheckOs) - if !ok { - return errors.Errorf("unexpected type %v when filling model PostureCheckOs", reflect.TypeOf(boltEntity)) - } - +func (entity *PostureCheckType) fillFrom(_ Env, _ *bbolt.Tx, boltPostureCheckType *persistence.PostureCheckType) error { var operatingSystems []OperatingSystem for _, os := range boltPostureCheckType.OperatingSystems { diff --git a/controller/model/posture_response_manager.go b/controller/model/posture_response_manager.go index e1ba8da07..8c4f880d0 100644 --- a/controller/model/posture_response_manager.go +++ b/controller/model/posture_response_manager.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/db" "github.com/openziti/storage/ast" "go.etcd.io/bbolt" @@ -208,9 +209,8 @@ func (self *PostureResponseManager) postureDataUpdated(env Env, identityId strin for _, sessionId := range sessionIdsToDelete { //todo: delete batch? - _ = self.env.GetManagers().Session.Delete(sessionId) + _ = self.env.GetManagers().Session.Delete(sessionId, change.New().SetSource("posture.cache").SetChangeAuthorType("controller")) } - } func (self *PostureResponseManager) Evaluate(identityId, apiSessionId string, check *PostureCheck) (bool, *PostureCheckFailure) { @@ -325,7 +325,7 @@ func (self *PostureResponseManager) GetEndpointStateChangeAffectedServices(timeS service, err := self.env.GetStores().EdgeService.LoadOneById(tx, string(serviceCursor.Current())) if err == nil { modelService := &Service{} - if err := modelService.fillFrom(self.env.GetManagers().EdgeService, tx, service); err == nil { + if err := modelService.fillFrom(self.env, tx, service); err == nil { //use the lowest configured timeout (which is some timeout or no timeout) if existingService, ok := services[service.Id]; !ok || timeout < existingService.Timeout { services[service.Id] = &ServiceWithTimeout{ diff --git a/controller/model/posture_response_model.go b/controller/model/posture_response_model.go index 335e9216d..02e745ad4 100644 --- a/controller/model/posture_response_model.go +++ b/controller/model/posture_response_model.go @@ -22,6 +22,7 @@ import ( "github.com/kataras/go-events" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" + "github.com/openziti/fabric/controller/change" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" cmap "github.com/orcaman/concurrent-map/v2" @@ -56,12 +57,11 @@ func newPostureCache(env Env) *PostureCache { pc.run(env.GetHostController().GetCloseNotifyChannel()) - env.GetStores().ApiSession.AddListener(boltz.EventCreate, pc.ApiSessionCreated) - env.GetStores().ApiSession.AddListener(boltz.EventDelete, pc.ApiSessionDeleted) - env.GetStores().Identity.AddListener(boltz.EventDelete, pc.IdentityDeleted) + env.GetStores().ApiSession.AddEntityEventListenerF(pc.ApiSessionCreated, boltz.EntityCreatedAsync) + env.GetStores().ApiSession.AddEntityEventListenerF(pc.ApiSessionDeleted, boltz.EntityDeletedAsync) + env.GetStores().Identity.AddEntityEventListenerF(pc.IdentityDeleted, boltz.EntityDeletedAsync) - env.GetStores().PostureCheckType.AddListener(boltz.EventCreate, pc.PostureCheckChanged) - env.GetStores().PostureCheckType.AddListener(boltz.EventUpdate, pc.PostureCheckChanged) + env.GetStores().PostureCheckType.AddListener(pc.PostureCheckChanged, boltz.EntityCreatedAsync, boltz.EntityUpdatedAsync) return pc } @@ -153,7 +153,7 @@ func (pc *PostureCache) evaluate() { //delete sessions that failed pc checks, clear list for _, sessionId := range toDeleteSessionIds { - err := pc.env.GetManagers().Session.Delete(sessionId) + err := pc.env.GetManagers().Session.Delete(sessionId, change.New().SetSource("posture.cache").SetChangeAuthorType("controller")) if err != nil { log.WithError(err).Errorf("error removing session [%s] due to posture check failure, delete error: %v", sessionId, err) } @@ -277,37 +277,11 @@ func (pc *PostureCache) WithPostureData(identityId string, f func(data *PostureD }) } -func (pc *PostureCache) ApiSessionCreated(args ...interface{}) { - var apiSession *persistence.ApiSession - if len(args) == 1 { - apiSession, _ = args[0].(*persistence.ApiSession) - } else { - pfxlog.Logger().Errorf("unexpected number of args [%d]", len(args)) - return - } - - if apiSession == nil { - pfxlog.Logger().Error("api session create event trigger with args[0] not convertible to *persistence.ApiSession") - return - } - +func (pc *PostureCache) ApiSessionCreated(apiSession *persistence.ApiSession) { pc.apiSessionIdToIdentityId.Set(apiSession.Id, apiSession.IdentityId) } -func (pc *PostureCache) ApiSessionDeleted(args ...interface{}) { - var apiSession *persistence.ApiSession - if len(args) == 1 { - apiSession, _ = args[0].(*persistence.ApiSession) - } else { - pfxlog.Logger().Errorf("unexpected number of args [%d]", len(args)) - return - } - - if apiSession == nil { - pfxlog.Logger().Error("api session delete event trigger with args[0] not convertible to *persistence.ApiSession") - return - } - +func (pc *PostureCache) ApiSessionDeleted(apiSession *persistence.ApiSession) { pc.identityToPostureData.Upsert(apiSession.IdentityId, newPostureData(), func(exist bool, valueInMap *PostureData, newValue *PostureData) *PostureData { if exist { if valueInMap != nil && valueInMap.ApiSessions != nil { @@ -323,39 +297,13 @@ func (pc *PostureCache) ApiSessionDeleted(args ...interface{}) { pc.apiSessionIdToIdentityId.Remove(apiSession.Id) } -func (pc *PostureCache) IdentityDeleted(args ...interface{}) { - var identity *persistence.Identity - if len(args) == 1 { - identity, _ = args[0].(*persistence.Identity) - } else { - pfxlog.Logger().Errorf("unexpected number of args [%d]", len(args)) - return - } - - if identity == nil { - pfxlog.Logger().Error("identity delete event trigger with args[0] not convertible to *persistence.ApiSession") - return - } - +func (pc *PostureCache) IdentityDeleted(identity *persistence.Identity) { pc.identityToPostureData.Remove(identity.Id) } // PostureCheckChanged notifies all associated identities that posture configuration has changed // and that endpoints may need to reevaluate posture queries. -func (pc *PostureCache) PostureCheckChanged(args ...interface{}) { - var entity boltz.Entity - if len(args) == 1 { - var ok bool - entity, ok = args[0].(boltz.Entity) - - if !ok { - pfxlog.Logger().Errorf("unexpected type [%T] expected boltz.Entity: %v", args[0], args[0]) - } - } else { - pfxlog.Logger().Errorf("unexpected number of args [%d]", len(args)) - return - } - +func (pc *PostureCache) PostureCheckChanged(entity boltz.Entity) { servicePolicyLinks := pc.env.GetStores().PostureCheck.GetLinkCollection(persistence.EntityTypeServicePolicies) if servicePolicyLinks == nil { diff --git a/controller/model/service_edge_router_policy_manager.go b/controller/model/service_edge_router_policy_manager.go index 891a0c440..6fb85e192 100644 --- a/controller/model/service_edge_router_policy_manager.go +++ b/controller/model/service_edge_router_policy_manager.go @@ -17,18 +17,20 @@ package model import ( + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" - "go.etcd.io/bbolt" + "github.com/openziti/storage/boltz" "google.golang.org/protobuf/proto" ) func NewServiceEdgeRouterPolicyManager(env Env) *ServiceEdgeRouterPolicyManager { manager := &ServiceEdgeRouterPolicyManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ServiceEdgeRouterPolicy), + baseEntityManager: newBaseEntityManager[*ServiceEdgeRouterPolicy, *persistence.ServiceEdgeRouterPolicy](env, env.GetStores().ServiceEdgeRouterPolicy), } manager.impl = manager @@ -38,44 +40,28 @@ func NewServiceEdgeRouterPolicyManager(env Env) *ServiceEdgeRouterPolicyManager } type ServiceEdgeRouterPolicyManager struct { - baseEntityManager + baseEntityManager[*ServiceEdgeRouterPolicy, *persistence.ServiceEdgeRouterPolicy] } -func (self *ServiceEdgeRouterPolicyManager) newModelEntity() edgeEntity { +func (self *ServiceEdgeRouterPolicyManager) newModelEntity() *ServiceEdgeRouterPolicy { return &ServiceEdgeRouterPolicy{} } -func (self *ServiceEdgeRouterPolicyManager) Create(entity *ServiceEdgeRouterPolicy) error { - return network.DispatchCreate[*ServiceEdgeRouterPolicy](self, entity) +func (self *ServiceEdgeRouterPolicyManager) Create(entity *ServiceEdgeRouterPolicy, ctx *change.Context) error { + return network.DispatchCreate[*ServiceEdgeRouterPolicy](self, entity, ctx) } -func (self *ServiceEdgeRouterPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*ServiceEdgeRouterPolicy]) error { - _, err := self.createEntity(cmd.Entity) +func (self *ServiceEdgeRouterPolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*ServiceEdgeRouterPolicy], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *ServiceEdgeRouterPolicyManager) Update(entity *ServiceEdgeRouterPolicy, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*ServiceEdgeRouterPolicy](self, entity, checker) +func (self *ServiceEdgeRouterPolicyManager) Update(entity *ServiceEdgeRouterPolicy, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*ServiceEdgeRouterPolicy](self, entity, checker, ctx) } -func (self *ServiceEdgeRouterPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ServiceEdgeRouterPolicy]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) -} - -func (self *ServiceEdgeRouterPolicyManager) Read(id string) (*ServiceEdgeRouterPolicy, error) { - modelEntity := &ServiceEdgeRouterPolicy{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - -func (self *ServiceEdgeRouterPolicyManager) readInTx(tx *bbolt.Tx, id string) (*ServiceEdgeRouterPolicy, error) { - modelEntity := &ServiceEdgeRouterPolicy{} - if err := self.readEntityInTx(tx, id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil +func (self *ServiceEdgeRouterPolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ServiceEdgeRouterPolicy], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *ServiceEdgeRouterPolicyManager) Marshall(entity *ServiceEdgeRouterPolicy) ([]byte, error) { diff --git a/controller/model/service_edge_router_policy_model.go b/controller/model/service_edge_router_policy_model.go index c2b88fb15..56cc3b2d6 100644 --- a/controller/model/service_edge_router_policy_model.go +++ b/controller/model/service_edge_router_policy_model.go @@ -20,9 +20,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type ServiceEdgeRouterPolicy struct { @@ -33,7 +31,7 @@ type ServiceEdgeRouterPolicy struct { EdgeRouterRoles []string } -func (entity *ServiceEdgeRouterPolicy) toBoltEntity() (boltz.Entity, error) { +func (entity *ServiceEdgeRouterPolicy) toBoltEntity() (*persistence.ServiceEdgeRouterPolicy, error) { return &persistence.ServiceEdgeRouterPolicy{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Name: entity.Name, @@ -43,19 +41,15 @@ func (entity *ServiceEdgeRouterPolicy) toBoltEntity() (boltz.Entity, error) { }, nil } -func (entity *ServiceEdgeRouterPolicy) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *ServiceEdgeRouterPolicy) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.ServiceEdgeRouterPolicy, error) { return entity.toBoltEntity() } -func (entity *ServiceEdgeRouterPolicy) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ServiceEdgeRouterPolicy) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.ServiceEdgeRouterPolicy, error) { return entity.toBoltEntity() } -func (entity *ServiceEdgeRouterPolicy) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltServiceEdgeRouterPolicy, ok := boltEntity.(*persistence.ServiceEdgeRouterPolicy) - if !ok { - return errors.Errorf("unexpected type %v when filling model edge router policy", reflect.TypeOf(boltEntity)) - } +func (entity *ServiceEdgeRouterPolicy) fillFrom(_ Env, _ *bbolt.Tx, boltServiceEdgeRouterPolicy *persistence.ServiceEdgeRouterPolicy) error { entity.FillCommon(boltServiceEdgeRouterPolicy) entity.Name = boltServiceEdgeRouterPolicy.Name entity.Semantic = boltServiceEdgeRouterPolicy.Semantic diff --git a/controller/model/service_policy_manager.go b/controller/model/service_policy_manager.go index 88bb0a6d8..11af0a0de 100644 --- a/controller/model/service_policy_manager.go +++ b/controller/model/service_policy_manager.go @@ -17,18 +17,20 @@ package model import ( + "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/fields" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" - "go.etcd.io/bbolt" + "github.com/openziti/storage/boltz" "google.golang.org/protobuf/proto" ) func NewServicePolicyManager(env Env) *ServicePolicyManager { manager := &ServicePolicyManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().ServicePolicy), + baseEntityManager: newBaseEntityManager[*ServicePolicy, *persistence.ServicePolicy](env, env.GetStores().ServicePolicy), } manager.impl = manager @@ -38,44 +40,28 @@ func NewServicePolicyManager(env Env) *ServicePolicyManager { } type ServicePolicyManager struct { - baseEntityManager + baseEntityManager[*ServicePolicy, *persistence.ServicePolicy] } -func (self *ServicePolicyManager) newModelEntity() edgeEntity { +func (self *ServicePolicyManager) newModelEntity() *ServicePolicy { return &ServicePolicy{} } -func (self *ServicePolicyManager) Create(entity *ServicePolicy) error { - return network.DispatchCreate[*ServicePolicy](self, entity) +func (self *ServicePolicyManager) Create(entity *ServicePolicy, ctx *change.Context) error { + return network.DispatchCreate[*ServicePolicy](self, entity, ctx) } -func (self *ServicePolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*ServicePolicy]) error { - _, err := self.createEntity(cmd.Entity) +func (self *ServicePolicyManager) ApplyCreate(cmd *command.CreateEntityCommand[*ServicePolicy], ctx boltz.MutateContext) error { + _, err := self.createEntity(cmd.Entity, ctx) return err } -func (self *ServicePolicyManager) Update(entity *ServicePolicy, checker fields.UpdatedFields) error { - return network.DispatchUpdate[*ServicePolicy](self, entity, checker) +func (self *ServicePolicyManager) Update(entity *ServicePolicy, checker fields.UpdatedFields, ctx *change.Context) error { + return network.DispatchUpdate[*ServicePolicy](self, entity, checker, ctx) } -func (self *ServicePolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ServicePolicy]) error { - return self.updateEntity(cmd.Entity, cmd.UpdatedFields) -} - -func (self *ServicePolicyManager) Read(id string) (*ServicePolicy, error) { - modelEntity := &ServicePolicy{} - if err := self.readEntity(id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - -func (self *ServicePolicyManager) readInTx(tx *bbolt.Tx, id string) (*ServicePolicy, error) { - modelEntity := &ServicePolicy{} - if err := self.readEntityInTx(tx, id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil +func (self *ServicePolicyManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*ServicePolicy], ctx boltz.MutateContext) error { + return self.updateEntity(cmd.Entity, cmd.UpdatedFields, ctx) } func (self *ServicePolicyManager) Marshall(entity *ServicePolicy) ([]byte, error) { diff --git a/controller/model/service_policy_model.go b/controller/model/service_policy_model.go index 21916a77e..326d92e02 100644 --- a/controller/model/service_policy_model.go +++ b/controller/model/service_policy_model.go @@ -22,9 +22,7 @@ import ( "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" "strings" ) @@ -46,7 +44,7 @@ func (entity *ServicePolicy) validatePolicyType() error { return nil } -func (entity *ServicePolicy) toBoltEntity(checker boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ServicePolicy) toBoltEntity(checker boltz.FieldChecker) (*persistence.ServicePolicy, error) { if checker == nil || checker.IsUpdated(persistence.FieldServicePolicyType) { if err := entity.validatePolicyType(); err != nil { return nil, err @@ -71,20 +69,15 @@ func (entity *ServicePolicy) toBoltEntity(checker boltz.FieldChecker) (boltz.Ent }, nil } -func (entity *ServicePolicy) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (entity *ServicePolicy) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.ServicePolicy, error) { return entity.toBoltEntity(nil) } -func (entity *ServicePolicy) toBoltEntityForUpdate(_ *bbolt.Tx, _ EntityManager, checker boltz.FieldChecker) (boltz.Entity, error) { +func (entity *ServicePolicy) toBoltEntityForUpdate(_ *bbolt.Tx, _ Env, checker boltz.FieldChecker) (*persistence.ServicePolicy, error) { return entity.toBoltEntity(checker) } -func (entity *ServicePolicy) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltServicePolicy, ok := boltEntity.(*persistence.ServicePolicy) - if !ok { - return errors.Errorf("unexpected type %v when filling model service policy", reflect.TypeOf(boltEntity)) - } - +func (entity *ServicePolicy) fillFrom(_ Env, _ *bbolt.Tx, boltServicePolicy *persistence.ServicePolicy) error { policyType := "Invalid" if boltServicePolicy.PolicyType == persistence.PolicyTypeDial { policyType = persistence.PolicyTypeDialName diff --git a/controller/model/session_manager.go b/controller/model/session_manager.go index 24ab1f6e2..751d70954 100644 --- a/controller/model/session_manager.go +++ b/controller/model/session_manager.go @@ -22,6 +22,7 @@ import ( "github.com/openziti/edge/controller/apierror" "github.com/openziti/edge/controller/persistence" fabricApiError "github.com/openziti/fabric/controller/apierror" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" @@ -33,17 +34,17 @@ import ( func NewSessionManager(env Env) *SessionManager { manager := &SessionManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().Session), + baseEntityManager: newBaseEntityManager[*Session, *persistence.Session](env, env.GetStores().Session), } manager.impl = manager return manager } type SessionManager struct { - baseEntityManager + baseEntityManager[*Session, *persistence.Session] } -func (self *SessionManager) newModelEntity() edgeEntity { +func (self *SessionManager) newModelEntity() *Session { return &Session{} } @@ -150,7 +151,7 @@ func (self *SessionManager) EvaluatePostureForService(identityId, apiSessionId, } } -func (self *SessionManager) Create(entity *Session) (string, error) { +func (self *SessionManager) Create(entity *Session, ctx *change.Context) (string, error) { if self.getExistingSessionEntity(entity) { return entity.Id, nil } @@ -199,19 +200,19 @@ func (self *SessionManager) Create(entity *Session) (string, error) { entity.ServicePolicies = policyResult.PassingPolicyIds - return self.createSessionEntity(entity) + return self.createSessionEntity(entity, ctx) } -func (self *SessionManager) createSessionEntity(session *Session) (string, error) { +func (self *SessionManager) createSessionEntity(session *Session, ctx *change.Context) (string, error) { var id string - err := self.GetDb().Update(func(tx *bbolt.Tx) error { - if self.getExistingSessionEntityInTx(tx, session) { + err := self.GetDb().Update(ctx.NewMutateContext(), func(ctx boltz.MutateContext) error { + if self.getExistingSessionEntityInTx(ctx.Tx(), session) { id = session.Id return nil } var err error - id, err = self.createEntityInTx(boltz.NewMutateContext(tx), session) + id, err = self.createEntityInTx(ctx, session) return err }) if err != nil { @@ -280,15 +281,7 @@ func (self *SessionManager) Read(id string) (*Session, error) { return entity, nil } -func (self *SessionManager) readInTx(tx *bbolt.Tx, id string) (*Session, error) { - entity := &Session{} - if err := self.readEntityInTx(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (self *SessionManager) DeleteForIdentity(id, identityId string) error { +func (self *SessionManager) DeleteForIdentity(id, identityId string, ctx *change.Context) error { session, err := self.ReadForIdentity(id, identityId) if err != nil { return err @@ -296,11 +289,11 @@ func (self *SessionManager) DeleteForIdentity(id, identityId string) error { if session == nil { return boltz.NewNotFoundError(self.GetStore().GetSingularEntityType(), "id", id) } - return self.deleteEntity(id) + return self.deleteEntity(id, ctx) } -func (self *SessionManager) Delete(id string) error { - return self.deleteEntity(id) +func (self *SessionManager) Delete(id string, ctx *change.Context) error { + return self.deleteEntity(id, ctx) } func (self *SessionManager) PublicQueryForIdentity(sessionIdentity *Identity, query ast.Query) (*SessionListResult, error) { diff --git a/controller/model/session_manager_test.go b/controller/model/session_manager_test.go index a0459e40d..3088b87ca 100644 --- a/controller/model/session_manager_test.go +++ b/controller/model/session_manager_test.go @@ -3,6 +3,8 @@ package model import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" + "github.com/openziti/storage/boltztest" "github.com/stretchr/testify/require" "testing" "time" @@ -22,7 +24,7 @@ func (ctx *TestContext) testSessionIdempotency(t *testing.T) { service := ctx.requireNewService() service2 := ctx.requireNewService() service.RoleAttributes = []string{eid.New()} - ctx.NoError(ctx.managers.EdgeService.Update(service, nil)) + ctx.NoError(ctx.managers.EdgeService.Update(service, nil, change.New().SetSource("test"))) ctx.requireNewServicePolicy(persistence.PolicyTypeDialName, ss("#all"), ss("#all")) ctx.requireNewServicePolicy(persistence.PolicyTypeBindName, ss("#all"), ss("#all")) @@ -67,7 +69,7 @@ func (ctx *TestContext) testSessionIdempotency(t *testing.T) { req.Equal(sessSvc1Dial.Id, sessSvc1Dial3.Id) req.Equal(sessSvc1Bind.Id, sessSvc1Bind3.Id) - req.NoError(ctx.managers.ApiSession.Delete(apiSession.Id)) + req.NoError(ctx.managers.ApiSession.Delete(apiSession.Id, change.New().SetSource("test"))) done, err := ctx.GetStores().EventualEventer.Trigger() ctx.NoError(err) @@ -77,9 +79,9 @@ func (ctx *TestContext) testSessionIdempotency(t *testing.T) { ctx.Fail("did not receive done notification from eventual eventer") } - ctx.ValidateDeleted(apiSession.Id) - ctx.ValidateDeleted(sessSvc1Dial.Id) - ctx.ValidateDeleted(sessSvc1Dial2.Id) - ctx.ValidateDeleted(sessSvc1Bind.Id) - ctx.ValidateDeleted(sessSvc1Bind2.Id) + boltztest.ValidateDeleted(ctx, apiSession.Id) + boltztest.ValidateDeleted(ctx, sessSvc1Dial.Id) + boltztest.ValidateDeleted(ctx, sessSvc1Dial2.Id) + boltztest.ValidateDeleted(ctx, sessSvc1Bind.Id) + boltztest.ValidateDeleted(ctx, sessSvc1Bind2.Id) } diff --git a/controller/model/session_model.go b/controller/model/session_model.go index 2fbb21e72..b442becd5 100644 --- a/controller/model/session_model.go +++ b/controller/model/session_model.go @@ -21,9 +21,7 @@ import ( "github.com/openziti/fabric/controller/models" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" - "reflect" ) type Session struct { @@ -36,8 +34,8 @@ type Session struct { ServicePolicies []string } -func (entity *Session) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager) (boltz.Entity, error) { - apiSession, err := manager.GetEnv().GetStores().ApiSession.LoadOneById(tx, entity.ApiSessionId) +func (entity *Session) toBoltEntityForCreate(tx *bbolt.Tx, env Env) (*persistence.Session, error) { + apiSession, err := env.GetStores().ApiSession.LoadOneById(tx, entity.ApiSessionId) if err != nil { return nil, err } @@ -59,7 +57,7 @@ func (entity *Session) toBoltEntityForCreate(tx *bbolt.Tx, manager EntityManager return boltEntity, nil } -func (entity *Session) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *Session) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.Session, error) { return &persistence.Session{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), Token: entity.Token, @@ -71,11 +69,7 @@ func (entity *Session) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.Fie }, nil } -func (entity *Session) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltSession, ok := boltEntity.(*persistence.Session) - if !ok { - return errors.Errorf("unexpected type %v when filling model Session", reflect.TypeOf(boltEntity)) - } +func (entity *Session) fillFrom(_ Env, _ *bbolt.Tx, boltSession *persistence.Session) error { entity.FillCommon(boltSession) entity.Token = boltSession.Token entity.ApiSessionId = boltSession.ApiSessionId diff --git a/controller/model/testing.go b/controller/model/testing.go index f5115e3f2..0f5b6bc1c 100644 --- a/controller/model/testing.go +++ b/controller/model/testing.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/edge/eid" "github.com/openziti/edge/internal/cert" "github.com/openziti/edge/internal/jwtsigner" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/network" "github.com/openziti/identity" "github.com/openziti/metrics" @@ -143,11 +144,7 @@ func NewTestContext(t *testing.T) *TestContext { return context } func (ctx *TestContext) Init() { - ctx.InitWithDbFile("") -} - -func (ctx *TestContext) InitWithDbFile(dbPath string) { - ctx.TestContext.InitWithDbFile(dbPath) + ctx.TestContext.Init() ctx.config = &config.Config{ Enrollment: config.Enrollment{ EdgeRouter: config.EnrollmentOption{ @@ -173,7 +170,7 @@ func (ctx *TestContext) requireNewIdentity(isAdmin bool) *Identity { IsAdmin: isAdmin, IdentityTypeId: identityType.Id, } - ctx.NoError(ctx.managers.Identity.Create(identity)) + ctx.NoError(ctx.managers.Identity.Create(identity, change.New().SetSource("test"))) return identity } @@ -181,7 +178,7 @@ func (ctx *TestContext) requireNewService() *Service { service := &Service{ Name: eid.New(), } - ctx.NoError(ctx.managers.EdgeService.Create(service)) + ctx.NoError(ctx.managers.EdgeService.Create(service, change.New().SetSource("test"))) return service } @@ -189,7 +186,7 @@ func (ctx *TestContext) requireNewEdgeRouter() *EdgeRouter { edgeRouter := &EdgeRouter{ Name: eid.New(), } - ctx.NoError(ctx.managers.EdgeRouter.Create(edgeRouter)) + ctx.NoError(ctx.managers.EdgeRouter.Create(edgeRouter, change.New().SetSource("test"))) return edgeRouter } @@ -213,7 +210,7 @@ func (ctx *TestContext) requireNewSession(apiSession *ApiSession, serviceId stri ServiceId: serviceId, Type: sessionType, } - _, err := ctx.managers.Session.Create(entity) + _, err := ctx.managers.Session.Create(entity, change.New().SetSource("test")) ctx.NoError(err) return entity } @@ -226,7 +223,7 @@ func (ctx *TestContext) requireNewServicePolicy(policyType string, identityRoles ServiceRoles: serviceRoles, PolicyType: policyType, } - ctx.NoError(ctx.managers.ServicePolicy.Create(policy)) + ctx.NoError(ctx.managers.ServicePolicy.Create(policy, change.New().SetSource("test"))) return policy } @@ -237,7 +234,7 @@ func (ctx *TestContext) requireNewEdgeRouterPolicy(identityRoles, edgeRouterRole IdentityRoles: identityRoles, EdgeRouterRoles: edgeRouterRoles, } - ctx.NoError(ctx.managers.EdgeRouterPolicy.Create(policy)) + ctx.NoError(ctx.managers.EdgeRouterPolicy.Create(policy, change.New().SetSource("test"))) return policy } @@ -248,7 +245,7 @@ func (ctx *TestContext) requireNewServiceNewEdgeRouterPolicy(serviceRoles, edgeR ServiceRoles: serviceRoles, EdgeRouterRoles: edgeRouterRoles, } - ctx.NoError(ctx.managers.ServiceEdgeRouterPolicy.Create(policy)) + ctx.NoError(ctx.managers.ServiceEdgeRouterPolicy.Create(policy, change.New().SetSource("test"))) return policy } diff --git a/controller/model/transit_router_manager.go b/controller/model/transit_router_manager.go index 550990fe7..cc3187d29 100644 --- a/controller/model/transit_router_manager.go +++ b/controller/model/transit_router_manager.go @@ -23,6 +23,7 @@ import ( "github.com/openziti/edge/controller/persistence" "github.com/openziti/edge/eid" "github.com/openziti/edge/pb/edge_cmd_pb" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/db" "github.com/openziti/fabric/controller/fields" @@ -37,7 +38,7 @@ import ( func NewTransitRouterManager(env Env) *TransitRouterManager { manager := &TransitRouterManager{ - baseEntityManager: newBaseEntityManager(env, env.GetStores().TransitRouter), + baseEntityManager: newBaseEntityManager[*TransitRouter, *persistence.TransitRouter](env, env.GetStores().TransitRouter), allowedFields: boltz.MapFieldChecker{ persistence.FieldName: struct{}{}, boltz.FieldTags: struct{}{}, @@ -53,7 +54,7 @@ func NewTransitRouterManager(env Env) *TransitRouterManager { } type TransitRouterManager struct { - baseEntityManager + baseEntityManager[*TransitRouter, *persistence.TransitRouter] allowedFields boltz.FieldChecker } @@ -61,11 +62,11 @@ func (self *TransitRouterManager) GetEntityTypeId() string { return "transitRouters" } -func (self *TransitRouterManager) newModelEntity() edgeEntity { +func (self *TransitRouterManager) newModelEntity() *TransitRouter { return &TransitRouter{} } -func (self *TransitRouterManager) Create(txRouter *TransitRouter) error { +func (self *TransitRouterManager) Create(txRouter *TransitRouter, ctx *change.Context) error { if txRouter.Id == "" { txRouter.Id = eid.New() } @@ -80,18 +81,18 @@ func (self *TransitRouterManager) Create(txRouter *TransitRouter) error { manager: self, router: txRouter, enrollment: enrollment, + ctx: ctx, } return self.Dispatch(cmd) } -func (self *TransitRouterManager) ApplyCreate(cmd *CreateTransitRouterCmd) error { +func (self *TransitRouterManager) ApplyCreate(cmd *CreateTransitRouterCmd, ctx boltz.MutateContext) error { txRouter := cmd.router enrollment := cmd.enrollment - return self.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) - boltEntity, err := txRouter.toBoltEntityForCreate(tx, self.impl) + return self.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + boltEntity, err := txRouter.toBoltEntityForCreate(ctx.Tx(), self.env) if err != nil { return err } @@ -109,7 +110,7 @@ func (self *TransitRouterManager) ApplyCreate(cmd *CreateTransitRouterCmd) error }) } -func (self *TransitRouterManager) Update(entity *TransitRouter, unrestricted bool, checker fields.UpdatedFields) error { +func (self *TransitRouterManager) Update(entity *TransitRouter, unrestricted bool, checker fields.UpdatedFields, ctx *change.Context) error { curEntity, err := self.Read(entity.Id) if err != nil { @@ -124,6 +125,7 @@ func (self *TransitRouterManager) Update(entity *TransitRouter, unrestricted boo Updater: self, Entity: entity, UpdatedFields: checker, + Context: ctx, } if unrestricted { cmd.Flags = updateUnrestricted @@ -131,7 +133,7 @@ func (self *TransitRouterManager) Update(entity *TransitRouter, unrestricted boo return self.Dispatch(cmd) } -func (self *TransitRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*TransitRouter]) error { +func (self *TransitRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[*TransitRouter], ctx boltz.MutateContext) error { var checker boltz.FieldChecker = cmd.UpdatedFields if cmd.Flags != updateUnrestricted { if checker == nil { @@ -140,7 +142,7 @@ func (self *TransitRouterManager) ApplyUpdate(cmd *command.UpdateEntityCommand[* checker = &AndFieldChecker{first: self.allowedFields, second: cmd.UpdatedFields} } } - return self.updateEntity(cmd.Entity, checker) + return self.updateEntity(cmd.Entity, checker, ctx) } func (self *TransitRouterManager) ReadOneByFingerprint(fingerprint string) (*TransitRouter, error) { @@ -158,24 +160,6 @@ func (self *TransitRouterManager) ReadOneByQuery(query string) (*TransitRouter, return result.(*TransitRouter), nil } -func (self *TransitRouterManager) Read(id string) (*TransitRouter, error) { - result := &TransitRouter{} - - if err := self.readEntity(id, result); err != nil { - return nil, err - } - - return result, nil -} - -func (self *TransitRouterManager) readInTx(tx *bbolt.Tx, id string) (*TransitRouter, error) { - modelEntity := &TransitRouter{} - if err := self.readEntityInTx(tx, id, modelEntity); err != nil { - return nil, err - } - return modelEntity, nil -} - func (self *TransitRouterManager) CollectEnrollments(id string, collector func(entity *Enrollment) error) error { return self.GetDb().View(func(tx *bbolt.Tx) error { return self.collectEnrollmentsInTx(tx, id, collector) @@ -203,7 +187,7 @@ func (self *TransitRouterManager) collectEnrollmentsInTx(tx *bbolt.Tx, id string return nil } -func (self *TransitRouterManager) ExtendEnrollment(router *TransitRouter, clientCsrPem []byte, serverCertCsrPem []byte) (*ExtendedCerts, error) { +func (self *TransitRouterManager) ExtendEnrollment(router *TransitRouter, clientCsrPem []byte, serverCertCsrPem []byte, ctx *change.Context) (*ExtendedCerts, error) { enrollmentModule := self.env.GetEnrollRegistry().GetByMethod("erott").(*EnrollModuleEr) clientCertRaw, err := enrollmentModule.ProcessClientCsrPem(clientCsrPem, router.Id) @@ -233,7 +217,7 @@ func (self *TransitRouterManager) ExtendEnrollment(router *TransitRouter, client err = self.Update(router, true, &fields.UpdatedFieldsMap{ persistence.FieldEdgeRouterCertPEM: struct{}{}, db.FieldRouterFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return nil, err @@ -245,7 +229,7 @@ func (self *TransitRouterManager) ExtendEnrollment(router *TransitRouter, client }, nil } -func (self *TransitRouterManager) ExtendEnrollmentWithVerify(router *TransitRouter, clientCsrPem []byte, serverCertCsrPem []byte) (*ExtendedCerts, error) { +func (self *TransitRouterManager) ExtendEnrollmentWithVerify(router *TransitRouter, clientCsrPem []byte, serverCertCsrPem []byte, ctx *change.Context) (*ExtendedCerts, error) { enrollmentModule := self.env.GetEnrollRegistry().GetByMethod("erott").(*EnrollModuleEr) clientCertRaw, err := enrollmentModule.ProcessClientCsrPem(clientCsrPem, router.Id) @@ -275,7 +259,7 @@ func (self *TransitRouterManager) ExtendEnrollmentWithVerify(router *TransitRout err = self.Update(router, true, &fields.UpdatedFieldsMap{ persistence.FieldEdgeRouterUnverifiedCertPEM: struct{}{}, persistence.FieldEdgeRouterUnverifiedFingerprint: struct{}{}, - }) + }, ctx) if err != nil { return nil, err @@ -291,7 +275,7 @@ func (self *TransitRouterManager) ReadOneByUnverifiedFingerprint(fingerprint str return self.ReadOneByQuery(fmt.Sprintf(`%s = "%v"`, persistence.FieldEdgeRouterUnverifiedFingerprint, fingerprint)) } -func (self *TransitRouterManager) ExtendEnrollmentVerify(router *TransitRouter) error { +func (self *TransitRouterManager) ExtendEnrollmentVerify(router *TransitRouter, ctx *change.Context) error { if router.UnverifiedFingerprint != nil && router.UnverifiedCertPem != nil { router.Fingerprint = router.UnverifiedFingerprint @@ -302,7 +286,7 @@ func (self *TransitRouterManager) ExtendEnrollmentVerify(router *TransitRouter) db.FieldRouterFingerprint: struct{}{}, persistence.FieldEdgeRouterUnverifiedCertPEM: struct{}{}, persistence.FieldEdgeRouterUnverifiedFingerprint: struct{}{}, - }) + }, ctx) } return errors.New("no outstanding verification necessary") @@ -365,10 +349,11 @@ type CreateTransitRouterCmd struct { manager *TransitRouterManager router *TransitRouter enrollment *Enrollment + ctx *change.Context } -func (self *CreateTransitRouterCmd) Apply() error { - return self.manager.ApplyCreate(self) +func (self *CreateTransitRouterCmd) Apply(ctx boltz.MutateContext) error { + return self.manager.ApplyCreate(self, ctx) } func (self *CreateTransitRouterCmd) Encode() ([]byte, error) { @@ -385,6 +370,7 @@ func (self *CreateTransitRouterCmd) Encode() ([]byte, error) { cmd := &edge_cmd_pb.CreateTransitRouterCmd{ Router: transitRouterMsg, Enrollment: enrollment, + Ctx: ContextToProtobuf(self.ctx), } return cmd_pb.EncodeProtobuf(cmd) @@ -405,6 +391,11 @@ func (self *CreateTransitRouterCmd) Decode(env Env, msg *edge_cmd_pb.CreateTrans self.router = router self.enrollment = enrollment + self.ctx = ProtobufToContext(msg.Ctx) return nil } + +func (self *CreateTransitRouterCmd) GetChangeContext() *change.Context { + return self.ctx +} diff --git a/controller/model/transit_router_model.go b/controller/model/transit_router_model.go index 79558d589..451f17fd9 100644 --- a/controller/model/transit_router_model.go +++ b/controller/model/transit_router_model.go @@ -17,13 +17,10 @@ package model import ( - "reflect" - "github.com/openziti/edge/controller/persistence" "github.com/openziti/fabric/controller/db" "github.com/openziti/fabric/controller/models" "github.com/openziti/storage/boltz" - "github.com/pkg/errors" "go.etcd.io/bbolt" ) @@ -40,7 +37,11 @@ type TransitRouter struct { Disabled bool } -func (entity *TransitRouter) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (boltz.Entity, error) { +func (self *TransitRouter) GetName() string { + return self.Name +} + +func (entity *TransitRouter) toBoltEntityForCreate(*bbolt.Tx, Env) (*persistence.TransitRouter, error) { boltEntity := &persistence.TransitRouter{ Router: db.Router{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), @@ -56,7 +57,7 @@ func (entity *TransitRouter) toBoltEntityForCreate(*bbolt.Tx, EntityManager) (bo return boltEntity, nil } -func (entity *TransitRouter) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, boltz.FieldChecker) (boltz.Entity, error) { +func (entity *TransitRouter) toBoltEntityForUpdate(*bbolt.Tx, Env, boltz.FieldChecker) (*persistence.TransitRouter, error) { ret := &persistence.TransitRouter{ Router: db.Router{ BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags), @@ -74,11 +75,7 @@ func (entity *TransitRouter) toBoltEntityForUpdate(*bbolt.Tx, EntityManager, bol return ret, nil } -func (entity *TransitRouter) fillFrom(_ EntityManager, _ *bbolt.Tx, boltEntity boltz.Entity) error { - boltTransitRouter, ok := boltEntity.(*persistence.TransitRouter) - if !ok { - return errors.Errorf("unexpected type %v when filling model transitRouter", reflect.TypeOf(boltEntity)) - } +func (entity *TransitRouter) fillFrom(_ Env, _ *bbolt.Tx, boltTransitRouter *persistence.TransitRouter) error { entity.FillCommon(boltTransitRouter) entity.Name = boltTransitRouter.Name entity.IsVerified = boltTransitRouter.IsVerified diff --git a/controller/persistence/api_session_certificate_store.go b/controller/persistence/api_session_certificate_store.go index 22e99791b..61306748a 100644 --- a/controller/persistence/api_session_certificate_store.go +++ b/controller/persistence/api_session_certificate_store.go @@ -17,10 +17,8 @@ package persistence import ( - "github.com/openziti/edge/eid" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" "time" ) @@ -43,61 +41,28 @@ type ApiSessionCertificate struct { PEM string } -func NewApiSessionCertificate(apiSessionId string) *ApiSessionCertificate { - return &ApiSessionCertificate{ - BaseExtEntity: boltz.BaseExtEntity{Id: eid.New()}, - ApiSessionId: apiSessionId, - Subject: eid.New(), - } -} - -func (entity *ApiSessionCertificate) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.ApiSessionId = bucket.GetStringOrError(FieldApiSessionCertificateApiSession) - entity.Subject = bucket.GetStringOrError(FieldApiSessionCertificateSubject) - entity.Fingerprint = bucket.GetStringOrError(FieldApiSessionCertificateFingerprint) - entity.ValidAfter = bucket.GetTime(FieldApiSessionCertificateValidAfter) - entity.ValidBefore = bucket.GetTime(FieldApiSessionCertificateValidBefore) - entity.PEM = bucket.GetStringOrError(FieldApiSessionCertificatePem) -} - -func (entity *ApiSessionCertificate) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldApiSessionCertificateApiSession, entity.ApiSessionId) - ctx.SetString(FieldApiSessionCertificateSubject, entity.Subject) - ctx.SetString(FieldApiSessionCertificateFingerprint, entity.Fingerprint) - ctx.SetTimeP(FieldApiSessionCertificateValidAfter, entity.ValidAfter) - ctx.SetTimeP(FieldApiSessionCertificateValidBefore, entity.ValidBefore) - ctx.SetString(FieldApiSessionCertificatePem, entity.PEM) -} - func (entity *ApiSessionCertificate) GetEntityType() string { return EntityTypeApiSessionCertificates } +var _ ApiSessionCertificateStore = (*ApiSessionCertificateStoreImpl)(nil) + type ApiSessionCertificateStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*ApiSessionCertificate, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*ApiSessionCertificate, error) + Store[*ApiSessionCertificate] } func newApiSessionCertificateStore(stores *stores) *ApiSessionCertificateStoreImpl { - store := &ApiSessionCertificateStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeApiSessionCertificates), - } + store := &ApiSessionCertificateStoreImpl{} + store.baseStore = newBaseStore[*ApiSessionCertificate](stores, store) store.InitImpl(store) return store } type ApiSessionCertificateStoreImpl struct { - *baseStore + *baseStore[*ApiSessionCertificate] symbolApiSession boltz.EntitySymbol } -func (store *ApiSessionCertificateStoreImpl) NewStoreEntity() boltz.Entity { - return &ApiSessionCertificate{} -} - func (store *ApiSessionCertificateStoreImpl) initializeLocal() { store.AddExtEntitySymbols() store.AddSymbol(FieldApiSessionCertificateApiSession, ast.NodeTypeString) @@ -111,18 +76,26 @@ func (store *ApiSessionCertificateStoreImpl) initializeLocal() { func (store *ApiSessionCertificateStoreImpl) initializeLinked() { } -func (store *ApiSessionCertificateStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ApiSessionCertificate, error) { - entity := &ApiSessionCertificate{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *ApiSessionCertificateStoreImpl) NewEntity() *ApiSessionCertificate { + return &ApiSessionCertificate{} } -func (store *ApiSessionCertificateStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*ApiSessionCertificate, error) { - entity := &ApiSessionCertificate{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil +func (store *ApiSessionCertificateStoreImpl) FillEntity(entity *ApiSessionCertificate, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.ApiSessionId = bucket.GetStringOrError(FieldApiSessionCertificateApiSession) + entity.Subject = bucket.GetStringOrError(FieldApiSessionCertificateSubject) + entity.Fingerprint = bucket.GetStringOrError(FieldApiSessionCertificateFingerprint) + entity.ValidAfter = bucket.GetTime(FieldApiSessionCertificateValidAfter) + entity.ValidBefore = bucket.GetTime(FieldApiSessionCertificateValidBefore) + entity.PEM = bucket.GetStringOrError(FieldApiSessionCertificatePem) +} + +func (store *ApiSessionCertificateStoreImpl) PersistEntity(entity *ApiSessionCertificate, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldApiSessionCertificateApiSession, entity.ApiSessionId) + ctx.SetString(FieldApiSessionCertificateSubject, entity.Subject) + ctx.SetString(FieldApiSessionCertificateFingerprint, entity.Fingerprint) + ctx.SetTimeP(FieldApiSessionCertificateValidAfter, entity.ValidAfter) + ctx.SetTimeP(FieldApiSessionCertificateValidBefore, entity.ValidBefore) + ctx.SetString(FieldApiSessionCertificatePem, entity.PEM) } diff --git a/controller/persistence/api_session_store.go b/controller/persistence/api_session_store.go index e4d274546..850e4100c 100644 --- a/controller/persistence/api_session_store.go +++ b/controller/persistence/api_session_store.go @@ -20,6 +20,7 @@ import ( "github.com/kataras/go-events" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/db" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" @@ -63,7 +64,43 @@ func NewApiSession(identityId string) *ApiSession { } } -func (entity *ApiSession) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *ApiSession) GetEntityType() string { + return EntityTypeApiSessions +} + +var _ ApiSessionStore = (*apiSessionStoreImpl)(nil) + +type ApiSessionStore interface { + Store[*ApiSession] + LoadOneByToken(tx *bbolt.Tx, token string) (*ApiSession, error) + GetTokenIndex() boltz.ReadIndex + GetCachedSessionId(tx *bbolt.Tx, apiSessionId, sessionType, serviceId string) *string + GetEventsEmitter() events.EventEmmiter +} + +func newApiSessionStore(stores *stores) *apiSessionStoreImpl { + store := &apiSessionStoreImpl{ + eventsEmitter: events.New(), + } + store.baseStore = newBaseStore[*ApiSession](stores, store) + stores.EventualEventer.AddEventualListener(EventualEventApiSessionDelete, store.onEventualDelete) + store.InitImpl(store) + return store +} + +type apiSessionStoreImpl struct { + *baseStore[*ApiSession] + + indexToken boltz.ReadIndex + symbolIdentity boltz.EntitySymbol + eventsEmitter events.EventEmmiter +} + +func (store *apiSessionStoreImpl) NewEntity() *ApiSession { + return &ApiSession{} +} + +func (store *apiSessionStoreImpl) FillEntity(entity *ApiSession, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.IdentityId = bucket.GetStringOrError(FieldApiSessionIdentity) entity.Token = bucket.GetStringOrError(FieldApiSessionToken) @@ -79,7 +116,7 @@ func (entity *ApiSession) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucke } } -func (entity *ApiSession) SetValues(ctx *boltz.PersistContext) { +func (store *apiSessionStoreImpl) PersistEntity(entity *ApiSession, ctx *boltz.PersistContext) { entity.SetBaseValues(ctx) ctx.SetString(FieldApiSessionIdentity, entity.IdentityId) ctx.SetString(FieldApiSessionToken, entity.Token) @@ -91,34 +128,8 @@ func (entity *ApiSession) SetValues(ctx *boltz.PersistContext) { ctx.SetTimeP(FieldApiSessionLastActivityAt, &entity.LastActivityAt) } -func (entity *ApiSession) GetEntityType() string { - return EntityTypeApiSessions -} - -type ApiSessionStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*ApiSession, error) - LoadOneByToken(tx *bbolt.Tx, token string) (*ApiSession, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*ApiSession, error) - GetTokenIndex() boltz.ReadIndex - GetCachedSessionId(tx *bbolt.Tx, apiSessionId, sessionType, serviceId string) *string -} - -func newApiSessionStore(stores *stores) *apiSessionStoreImpl { - store := &apiSessionStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeApiSessions), - } - - stores.EventualEventer.AddEventualListener(EventualEventApiSessionDelete, store.onEventualDelete) - store.InitImpl(store) - return store -} - -type apiSessionStoreImpl struct { - *baseStore - - indexToken boltz.ReadIndex - symbolIdentity boltz.EntitySymbol +func (store *apiSessionStoreImpl) GetEventsEmitter() events.EventEmmiter { + return store.eventsEmitter } func (store *apiSessionStoreImpl) onEventualDelete(name string, apiSessionId []byte) { @@ -140,8 +151,8 @@ func (store *apiSessionStoreImpl) onEventualDelete(name string, apiSessionId []b } for _, id := range idCollector.ids { - err = store.stores.DbProvider.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) + changeContext := change.New().SetSource("events.emitter").SetChangeAuthorType("controller") + err = store.stores.DbProvider.GetDb().Update(changeContext.NewMutateContext(), func(ctx boltz.MutateContext) error { if err := store.stores.session.DeleteById(ctx, id); err != nil { if boltz.IsErrNotFoundErr(err) { return nil @@ -160,8 +171,9 @@ func (store *apiSessionStoreImpl) onEventualDelete(name string, apiSessionId []b } } - err = store.stores.DbProvider.GetDb().Update(func(tx *bbolt.Tx) error { - if bucket := boltz.Path(tx, indexPath...); bucket != nil { + changeContext := change.New().SetSource("events.emitter").SetChangeAuthorType("controller") + err = store.stores.DbProvider.GetDb().Update(changeContext.NewMutateContext(), func(ctx boltz.MutateContext) error { + if bucket := boltz.Path(ctx.Tx(), indexPath...); bucket != nil { if err := bucket.DeleteBucket(apiSessionId); err != nil { if err != bbolt.ErrBucketNotFound { return err @@ -179,27 +191,28 @@ func (store *apiSessionStoreImpl) onEventualDelete(name string, apiSessionId []b } } -func (store *apiSessionStoreImpl) Create(ctx boltz.MutateContext, entity boltz.Entity) error { +func (store *apiSessionStoreImpl) Create(ctx boltz.MutateContext, entity *ApiSession) error { err := store.baseStore.Create(ctx, entity) if err == nil { - if apiSession, ok := entity.(*ApiSession); ok && apiSession != nil { - if !apiSession.MfaRequired || apiSession.MfaComplete { - ctx.AddEvent(store, EventFullyAuthenticated, apiSession) - } + if !entity.MfaRequired || entity.MfaComplete { + ctx.AddCommitAction(func() { + store.eventsEmitter.Emit(EventFullyAuthenticated, entity) + }) } + } return err } -func (store *apiSessionStoreImpl) Update(ctx boltz.MutateContext, entity boltz.Entity, checker boltz.FieldChecker) error { +func (store *apiSessionStoreImpl) Update(ctx boltz.MutateContext, entity *ApiSession, checker boltz.FieldChecker) error { err := store.baseStore.Update(ctx, entity, checker) if err == nil { - if apiSession, ok := entity.(*ApiSession); ok && apiSession != nil { - if (checker == nil || checker.IsUpdated(FieldApiSessionMfaComplete)) && apiSession.MfaComplete { - ctx.AddEvent(store, EventFullyAuthenticated, apiSession) - } + if (checker == nil || checker.IsUpdated(FieldApiSessionMfaComplete)) && entity.MfaComplete { + ctx.AddCommitAction(func() { + store.eventsEmitter.Emit(EventFullyAuthenticated, entity) + }) } } @@ -220,10 +233,6 @@ func (store *apiSessionStoreImpl) DeleteById(ctx boltz.MutateContext, id string) return err } -func (store *apiSessionStoreImpl) NewStoreEntity() boltz.Entity { - return &ApiSession{} -} - func (store *apiSessionStoreImpl) GetTokenIndex() boltz.ReadIndex { return store.indexToken } @@ -245,14 +254,6 @@ func (store *apiSessionStoreImpl) initializeLocal() { func (store *apiSessionStoreImpl) initializeLinked() { } -func (store *apiSessionStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ApiSession, error) { - entity := &ApiSession{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - func (store *apiSessionStoreImpl) LoadOneByToken(tx *bbolt.Tx, token string) (*ApiSession, error) { id := store.indexToken.Read(tx, []byte(token)) if id != nil { @@ -261,14 +262,6 @@ func (store *apiSessionStoreImpl) LoadOneByToken(tx *bbolt.Tx, token string) (*A return nil, boltz.NewNotFoundError(store.GetSingularEntityType(), "token", token) } -func (store *apiSessionStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*ApiSession, error) { - entity := &ApiSession{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} - func (store *apiSessionStoreImpl) GetCachedSessionId(tx *bbolt.Tx, apiSessionId, sessionType, serviceId string) *string { bucket := boltz.Path(tx, db.RootBucket, boltz.IndexesBucket, diff --git a/controller/persistence/api_session_store_test.go b/controller/persistence/api_session_store_test.go index 50f8eced5..5d32c0bec 100644 --- a/controller/persistence/api_session_store_test.go +++ b/controller/persistence/api_session_store_test.go @@ -20,8 +20,10 @@ import ( "fmt" "github.com/google/go-cmp/cmp" "github.com/openziti/edge/eid" - "github.com/openziti/storage/boltz" + "github.com/openziti/fabric/controller/change" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "testing" "time" @@ -44,24 +46,24 @@ func (ctx *TestContext) testCreateInvalidApiSessions(t *testing.T) { defer ctx.CleanupAll() apiSession := NewApiSession(eid.New()) - err := ctx.Create(apiSession) + err := boltztest.Create(ctx, apiSession) ctx.EqualError(err, fmt.Sprintf("identity with id %v not found", apiSession.IdentityId)) apiSession.IdentityId = "" - err = ctx.Create(apiSession) + err = boltztest.Create(ctx, apiSession) ctx.EqualError(err, "fk constraint on apiSessions.identity does not allow null or empty values") identity := ctx.RequireNewIdentity("user1", false) apiSession.Token = "" apiSession.IdentityId = identity.Id - err = ctx.Create(apiSession) + err = boltztest.Create(ctx, apiSession) ctx.EqualError(err, "index on apiSessions.token does not allow null or empty values") apiSession.Token = eid.New() - err = ctx.Create(apiSession) + err = boltztest.Create(ctx, apiSession) ctx.NoError(err) - err = ctx.Create(apiSession) + err = boltztest.Create(ctx, apiSession) ctx.EqualError(err, fmt.Sprintf("an entity of type apiSession already exists with id %v", apiSession.GetId())) } @@ -72,19 +74,19 @@ func (ctx *TestContext) testCreateApiSessions(t *testing.T) { identity := ctx.RequireNewIdentity("Jojo", false) apiSession := NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) - ctx.ValidateBaseline(apiSession) + boltztest.ValidateBaseline(ctx, apiSession) apiSession2 := NewApiSession(identity.Id) apiSession2.Tags = ctx.CreateTags() - ctx.RequireCreate(apiSession2) + boltztest.RequireCreate(ctx, apiSession2) - ctx.ValidateBaseline(apiSession2) + boltztest.ValidateBaseline(ctx, apiSession2) - err := ctx.Delete(apiSession) + err := boltztest.Delete(ctx, apiSession) ctx.NoError(err) - ctx.RequireDelete(identity) + boltztest.RequireDelete(ctx, identity) done, err := ctx.GetStores().EventualEventer.Trigger() ctx.NoError(err) @@ -96,8 +98,8 @@ func (ctx *TestContext) testCreateApiSessions(t *testing.T) { } - ctx.ValidateDeleted(apiSession.Id) - ctx.ValidateDeleted(apiSession2.Id) + boltztest.ValidateDeleted(ctx, apiSession.Id) + boltztest.ValidateDeleted(ctx, apiSession2.Id) } type apiSessionTestEntities struct { @@ -115,13 +117,13 @@ func (ctx *TestContext) createApiSessionTestEntities() *apiSessionTestEntities { identity2 := ctx.RequireNewIdentity("user1", false) apiSession1 := NewApiSession(identity1.Id) - ctx.RequireCreate(apiSession1) + boltztest.RequireCreate(ctx, apiSession1) apiSession2 := NewApiSession(identity2.Id) - ctx.RequireCreate(apiSession2) + boltztest.RequireCreate(ctx, apiSession2) apiSession3 := NewApiSession(identity2.Id) - ctx.RequireCreate(apiSession3) + boltztest.RequireCreate(ctx, apiSession3) service := ctx.RequireNewService("test-service") session := &Session{ @@ -130,7 +132,7 @@ func (ctx *TestContext) createApiSessionTestEntities() *apiSessionTestEntities { ApiSessionId: apiSession2.Id, ServiceId: service.Id, } - ctx.RequireCreate(session) + boltztest.RequireCreate(ctx, session) return &apiSessionTestEntities{ identity1: identity1, @@ -155,13 +157,7 @@ func (ctx *TestContext) testLoadQueryApiSessions(t *testing.T) { ctx.NotNil(apiSession) ctx.EqualValues(entities.apiSession1.Id, apiSession.Id) - query := fmt.Sprintf(`identity = "%v"`, entities.identity1.Id) - apiSession, err = ctx.stores.ApiSession.LoadOneByQuery(tx, query) - ctx.NoError(err) - ctx.NotNil(apiSession) - ctx.EqualValues(entities.apiSession1.Id, apiSession.Id) - - query = fmt.Sprintf(`identity = "%v"`, entities.identity2.Id) + query := fmt.Sprintf(`identity = "%v"`, entities.identity2.Id) ids, _, err := ctx.stores.ApiSession.QueryIds(tx, query) ctx.NoError(err) ctx.EqualValues(2, len(ids)) @@ -179,7 +175,9 @@ func (ctx *TestContext) testUpdateApiSessions(t *testing.T) { entities := ctx.createApiSessionTestEntities() earlier := time.Now() - err := ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx := change.New().SetSource("test").NewMutateContext() + err := ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() original, err := ctx.stores.ApiSession.LoadOneById(tx, entities.apiSession1.Id) ctx.NoError(err) ctx.NotNil(original) @@ -196,7 +194,7 @@ func (ctx *TestContext) testUpdateApiSessions(t *testing.T) { apiSession.IdentityId = entities.identity2.Id apiSession.Tags = tags - err = ctx.stores.ApiSession.Update(boltz.NewMutateContext(tx), apiSession, nil) + err = ctx.stores.ApiSession.Update(mutateCtx, apiSession, nil) ctx.NoError(err) loaded, err := ctx.stores.ApiSession.LoadOneById(tx, entities.apiSession1.Id) ctx.NoError(err) @@ -216,13 +214,13 @@ func (ctx *TestContext) testDeleteApiSessions(t *testing.T) { ctx.CleanupAll() entities := ctx.createApiSessionTestEntities() - err := ctx.Delete(entities.apiSession1) + err := boltztest.Delete(ctx, entities.apiSession1) ctx.NoError(err) - err = ctx.Delete(entities.apiSession2) + err = boltztest.Delete(ctx, entities.apiSession2) ctx.NoError(err) - err = ctx.Delete(entities.apiSession3) + err = boltztest.Delete(ctx, entities.apiSession3) ctx.NoError(err) done, err := ctx.GetStores().EventualEventer.Trigger() @@ -235,7 +233,7 @@ func (ctx *TestContext) testDeleteApiSessions(t *testing.T) { } - ctx.ValidateDeleted(entities.apiSession1.GetId()) - ctx.ValidateDeleted(entities.apiSession2.GetId()) - ctx.ValidateDeleted(entities.apiSession3.GetId()) + boltztest.ValidateDeleted(ctx, entities.apiSession1.GetId()) + boltztest.ValidateDeleted(ctx, entities.apiSession2.GetId()) + boltztest.ValidateDeleted(ctx, entities.apiSession3.GetId()) } diff --git a/controller/persistence/auth_policy_store.go b/controller/persistence/auth_policy_store.go index 2acd07dfc..9a34d24b9 100644 --- a/controller/persistence/auth_policy_store.go +++ b/controller/persistence/auth_policy_store.go @@ -19,7 +19,6 @@ package persistence import ( "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -91,92 +90,31 @@ func (entity *AuthPolicy) GetName() string { return entity.Name } -func (entity *AuthPolicy) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - - entity.Name = bucket.GetStringOrError(FieldName) - entity.Primary.Updb.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbAllowed, true) - entity.Primary.Updb.MinPasswordLength = bucket.GetInt64WithDefault(FiledAuthPolicyPrimaryUpdbMinPasswordLength, DefaultUpdbMinPasswordLength) - entity.Primary.Updb.RequireSpecialChar = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireSpecialChar, false) - entity.Primary.Updb.RequireNumberChar = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireNumberChar, false) - entity.Primary.Updb.RequireMixedCase = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireMixedCase, false) - entity.Primary.Updb.MaxAttempts = bucket.GetInt64WithDefault(FieldAuthPolicyPrimaryUpdbMaxAttempts, DefaultUpdbMaxAttempts) - entity.Primary.Updb.LockoutDurationMinutes = bucket.GetInt64WithDefault(FieldAuthPolicyPrimaryUpdbLockoutDurationMinutes, 0) - - entity.Primary.Cert.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryCertAllowed, true) - entity.Primary.Cert.AllowExpiredCerts = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryCertAllowExpiredCerts, true) - - entity.Primary.ExtJwt.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryExtJwtAllowed, true) - entity.Primary.ExtJwt.AllowedExtJwtSigners = bucket.GetStringList(FieldAuthPolicyPrimaryExtJwtAllowedSigners) - - entity.Secondary.RequireTotp = bucket.GetBoolWithDefault(FieldAuthSecondaryPolicyRequireTotp, false) - entity.Secondary.RequiredExtJwtSigner = bucket.GetString(FieldAuthSecondaryPolicyRequiredExtJwtSigner) -} - -func (entity *AuthPolicy) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - - if entity.Primary.Updb.LockoutDurationMinutes < 0 { - entity.Primary.Updb.LockoutDurationMinutes = UpdbIndefiniteLockout - } - - if entity.Primary.Updb.MaxAttempts < 0 { - entity.Primary.Updb.MaxAttempts = UpdbUnlimitedAttemptsLimit - } - - if entity.Primary.Updb.MinPasswordLength < DefaultUpdbMinPasswordLength { - entity.Primary.Updb.MinPasswordLength = DefaultUpdbMinPasswordLength - } - - ctx.SetString(FieldName, entity.Name) - - ctx.SetBool(FieldAuthPolicyPrimaryCertAllowed, entity.Primary.Cert.Allowed) - ctx.SetBool(FieldAuthPolicyPrimaryCertAllowExpiredCerts, entity.Primary.Cert.AllowExpiredCerts) - - ctx.SetBool(FieldAuthPolicyPrimaryUpdbAllowed, entity.Primary.Updb.Allowed) - ctx.SetInt64(FiledAuthPolicyPrimaryUpdbMinPasswordLength, entity.Primary.Updb.MinPasswordLength) - ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireSpecialChar, entity.Primary.Updb.RequireSpecialChar) - ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireNumberChar, entity.Primary.Updb.RequireNumberChar) - ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireMixedCase, entity.Primary.Updb.RequireMixedCase) - ctx.SetInt64(FieldAuthPolicyPrimaryUpdbMaxAttempts, entity.Primary.Updb.MaxAttempts) - ctx.SetInt64(FieldAuthPolicyPrimaryUpdbLockoutDurationMinutes, entity.Primary.Updb.LockoutDurationMinutes) - - ctx.SetBool(FieldAuthPolicyPrimaryExtJwtAllowed, entity.Primary.ExtJwt.Allowed) - ctx.SetStringList(FieldAuthPolicyPrimaryExtJwtAllowedSigners, entity.Primary.ExtJwt.AllowedExtJwtSigners) - - ctx.SetBool(FieldAuthSecondaryPolicyRequireTotp, entity.Secondary.RequireTotp) - ctx.SetStringP(FieldAuthSecondaryPolicyRequiredExtJwtSigner, entity.Secondary.RequiredExtJwtSigner) -} - func (entity *AuthPolicy) GetEntityType() string { return EntityTypeAuthPolicies } +var _ AuthPolicyStore = (*AuthPolicyStoreImpl)(nil) + type AuthPolicyStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*AuthPolicy, error) - LoadOneByName(tx *bbolt.Tx, id string) (*AuthPolicy, error) + NameIndexed + Store[*AuthPolicy] } func newAuthPolicyStore(stores *stores) *AuthPolicyStoreImpl { - store := &AuthPolicyStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeAuthPolicies), - } + store := &AuthPolicyStoreImpl{} + store.baseStore = newBaseStore[*AuthPolicy](stores, store) store.InitImpl(store) return store } type AuthPolicyStoreImpl struct { - *baseStore + *baseStore[*AuthPolicy] indexName boltz.ReadIndex symbolPrimaryAllowedExtJwtSigners boltz.EntitySetSymbol symbolSecondaryRequiredExtJwtSignerId boltz.EntitySymbol } -func (store *AuthPolicyStoreImpl) NewStoreEntity() boltz.Entity { - return &AuthPolicy{} -} - func (store *AuthPolicyStoreImpl) initializeLocal() { store.AddExtEntitySymbols() store.indexName = store.addUniqueNameField() @@ -210,26 +148,63 @@ func (store *AuthPolicyStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *AuthPolicyStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*AuthPolicy, error) { - entity := &AuthPolicy{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *AuthPolicyStoreImpl) NewEntity() *AuthPolicy { + return &AuthPolicy{} } -func (store *AuthPolicyStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*AuthPolicy, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil +func (store *AuthPolicyStoreImpl) FillEntity(entity *AuthPolicy, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + + entity.Name = bucket.GetStringOrError(FieldName) + entity.Primary.Updb.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbAllowed, true) + entity.Primary.Updb.MinPasswordLength = bucket.GetInt64WithDefault(FiledAuthPolicyPrimaryUpdbMinPasswordLength, DefaultUpdbMinPasswordLength) + entity.Primary.Updb.RequireSpecialChar = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireSpecialChar, false) + entity.Primary.Updb.RequireNumberChar = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireNumberChar, false) + entity.Primary.Updb.RequireMixedCase = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryUpdbRequireMixedCase, false) + entity.Primary.Updb.MaxAttempts = bucket.GetInt64WithDefault(FieldAuthPolicyPrimaryUpdbMaxAttempts, DefaultUpdbMaxAttempts) + entity.Primary.Updb.LockoutDurationMinutes = bucket.GetInt64WithDefault(FieldAuthPolicyPrimaryUpdbLockoutDurationMinutes, 0) + + entity.Primary.Cert.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryCertAllowed, true) + entity.Primary.Cert.AllowExpiredCerts = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryCertAllowExpiredCerts, true) + + entity.Primary.ExtJwt.Allowed = bucket.GetBoolWithDefault(FieldAuthPolicyPrimaryExtJwtAllowed, true) + entity.Primary.ExtJwt.AllowedExtJwtSigners = bucket.GetStringList(FieldAuthPolicyPrimaryExtJwtAllowedSigners) + + entity.Secondary.RequireTotp = bucket.GetBoolWithDefault(FieldAuthSecondaryPolicyRequireTotp, false) + entity.Secondary.RequiredExtJwtSigner = bucket.GetString(FieldAuthSecondaryPolicyRequiredExtJwtSigner) } -func (store *AuthPolicyStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*AuthPolicy, error) { - entity := &AuthPolicy{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err +func (store *AuthPolicyStoreImpl) PersistEntity(entity *AuthPolicy, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + + if entity.Primary.Updb.LockoutDurationMinutes < 0 { + entity.Primary.Updb.LockoutDurationMinutes = UpdbIndefiniteLockout } - return entity, nil + + if entity.Primary.Updb.MaxAttempts < 0 { + entity.Primary.Updb.MaxAttempts = UpdbUnlimitedAttemptsLimit + } + + if entity.Primary.Updb.MinPasswordLength < DefaultUpdbMinPasswordLength { + entity.Primary.Updb.MinPasswordLength = DefaultUpdbMinPasswordLength + } + + ctx.SetString(FieldName, entity.Name) + + ctx.SetBool(FieldAuthPolicyPrimaryCertAllowed, entity.Primary.Cert.Allowed) + ctx.SetBool(FieldAuthPolicyPrimaryCertAllowExpiredCerts, entity.Primary.Cert.AllowExpiredCerts) + + ctx.SetBool(FieldAuthPolicyPrimaryUpdbAllowed, entity.Primary.Updb.Allowed) + ctx.SetInt64(FiledAuthPolicyPrimaryUpdbMinPasswordLength, entity.Primary.Updb.MinPasswordLength) + ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireSpecialChar, entity.Primary.Updb.RequireSpecialChar) + ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireNumberChar, entity.Primary.Updb.RequireNumberChar) + ctx.SetBool(FieldAuthPolicyPrimaryUpdbRequireMixedCase, entity.Primary.Updb.RequireMixedCase) + ctx.SetInt64(FieldAuthPolicyPrimaryUpdbMaxAttempts, entity.Primary.Updb.MaxAttempts) + ctx.SetInt64(FieldAuthPolicyPrimaryUpdbLockoutDurationMinutes, entity.Primary.Updb.LockoutDurationMinutes) + + ctx.SetBool(FieldAuthPolicyPrimaryExtJwtAllowed, entity.Primary.ExtJwt.Allowed) + ctx.SetStringList(FieldAuthPolicyPrimaryExtJwtAllowedSigners, entity.Primary.ExtJwt.AllowedExtJwtSigners) + + ctx.SetBool(FieldAuthSecondaryPolicyRequireTotp, entity.Secondary.RequireTotp) + ctx.SetStringP(FieldAuthSecondaryPolicyRequiredExtJwtSigner, entity.Secondary.RequiredExtJwtSigner) } diff --git a/controller/persistence/authenticator_store.go b/controller/persistence/authenticator_store.go index 08f39a373..98ddd7e5f 100644 --- a/controller/persistence/authenticator_store.go +++ b/controller/persistence/authenticator_store.go @@ -22,7 +22,6 @@ import ( "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -83,6 +82,10 @@ type Authenticator struct { SubType AuthenticatorSubType } +func (entity *Authenticator) GetEntityType() string { + return EntityTypeAuthenticators +} + var authenticatorFieldMappings = map[string]string{ FieldAuthenticatorIdentity: "identityId", FieldAuthenticatorUpdbPassword: "password", @@ -90,69 +93,6 @@ var authenticatorFieldMappings = map[string]string{ FieldAuthenticatorUpdbSalt: "salt", FieldAuthenticatorCertFingerprint: "fingerprint"} -func (entity *Authenticator) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.Type = bucket.GetStringOrError(FieldAuthenticatorMethod) - entity.IdentityId = bucket.GetStringOrError(FieldAuthenticatorIdentity) - - if entity.Type == MethodAuthenticatorCert { - authCert := &AuthenticatorCert{} - authCert.Fingerprint = bucket.GetStringWithDefault(FieldAuthenticatorCertFingerprint, "") - authCert.Pem = bucket.GetStringWithDefault(FieldAuthenticatorCertPem, "") - - authCert.UnverifiedPem = bucket.GetStringWithDefault(FieldAuthenticatorUnverifiedCertPem, "") - authCert.UnverifiedFingerprint = bucket.GetStringWithDefault(FieldAuthenticatorUnverifiedCertFingerprint, "") - entity.SubType = authCert - } else if entity.Type == MethodAuthenticatorUpdb { - authUpdb := &AuthenticatorUpdb{} - authUpdb.Username = bucket.GetStringWithDefault(FieldAuthenticatorUpdbUsername, "") - authUpdb.Password = bucket.GetStringWithDefault(FieldAuthenticatorUpdbPassword, "") - authUpdb.Salt = bucket.GetStringWithDefault(FieldAuthenticatorUpdbSalt, "") - entity.SubType = authUpdb - } -} - -func (entity *Authenticator) SetValues(ctx *boltz.PersistContext) { - ctx.WithFieldOverrides(authenticatorFieldMappings) - - entity.SetBaseValues(ctx) - ctx.SetString(FieldAuthenticatorMethod, entity.Type) - ctx.SetString(FieldAuthenticatorIdentity, entity.IdentityId) - - if entity.Type == MethodAuthenticatorCert { - if authCert, ok := entity.SubType.(*AuthenticatorCert); ok { - ctx.SetString(FieldAuthenticatorCertFingerprint, authCert.Fingerprint) - ctx.SetString(FieldAuthenticatorCertPem, authCert.Pem) - - ctx.SetString(FieldAuthenticatorUnverifiedCertFingerprint, authCert.UnverifiedFingerprint) - ctx.SetString(FieldAuthenticatorUnverifiedCertPem, authCert.UnverifiedPem) - } else { - pfxlog.Logger().Panic("type conversion error setting values for AuthenticatorCert") - } - } else if entity.Type == MethodAuthenticatorUpdb { - if authUpdb, ok := entity.SubType.(*AuthenticatorUpdb); ok { - ctx.SetString(FieldAuthenticatorUpdbPassword, authUpdb.Password) - ctx.SetString(FieldAuthenticatorUpdbUsername, authUpdb.Username) - ctx.SetString(FieldAuthenticatorUpdbSalt, authUpdb.Salt) - } else { - pfxlog.Logger().Panic("type conversion error setting values for AuthenticatorUpdb") - } - } - - store := ctx.Store.(*authenticatorStoreImpl) - _, identityId := store.symbolIdentityId.Eval(ctx.Tx(), []byte(entity.Id)) - if identityId != nil { - identityType := boltz.FieldToString(store.stores.identity.symbolIdentityTypeId.Eval(ctx.Tx(), identityId)) - if identityType != nil && *identityType == RouterIdentityType { - err := errorz.NewFieldError("may not create authenticators for router identities", "identityId", string(identityId)) - ctx.Bucket.SetError(errorz.NewFieldApiError(err)) - } - } -} - -func (entity *Authenticator) GetEntityType() string { - return EntityTypeAuthenticators -} - func (entity *Authenticator) ToUpdb() *AuthenticatorUpdb { if updb, ok := entity.SubType.(*AuthenticatorUpdb); ok { updb.Authenticator = *entity @@ -181,30 +121,24 @@ func (entity *Authenticator) ToSubType() AuthenticatorSubType { return nil } +var _ ApiSessionStore = (*apiSessionStoreImpl)(nil) + type AuthenticatorStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*Authenticator, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*Authenticator, error) + Store[*Authenticator] } func newAuthenticatorStore(stores *stores) *authenticatorStoreImpl { - store := &authenticatorStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeAuthenticators), - } + store := &authenticatorStoreImpl{} + store.baseStore = newBaseStore[*Authenticator](stores, store) store.InitImpl(store) - return store } type authenticatorStoreImpl struct { - *baseStore + *baseStore[*Authenticator] symbolIdentityId boltz.EntitySymbol } -func (store *authenticatorStoreImpl) NewStoreEntity() boltz.Entity { - return &Authenticator{} -} - func (store *authenticatorStoreImpl) initializeLocal() { store.AddExtEntitySymbols() @@ -222,20 +156,66 @@ func (store *authenticatorStoreImpl) initializeLinked() { store.AddFkIndex(store.symbolIdentityId, store.stores.identity.symbolAuthenticators) } -func (store *authenticatorStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Authenticator, error) { - entity := &Authenticator{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *authenticatorStoreImpl) NewEntity() *Authenticator { + return &Authenticator{} } -func (store *authenticatorStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*Authenticator, error) { - entity := &Authenticator{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err +func (store *authenticatorStoreImpl) FillEntity(entity *Authenticator, bucket *boltz.TypedBucket) { + entity.Type = bucket.GetStringOrError(FieldAuthenticatorMethod) + entity.IdentityId = bucket.GetStringOrError(FieldAuthenticatorIdentity) + + if entity.Type == MethodAuthenticatorCert { + authCert := &AuthenticatorCert{} + authCert.Fingerprint = bucket.GetStringWithDefault(FieldAuthenticatorCertFingerprint, "") + authCert.Pem = bucket.GetStringWithDefault(FieldAuthenticatorCertPem, "") + + authCert.UnverifiedPem = bucket.GetStringWithDefault(FieldAuthenticatorUnverifiedCertPem, "") + authCert.UnverifiedFingerprint = bucket.GetStringWithDefault(FieldAuthenticatorUnverifiedCertFingerprint, "") + entity.SubType = authCert + } else if entity.Type == MethodAuthenticatorUpdb { + authUpdb := &AuthenticatorUpdb{} + authUpdb.Username = bucket.GetStringWithDefault(FieldAuthenticatorUpdbUsername, "") + authUpdb.Password = bucket.GetStringWithDefault(FieldAuthenticatorUpdbPassword, "") + authUpdb.Salt = bucket.GetStringWithDefault(FieldAuthenticatorUpdbSalt, "") + entity.SubType = authUpdb + } +} + +func (store *authenticatorStoreImpl) PersistEntity(entity *Authenticator, ctx *boltz.PersistContext) { + ctx.WithFieldOverrides(authenticatorFieldMappings) + + entity.SetBaseValues(ctx) + ctx.SetString(FieldAuthenticatorMethod, entity.Type) + ctx.SetString(FieldAuthenticatorIdentity, entity.IdentityId) + + if entity.Type == MethodAuthenticatorCert { + if authCert, ok := entity.SubType.(*AuthenticatorCert); ok { + ctx.SetString(FieldAuthenticatorCertFingerprint, authCert.Fingerprint) + ctx.SetString(FieldAuthenticatorCertPem, authCert.Pem) + + ctx.SetString(FieldAuthenticatorUnverifiedCertFingerprint, authCert.UnverifiedFingerprint) + ctx.SetString(FieldAuthenticatorUnverifiedCertPem, authCert.UnverifiedPem) + } else { + pfxlog.Logger().Panic("type conversion error setting values for AuthenticatorCert") + } + } else if entity.Type == MethodAuthenticatorUpdb { + if authUpdb, ok := entity.SubType.(*AuthenticatorUpdb); ok { + ctx.SetString(FieldAuthenticatorUpdbPassword, authUpdb.Password) + ctx.SetString(FieldAuthenticatorUpdbUsername, authUpdb.Username) + ctx.SetString(FieldAuthenticatorUpdbSalt, authUpdb.Salt) + } else { + pfxlog.Logger().Panic("type conversion error setting values for AuthenticatorUpdb") + } + } + + _, identityId := store.symbolIdentityId.Eval(ctx.Tx(), []byte(entity.Id)) + if identityId != nil { + identityType := boltz.FieldToString(store.stores.identity.symbolIdentityTypeId.Eval(ctx.Tx(), identityId)) + if identityType != nil && *identityType == RouterIdentityType { + err := errorz.NewFieldError("may not create authenticators for router identities", "identityId", string(identityId)) + ctx.Bucket.SetError(errorz.NewFieldApiError(err)) + } } - return entity, nil } func (store *authenticatorStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { diff --git a/controller/persistence/base_store.go b/controller/persistence/base_store.go index a8853b23a..b6664d845 100644 --- a/controller/persistence/base_store.go +++ b/controller/persistence/base_store.go @@ -32,60 +32,43 @@ type DbProvider interface { GetManagers() *network.Managers } -type Store interface { - boltz.CrudStore +type initializableStore interface { + boltz.Store initializeLocal() initializeLinked() initializeIndexes(tx *bbolt.Tx, errorHolder errorz.ErrorHolder) } -func newBaseStore(stores *stores, entityType string) *baseStore { - singularEntityType := boltz.GetSingularEntityType(entityType) - return &baseStore{ - stores: stores, - BaseStore: boltz.NewBaseStore(entityType, func(id string) error { - return boltz.NewNotFoundError(singularEntityType, "id", id) - }, db.RootBucket), - } +type Store[E boltz.ExtEntity] interface { + boltz.EntityStore[E] + initializableStore + LoadOneById(tx *bbolt.Tx, id string) (E, error) } -func newChildBaseStore(stores *stores, parent boltz.CrudStore, parentMapper func(entity boltz.Entity) boltz.Entity) *baseStore { - return newChildBaseStoreWithPath(stores, parent, parentMapper, EdgeBucket) -} - -func newChildBaseStoreWithPath(stores *stores, parent boltz.CrudStore, parentMapper func(entity boltz.Entity) boltz.Entity, path string) *baseStore { - entityNotFoundF := func(id string) error { - return boltz.NewNotFoundError(parent.GetSingularEntityType(), "id", id) - } - - return &baseStore{ - stores: stores, - BaseStore: boltz.NewChildBaseStore(parent, parentMapper, entityNotFoundF, path), - } -} - -func newExtendedBaseStore(stores *stores, parent boltz.CrudStore, parentMapper func(entity boltz.Entity) boltz.Entity, path string) *baseStore { - store := newChildBaseStoreWithPath(stores, parent, parentMapper, path) - store.BaseStore.Extended() - return store -} - -type baseStore struct { +type baseStore[E boltz.ExtEntity] struct { stores *stores - *boltz.BaseStore + *boltz.BaseStore[E] } -func (store *baseStore) addUniqueNameField() boltz.ReadIndex { +func (store *baseStore[E]) addUniqueNameField() boltz.ReadIndex { symbolName := store.AddSymbol(FieldName, ast.NodeTypeString) return store.AddUniqueIndex(symbolName) } -func (store *baseStore) initializeIndexes(tx *bbolt.Tx, errorHolder errorz.ErrorHolder) { +func (store *baseStore[E]) initializeIndexes(tx *bbolt.Tx, errorHolder errorz.ErrorHolder) { store.InitializeIndexes(tx, errorHolder) } -func (store *baseStore) baseLoadOneById(tx *bbolt.Tx, id string, entity boltz.Entity) error { - found, err := store.BaseLoadOneById(tx, id, entity) +func (store *baseStore[E]) LoadOneById(tx *bbolt.Tx, id string) (E, error) { + entity := store.NewStoreEntity() + if err := store.baseLoadOneById(tx, id, entity); err != nil { + return *new(E), err + } + return entity, nil +} + +func (store *baseStore[E]) baseLoadOneById(tx *bbolt.Tx, id string, entity E) error { + found, err := store.LoadEntity(tx, id, entity) if err != nil { return err } @@ -95,7 +78,7 @@ func (store *baseStore) baseLoadOneById(tx *bbolt.Tx, id string, entity boltz.En return nil } -func (store *baseStore) deleteEntityReferences(tx *bbolt.Tx, entity boltz.NamedExtEntity, rolesSymbol boltz.EntitySetSymbol) error { +func (store *baseStore[E]) deleteEntityReferences(tx *bbolt.Tx, entity boltz.NamedExtEntity, rolesSymbol boltz.EntitySetSymbol) error { idRef := entityRef(entity.GetId()) for _, policyHolderId := range store.GetRelatedEntitiesIdList(tx, entity.GetId(), rolesSymbol.GetStore().GetEntityType()) { @@ -111,12 +94,17 @@ func (store *baseStore) deleteEntityReferences(tx *bbolt.Tx, entity boltz.NamedE return nil } -type NameIndexedStore interface { - Store +func (store *baseStore[E]) getParentBucket(entity boltz.Entity, childBucket *boltz.TypedBucket) *boltz.TypedBucket { + parentBucket := store.GetParentStore().GetEntityBucket(childBucket.Tx(), []byte(entity.GetId())) + parentBucket.ErrorHolderImpl = childBucket.ErrorHolderImpl + return parentBucket +} + +type NameIndexed interface { GetNameIndex() boltz.ReadIndex } -func (store *baseStore) GetName(tx *bbolt.Tx, id string) *string { +func (store *baseStore[E]) GetName(tx *bbolt.Tx, id string) *string { symbol := store.GetSymbol(FieldName) if symbol == nil { return nil @@ -129,7 +117,7 @@ func (store *baseStore) GetName(tx *bbolt.Tx, id string) *string { return nil } -func (store *baseStore) getRoleAttributesCursorProvider(index boltz.SetReadIndex, values []string, semantic string) (ast.SetCursorProvider, error) { +func (store *baseStore[E]) getRoleAttributesCursorProvider(index boltz.SetReadIndex, values []string, semantic string) (ast.SetCursorProvider, error) { if semantic == "" { semantic = SemanticAllOf } diff --git a/controller/persistence/ca_store.go b/controller/persistence/ca_store.go index 5c1b2fe3c..d4aa3d28c 100644 --- a/controller/persistence/ca_store.go +++ b/controller/persistence/ca_store.go @@ -19,7 +19,6 @@ package persistence import ( "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -83,7 +82,50 @@ func (entity *Ca) GetName() string { return entity.Name } -func (entity *Ca) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *Ca) GetEntityType() string { + return EntityTypeCas +} + +var _ CaStore = (*caStoreImpl)(nil) + +type CaStore interface { + Store[*Ca] +} + +func newCaStore(stores *stores) *caStoreImpl { + store := &caStoreImpl{} + store.baseStore = newBaseStore[*Ca](stores, store) + store.InitImpl(store) + return store +} + +type caStoreImpl struct { + *baseStore[*Ca] + indexName boltz.ReadIndex + symbolEnrollments boltz.EntitySetSymbol +} + +func (store *caStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + store.indexName = store.addUniqueNameField() + store.AddSymbol(FieldCaFingerprint, ast.NodeTypeString) + store.AddSymbol(FieldCaIsVerified, ast.NodeTypeBool) + store.AddSymbol(FieldCaVerificationToken, ast.NodeTypeString) + store.AddSymbol(FieldCaIsAutoCaEnrollmentEnabled, ast.NodeTypeBool) + store.AddSymbol(FieldCaIsOttCaEnrollmentEnabled, ast.NodeTypeBool) + store.AddSymbol(FieldCaIsAuthEnabled, ast.NodeTypeBool) + store.AddSetSymbol(FieldIdentityRoles, ast.NodeTypeString) + store.symbolEnrollments = store.AddFkSetSymbol(FieldCaEnrollments, store.stores.enrollment) + +} + +func (store *caStoreImpl) initializeLinked() {} + +func (store *caStoreImpl) NewEntity() *Ca { + return &Ca{} +} + +func (store *caStoreImpl) FillEntity(entity *Ca, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) entity.Fingerprint = bucket.GetStringOrError(FieldCaFingerprint) @@ -105,10 +147,9 @@ func (entity *Ca) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { entity.ExternalIdClaim.ParserCriteria = externalField.GetStringWithDefault(FieldCaExternalIdClaimParserCriteria, "") entity.ExternalIdClaim.Index = externalField.GetInt64WithDefault(FieldCaExternalIdClaimIndex, 0) } - } -func (entity *Ca) SetValues(ctx *boltz.PersistContext) { +func (store *caStoreImpl) PersistEntity(entity *Ca, ctx *boltz.PersistContext) { entity.SetBaseValues(ctx) ctx.SetString(FieldName, entity.Name) ctx.SetString(FieldCaFingerprint, entity.Fingerprint) @@ -132,77 +173,6 @@ func (entity *Ca) SetValues(ctx *boltz.PersistContext) { } else { _ = ctx.Bucket.DeleteBucket([]byte(FieldCaExternalIdClaim)) } - -} - -func (entity *Ca) GetEntityType() string { - return EntityTypeCas -} - -type CaStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*Ca, error) - LoadOneByName(tx *bbolt.Tx, id string) (*Ca, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*Ca, error) -} - -func newCaStore(stores *stores) *caStoreImpl { - store := &caStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeCas), - } - store.InitImpl(store) - return store -} - -type caStoreImpl struct { - *baseStore - indexName boltz.ReadIndex - symbolEnrollments boltz.EntitySetSymbol -} - -func (store *caStoreImpl) NewStoreEntity() boltz.Entity { - return &Ca{} -} - -func (store *caStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - store.indexName = store.addUniqueNameField() - store.AddSymbol(FieldCaFingerprint, ast.NodeTypeString) - store.AddSymbol(FieldCaIsVerified, ast.NodeTypeBool) - store.AddSymbol(FieldCaVerificationToken, ast.NodeTypeString) - store.AddSymbol(FieldCaIsAutoCaEnrollmentEnabled, ast.NodeTypeBool) - store.AddSymbol(FieldCaIsOttCaEnrollmentEnabled, ast.NodeTypeBool) - store.AddSymbol(FieldCaIsAuthEnabled, ast.NodeTypeBool) - store.AddSetSymbol(FieldIdentityRoles, ast.NodeTypeString) - store.symbolEnrollments = store.AddFkSetSymbol(FieldCaEnrollments, store.stores.enrollment) - -} - -func (store *caStoreImpl) initializeLinked() { -} - -func (store *caStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Ca, error) { - entity := &Ca{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *caStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*Ca, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - -func (store *caStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*Ca, error) { - entity := &Ca{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil } func (store *caStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { @@ -214,7 +184,3 @@ func (store *caStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { return store.baseStore.DeleteById(ctx, id) } - -func (store *caStoreImpl) Update(ctx boltz.MutateContext, entity boltz.Entity, checker boltz.FieldChecker) error { - return store.baseStore.Update(ctx, entity, checker) -} diff --git a/controller/persistence/config_store.go b/controller/persistence/config_store.go index 1ecd6767b..daaf66174 100644 --- a/controller/persistence/config_store.go +++ b/controller/persistence/config_store.go @@ -51,44 +51,26 @@ func (entity *Config) GetName() string { return entity.Name } -func (entity *Config) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Name = bucket.GetStringOrError(FieldName) - entity.Type = bucket.GetStringOrError(FieldConfigType) - entity.Data = bucket.GetMap(FieldConfigData) -} - -func (entity *Config) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldName, entity.Name) - ctx.SetString(FieldConfigType, entity.Type) - ctx.SetMap(FieldConfigData, entity.Data) - - if ctx.ProceedWithSet(FieldConfigData) && entity.Data == nil { - ctx.Bucket.SetError(errorz.NewFieldError("data is required", "data", nil)) - } -} - func (entity *Config) GetEntityType() string { return EntityTypeConfigs } +var _ ConfigStore = (*configStoreImpl)(nil) + type ConfigStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*Config, error) - LoadOneByName(tx *bbolt.Tx, name string) (*Config, error) + Store[*Config] + NameIndexed } func newConfigsStore(stores *stores) *configStoreImpl { - store := &configStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeConfigs), - } + store := &configStoreImpl{} + store.baseStore = newBaseStore[*Config](stores, store) store.InitImpl(store) return store } type configStoreImpl struct { - *baseStore + *baseStore[*Config] indexName boltz.ReadIndex symbolType boltz.EntitySymbol @@ -116,27 +98,29 @@ func (store *configStoreImpl) initializeLinked() { store.AddLinkCollection(store.symbolServices, store.stores.edgeService.symbolConfigs) } -func (store *configStoreImpl) NewStoreEntity() boltz.Entity { +func (store *configStoreImpl) NewEntity() *Config { return &Config{} } -func (store *configStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Config, error) { - entity := &Config{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *configStoreImpl) FillEntity(entity *Config, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Name = bucket.GetStringOrError(FieldName) + entity.Type = bucket.GetStringOrError(FieldConfigType) + entity.Data = bucket.GetMap(FieldConfigData) } -func (store *configStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*Config, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) +func (store *configStoreImpl) PersistEntity(entity *Config, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldName, entity.Name) + ctx.SetString(FieldConfigType, entity.Type) + ctx.SetMap(FieldConfigData, entity.Data) + + if ctx.ProceedWithSet(FieldConfigData) && entity.Data == nil { + ctx.Bucket.SetError(errorz.NewFieldError("data is required", "data", nil)) } - return nil, nil } -func (store *configStoreImpl) Update(ctx boltz.MutateContext, entity boltz.Entity, checker boltz.FieldChecker) error { +func (store *configStoreImpl) Update(ctx boltz.MutateContext, entity *Config, checker boltz.FieldChecker) error { if err := store.createServiceChangeEvents(ctx.Tx(), entity.GetId()); err != nil { return err } @@ -175,7 +159,7 @@ func (store *configStoreImpl) createServiceChangeEvents(tx *bbolt.Tx, configId s id := []byte(configId) err := store.symbolServices.Map(tx, id, func(ctx *boltz.MapContext) { - eh.addServiceUpdatedEvent(store.baseStore, tx, ctx.Value()) + eh.addServiceUpdatedEvent(store.stores, tx, ctx.Value()) }) if err != nil { diff --git a/controller/persistence/config_store_test.go b/controller/persistence/config_store_test.go index 9c07a60f2..34ef09bb3 100644 --- a/controller/persistence/config_store_test.go +++ b/controller/persistence/config_store_test.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "github.com/openziti/edge/eid" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "testing" "time" @@ -38,13 +39,13 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { ctx.CleanupAll() configType := newConfigType(eid.New()) - ctx.RequireCreate(configType) + boltztest.RequireCreate(ctx, configType) config := newConfig(eid.New(), "", map[string]interface{}{ "dnsHostname": "ssh.yourcompany.com", "port": int64(22), }) - err := ctx.Create(config) + err := boltztest.Create(ctx, config) ctx.EqualError(err, "index on configs.type does not allow null or empty values") invalidId := eid.New() @@ -52,18 +53,18 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { "dnsHostname": "ssh.yourcompany.com", "port": int64(22), }) - err = ctx.Create(config) + err = boltztest.Create(ctx, config) ctx.EqualError(err, fmt.Sprintf("configType with id %v not found", invalidId)) config = newConfig(eid.New(), configType.Id, map[string]interface{}{ "dnsHostname": "ssh.yourcompany.com", "port": int64(22), }) - ctx.RequireCreate(config) - ctx.ValidateBaseline(config) + boltztest.RequireCreate(ctx, config) + boltztest.ValidateBaseline(ctx, config) err = ctx.GetDb().View(func(tx *bbolt.Tx) error { - testConfig, err := ctx.stores.Config.LoadOneByName(tx, config.Name) + testConfig, err := ctx.stores.Config.LoadOneById(tx, config.Id) ctx.NoError(err) ctx.NotNil(testConfig) ctx.Equal(config.Name, testConfig.Name) @@ -73,7 +74,7 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { ctx.NoError(err) config.Id = eid.New() - err = ctx.Create(config) + err = boltztest.Create(ctx, config) ctx.EqualError(err, fmt.Sprintf("duplicate value '%v' in unique index on configs store", config.Name)) config = newConfig(eid.New(), configType.Id, map[string]interface{}{ @@ -86,8 +87,8 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { "count": 1000.32, }, }) - ctx.RequireCreate(config) - ctx.ValidateBaseline(config) + boltztest.RequireCreate(ctx, config) + boltztest.ValidateBaseline(ctx, config) config = newConfig(eid.New(), configType.Id, map[string]interface{}{ "dnsHostname": "ssh.yourcompany.com", @@ -106,8 +107,8 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { }, }, }) - ctx.RequireCreate(config) - ctx.ValidateBaseline(config) + boltztest.RequireCreate(ctx, config) + boltztest.ValidateBaseline(ctx, config) configValue := ` { @@ -122,8 +123,8 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { ctx.NoError(err) config = newConfig(eid.New(), configType.Id, configMap) - ctx.RequireCreate(config) - ctx.ValidateBaseline(config) + boltztest.RequireCreate(ctx, config) + boltztest.ValidateBaseline(ctx, config) config.Data = map[string]interface{}{ "dnsHostname": "ssh.mycompany.com", @@ -131,17 +132,17 @@ func (ctx *TestContext) testConfigCrud(*testing.T) { } time.Sleep(10 * time.Millisecond) // ensure updated time is different than created time - ctx.RequireUpdate(config) - ctx.ValidateUpdated(config) + boltztest.RequireUpdate(ctx, config) + boltztest.ValidateUpdated(ctx, config) - ctx.RequireDelete(config) + boltztest.RequireDelete(ctx, config) } func (ctx *TestContext) testConfigQuery(*testing.T) { ctx.CleanupAll() configType := newConfigType(eid.New()) - ctx.RequireCreate(configType) + boltztest.RequireCreate(ctx, configType) config := newConfig(eid.New(), configType.Id, map[string]interface{}{ "dnsHostname": "ssh.yourcompany.com", @@ -160,7 +161,7 @@ func (ctx *TestContext) testConfigQuery(*testing.T) { }, }, }) - ctx.RequireCreate(config) + boltztest.RequireCreate(ctx, config) err := ctx.GetDb().View(func(tx *bbolt.Tx) error { ids, _, err := ctx.stores.Config.QueryIds(tx, `data.enabled and data.nested.hello = "hi"`) @@ -180,5 +181,5 @@ func (ctx *TestContext) testConfigQuery(*testing.T) { }) ctx.NoError(err) - ctx.RequireDelete(config) + boltztest.RequireDelete(ctx, config) } diff --git a/controller/persistence/config_type_store.go b/controller/persistence/config_type_store.go index 2a50c9289..a6412c3dc 100644 --- a/controller/persistence/config_type_store.go +++ b/controller/persistence/config_type_store.go @@ -46,53 +46,28 @@ func (entity *ConfigType) GetName() string { return entity.Name } -func (entity *ConfigType) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Name = bucket.GetStringOrError(FieldName) - marshalledSchema := bucket.GetString(FieldConfigTypeSchema) - if marshalledSchema != nil { - entity.Schema = map[string]interface{}{} - bucket.SetError(json.Unmarshal([]byte(*marshalledSchema), &entity.Schema)) - } -} - -func (entity *ConfigType) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldName, entity.Name) - - if len(entity.Schema) > 0 { - marshalled, err := json.Marshal(entity.Schema) - if err != nil { - ctx.Bucket.SetError(err) - return - } - ctx.SetString(FieldConfigTypeSchema, string(marshalled)) - } else { - ctx.SetStringP(FieldConfigTypeSchema, nil) - } -} - func (entity *ConfigType) GetEntityType() string { return EntityTypeConfigTypes } +var _ ConfigTypeStore = (*configTypeStoreImpl)(nil) + type ConfigTypeStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*ConfigType, error) + Store[*ConfigType] + NameIndexed LoadOneByName(tx *bbolt.Tx, name string) (*ConfigType, error) GetName(tx *bbolt.Tx, id string) *string } func newConfigTypesStore(stores *stores) *configTypeStoreImpl { - store := &configTypeStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeConfigTypes), - } + store := &configTypeStoreImpl{} + store.baseStore = newBaseStore[*ConfigType](stores, store) store.InitImpl(store) return store } type configTypeStoreImpl struct { - *baseStore + *baseStore[*ConfigType] indexName boltz.ReadIndex symbolConfigs boltz.EntitySetSymbol @@ -112,16 +87,34 @@ func (store *configTypeStoreImpl) initializeLocal() { func (store *configTypeStoreImpl) initializeLinked() { } -func (store *configTypeStoreImpl) NewStoreEntity() boltz.Entity { +func (store *configTypeStoreImpl) NewEntity() *ConfigType { return &ConfigType{} } -func (store *configTypeStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ConfigType, error) { - entity := &ConfigType{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err +func (store *configTypeStoreImpl) FillEntity(entity *ConfigType, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Name = bucket.GetStringOrError(FieldName) + marshalledSchema := bucket.GetString(FieldConfigTypeSchema) + if marshalledSchema != nil { + entity.Schema = map[string]interface{}{} + bucket.SetError(json.Unmarshal([]byte(*marshalledSchema), &entity.Schema)) + } +} + +func (store *configTypeStoreImpl) PersistEntity(entity *ConfigType, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldName, entity.Name) + + if len(entity.Schema) > 0 { + marshalled, err := json.Marshal(entity.Schema) + if err != nil { + ctx.Bucket.SetError(err) + return + } + ctx.SetString(FieldConfigTypeSchema, string(marshalled)) + } else { + ctx.SetStringP(FieldConfigTypeSchema, nil) } - return entity, nil } func (store *configTypeStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*ConfigType, error) { diff --git a/controller/persistence/config_type_store_test.go b/controller/persistence/config_type_store_test.go index bcdac232e..e87d8406f 100644 --- a/controller/persistence/config_type_store_test.go +++ b/controller/persistence/config_type_store_test.go @@ -19,6 +19,7 @@ package persistence import ( "fmt" "github.com/openziti/edge/eid" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "testing" "time" @@ -36,12 +37,12 @@ func (ctx *TestContext) testConfigTypeCrud(*testing.T) { ctx.CleanupAll() configType := newConfigType("") - err := ctx.Create(configType) + err := boltztest.Create(ctx, configType) ctx.EqualError(err, "index on configTypes.name does not allow null or empty values") configType = newConfigType(eid.New()) - ctx.RequireCreate(configType) - ctx.ValidateBaseline(configType) + boltztest.RequireCreate(ctx, configType) + boltztest.ValidateBaseline(ctx, configType) err = ctx.GetDb().View(func(tx *bbolt.Tx) error { testConfigType, err := ctx.stores.ConfigType.LoadOneByName(tx, configType.Name) @@ -55,14 +56,14 @@ func (ctx *TestContext) testConfigTypeCrud(*testing.T) { time.Sleep(10 * time.Millisecond) // ensure updated time is different than created time configType.Name = eid.New() - ctx.RequireUpdate(configType) - ctx.ValidateUpdated(configType) + boltztest.RequireUpdate(ctx, configType) + boltztest.ValidateUpdated(ctx, configType) config := newConfig(eid.New(), configType.Id, map[string]interface{}{ "dnsHostname": "ssh.yourcompany.com", "port": int64(22), }) - ctx.RequireCreate(config) + boltztest.RequireCreate(ctx, config) err = ctx.GetDb().View(func(tx *bbolt.Tx) error { ids := ctx.stores.ConfigType.GetRelatedEntitiesIdList(tx, configType.Id, EntityTypeConfigs) @@ -71,9 +72,9 @@ func (ctx *TestContext) testConfigTypeCrud(*testing.T) { }) ctx.NoError(err) - err = ctx.Delete(configType) + err = boltztest.Delete(ctx, configType) ctx.EqualError(err, fmt.Sprintf("cannot delete config type %v, as configs of that type exist", configType.Id)) - ctx.RequireDelete(config) - ctx.RequireDelete(configType) + boltztest.RequireDelete(ctx, config) + boltztest.RequireDelete(ctx, configType) } diff --git a/controller/persistence/edge_router_policy_store.go b/controller/persistence/edge_router_policy_store.go index e90319118..28398d405 100644 --- a/controller/persistence/edge_router_policy_store.go +++ b/controller/persistence/edge_router_policy_store.go @@ -4,11 +4,10 @@ import ( "fmt" "github.com/openziti/edge/eid" "github.com/openziti/fabric/controller/db" - "github.com/openziti/storage/ast" - "github.com/openziti/storage/boltz" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" - "go.etcd.io/bbolt" + "github.com/openziti/storage/ast" + "github.com/openziti/storage/boltz" "sort" ) @@ -36,68 +35,26 @@ func (entity *EdgeRouterPolicy) GetSemantic() string { return entity.Semantic } -func (entity *EdgeRouterPolicy) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Name = bucket.GetStringOrError(FieldName) - entity.Semantic = bucket.GetStringWithDefault(FieldSemantic, SemanticAllOf) - entity.IdentityRoles = bucket.GetStringList(FieldIdentityRoles) - entity.EdgeRouterRoles = bucket.GetStringList(FieldEdgeRouterRoles) -} - -func (entity *EdgeRouterPolicy) SetValues(ctx *boltz.PersistContext) { - if err := validateRolesAndIds(FieldIdentityRoles, entity.IdentityRoles); err != nil { - ctx.Bucket.SetError(err) - } - - if err := validateRolesAndIds(FieldEdgeRouterRoles, entity.EdgeRouterRoles); err != nil { - ctx.Bucket.SetError(err) - } - - entity.SetBaseValues(ctx) - ctx.SetRequiredString(FieldName, entity.Name) - if ctx.ProceedWithSet(FieldSemantic) { - if !isSemanticValid(entity.Semantic) { - ctx.Bucket.SetError(errorz.NewFieldError("invalid semantic", FieldSemantic, entity.Semantic)) - return - } - ctx.SetRequiredString(FieldSemantic, entity.Semantic) - } - - edgeRouterPolicyStore := ctx.Store.(*edgeRouterPolicyStoreImpl) - - sort.Strings(entity.EdgeRouterRoles) - sort.Strings(entity.IdentityRoles) - - oldIdentityRoles, valueSet := ctx.GetAndSetStringList(FieldIdentityRoles, entity.IdentityRoles) - if valueSet && !stringz.EqualSlices(oldIdentityRoles, entity.IdentityRoles) { - edgeRouterPolicyStore.identityRolesUpdated(ctx, entity) - } - oldEdgeRouterRoles, valueSet := ctx.GetAndSetStringList(FieldEdgeRouterRoles, entity.EdgeRouterRoles) - if valueSet && !stringz.EqualSlices(oldEdgeRouterRoles, entity.EdgeRouterRoles) { - edgeRouterPolicyStore.edgeRouterRolesUpdated(ctx, entity) - } -} - func (entity *EdgeRouterPolicy) GetEntityType() string { return EntityTypeEdgeRouterPolicies } +var _ EdgeRouterPolicyStore = (*edgeRouterPolicyStoreImpl)(nil) + type EdgeRouterPolicyStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*EdgeRouterPolicy, error) - LoadOneByName(tx *bbolt.Tx, id string) (*EdgeRouterPolicy, error) + NameIndexed + Store[*EdgeRouterPolicy] } func newEdgeRouterPolicyStore(stores *stores) *edgeRouterPolicyStoreImpl { - store := &edgeRouterPolicyStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeEdgeRouterPolicies), - } + store := &edgeRouterPolicyStoreImpl{} + store.baseStore = newBaseStore[*EdgeRouterPolicy](stores, store) store.InitImpl(store) return store } type edgeRouterPolicyStoreImpl struct { - *baseStore + *baseStore[*EdgeRouterPolicy] indexName boltz.ReadIndex symbolSemantic boltz.EntitySymbol @@ -110,10 +67,6 @@ type edgeRouterPolicyStoreImpl struct { edgeRouterCollection boltz.LinkCollection } -func (store *edgeRouterPolicyStoreImpl) NewStoreEntity() boltz.Entity { - return &EdgeRouterPolicy{} -} - func (store *edgeRouterPolicyStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } @@ -136,28 +89,56 @@ func (store *edgeRouterPolicyStoreImpl) initializeLinked() { store.identityCollection = store.AddLinkCollection(store.symbolIdentities, store.stores.identity.symbolEdgeRouterPolicies) } -func (store *edgeRouterPolicyStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*EdgeRouterPolicy, error) { - entity := &EdgeRouterPolicy{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *edgeRouterPolicyStoreImpl) NewEntity() *EdgeRouterPolicy { + return &EdgeRouterPolicy{} } -func (store *edgeRouterPolicyStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*EdgeRouterPolicy, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) +func (store *edgeRouterPolicyStoreImpl) FillEntity(entity *EdgeRouterPolicy, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Name = bucket.GetStringOrError(FieldName) + entity.Semantic = bucket.GetStringWithDefault(FieldSemantic, SemanticAllOf) + entity.IdentityRoles = bucket.GetStringList(FieldIdentityRoles) + entity.EdgeRouterRoles = bucket.GetStringList(FieldEdgeRouterRoles) +} + +func (store *edgeRouterPolicyStoreImpl) PersistEntity(entity *EdgeRouterPolicy, ctx *boltz.PersistContext) { + if err := validateRolesAndIds(FieldIdentityRoles, entity.IdentityRoles); err != nil { + ctx.Bucket.SetError(err) + } + + if err := validateRolesAndIds(FieldEdgeRouterRoles, entity.EdgeRouterRoles); err != nil { + ctx.Bucket.SetError(err) + } + + entity.SetBaseValues(ctx) + ctx.SetRequiredString(FieldName, entity.Name) + if ctx.ProceedWithSet(FieldSemantic) { + if !isSemanticValid(entity.Semantic) { + ctx.Bucket.SetError(errorz.NewFieldError("invalid semantic", FieldSemantic, entity.Semantic)) + return + } + ctx.SetRequiredString(FieldSemantic, entity.Semantic) + } + + sort.Strings(entity.EdgeRouterRoles) + sort.Strings(entity.IdentityRoles) + + oldIdentityRoles, valueSet := ctx.GetAndSetStringList(FieldIdentityRoles, entity.IdentityRoles) + if valueSet && !stringz.EqualSlices(oldIdentityRoles, entity.IdentityRoles) { + store.identityRolesUpdated(ctx, entity) + } + oldEdgeRouterRoles, valueSet := ctx.GetAndSetStringList(FieldEdgeRouterRoles, entity.EdgeRouterRoles) + if valueSet && !stringz.EqualSlices(oldEdgeRouterRoles, entity.EdgeRouterRoles) { + store.edgeRouterRolesUpdated(ctx, entity) } - return nil, nil } /* Optimizations -1. When changing policies if only ids have changed, only add/remove ids from groups as needed -2. When related entities added/changed, only evaluate policies against that one entity (identity/edge router/service), - and just add/remove/ignore -3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) + 1. When changing policies if only ids have changed, only add/remove ids from groups as needed + 2. When related entities added/changed, only evaluate policies against that one entity (identity/edge router/service), + and just add/remove/ignore + 3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) */ func (store *edgeRouterPolicyStoreImpl) edgeRouterRolesUpdated(persistCtx *boltz.PersistContext, policy *EdgeRouterPolicy) { ctx := &roleAttributeChangeContext{ @@ -199,10 +180,10 @@ func (store *edgeRouterPolicyStoreImpl) DeleteById(ctx boltz.MutateContext, id s return store.BaseStore.DeleteById(ctx, id) } -func (store *edgeRouterPolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, errorSink func(error, bool)) error { - ctx := &denormCheckCtx{ +func (store *edgeRouterPolicyStoreImpl) CheckIntegrity(ctx boltz.MutateContext, fix bool, errorSink func(error, bool)) error { + checkCtx := &denormCheckCtx{ name: "edge-router-policies", - tx: tx, + mutateCtx: ctx, sourceStore: store.stores.identity, targetStore: store.stores.edgeRouter, policyStore: store, @@ -212,9 +193,9 @@ func (store *edgeRouterPolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, e repair: fix, errorSink: errorSink, } - if err := validatePolicyDenormalization(ctx); err != nil { + if err := validatePolicyDenormalization(checkCtx); err != nil { return err } - return store.BaseStore.CheckIntegrity(tx, fix, errorSink) + return store.BaseStore.CheckIntegrity(ctx, fix, errorSink) } diff --git a/controller/persistence/edge_router_policy_store_test.go b/controller/persistence/edge_router_policy_store_test.go index 2a9ae629b..c68653fb4 100644 --- a/controller/persistence/edge_router_policy_store_test.go +++ b/controller/persistence/edge_router_policy_store_test.go @@ -4,9 +4,10 @@ import ( "fmt" "github.com/openziti/edge/eid" "github.com/openziti/fabric/controller/db" - "github.com/openziti/storage/boltz" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "github.com/sirupsen/logrus" "go.etcd.io/bbolt" "sort" @@ -31,14 +32,14 @@ func (ctx *TestContext) testCreateEdgeRouterPolicy(t *testing.T) { ctx.CleanupAll() policy := newEdgeRouterPolicy(eid.New()) - ctx.RequireCreate(policy) - ctx.ValidateBaseline(policy) + boltztest.RequireCreate(ctx, policy) + boltztest.ValidateBaseline(ctx, policy) err := ctx.GetDb().View(func(tx *bbolt.Tx) error { ctx.Equal(0, len(ctx.stores.EdgeRouterPolicy.GetRelatedEntitiesIdList(tx, policy.Id, db.EntityTypeRouters))) ctx.Equal(0, len(ctx.stores.EdgeRouterPolicy.GetRelatedEntitiesIdList(tx, policy.Id, EntityTypeIdentities))) - testPolicy, err := ctx.stores.EdgeRouterPolicy.LoadOneByName(tx, policy.Name) + testPolicy, err := ctx.stores.EdgeRouterPolicy.LoadOneById(tx, policy.Id) ctx.NoError(err) ctx.NotNil(testPolicy) ctx.Equal(policy.Name, testPolicy.Name) @@ -56,55 +57,55 @@ func (ctx *TestContext) testEdgeRouterPolicyInvalidValues(t *testing.T) { policy := newEdgeRouterPolicy(eid.New()) invalidId := eid.New() policy.IdentityRoles = []string{entityRef(invalidId)} - err := ctx.Create(policy) + err := boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) policy.IdentityRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'identityRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) identityTypeId := ctx.getIdentityTypeId() identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateEdgeRouterPolicyIdentities([]*Identity{identity}, []*EdgeRouterPolicy{policy}) policy.IdentityRoles = append(policy.IdentityRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) // test edgeRouter roles policy.IdentityRoles = nil policy.EdgeRouterRoles = []string{entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) policy.EdgeRouterRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'edgeRouterRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*EdgeRouterPolicy{policy}) policy.EdgeRouterRoles = append(policy.EdgeRouterRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } func (ctx *TestContext) testEdgeRouterPolicyUpdateDeleteRefs(t *testing.T) { @@ -115,58 +116,58 @@ func (ctx *TestContext) testEdgeRouterPolicyUpdateDeleteRefs(t *testing.T) { policy := newEdgeRouterPolicy(eid.New()) identityTypeId := ctx.getIdentityTypeId() identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateEdgeRouterPolicies([]*Identity{identity}, nil, []*EdgeRouterPolicy{policy}) - ctx.RequireDelete(identity) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.IdentityRoles), "identity id should have been removed from identity roles") identity = newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateEdgeRouterPolicyIdentities([]*Identity{identity}, []*EdgeRouterPolicy{policy}) identity.Name = eid.New() - ctx.RequireUpdate(identity) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.IdentityRoles, entityRef(identity.Id))) ctx.validateEdgeRouterPolicyIdentities([]*Identity{identity}, []*EdgeRouterPolicy{policy}) - ctx.RequireDelete(identity) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.IdentityRoles), "identity name should have been removed from identity roles") // test edgeRouter roles edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*EdgeRouterPolicy{policy}) - ctx.RequireDelete(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.EdgeRouterRoles), "edgeRouter id should have been removed from edgeRouter roles") edgeRouter = newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*EdgeRouterPolicy{policy}) edgeRouter.Name = eid.New() - ctx.RequireUpdate(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.EdgeRouterRoles, entityRef(edgeRouter.Id))) ctx.validateEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*EdgeRouterPolicy{policy}) - ctx.RequireDelete(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.EdgeRouterRoles), "edgeRouter name should have been removed from edgeRouter roles") } @@ -177,27 +178,27 @@ func (ctx *TestContext) testRouterIdentityDeleteTest(t *testing.T) { policy := newEdgeRouterPolicy(eid.New()) policy.IdentityRoles = []string{"#all"} policy.EdgeRouterRoles = []string{"#all"} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) edgeRouterOther := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouterOther) + boltztest.RequireCreate(ctx, edgeRouterOther) logrus.Infof("router 1 id: %v", edgeRouterOther.Id) edgeRouter := newEdgeRouter(eid.New()) edgeRouter.IsTunnelerEnabled = true - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) logrus.Infof("router 2 id: %v", edgeRouter.Id) addErrors := func(err error, fixed bool) { ctx.NoError(err) } - err := ctx.db.View(func(tx *bbolt.Tx) error { - if err := ctx.stores.EdgeRouter.CheckIntegrity(tx, false, addErrors); err != nil { + err := ctx.GetDb().View(func(tx *bbolt.Tx) error { + if err := ctx.stores.EdgeRouter.CheckIntegrity(ctx.newViewTestCtx(tx), false, addErrors); err != nil { return nil } - if err := ctx.stores.EdgeRouterPolicy.CheckIntegrity(tx, false, addErrors); err != nil { + if err := ctx.stores.EdgeRouterPolicy.CheckIntegrity(ctx.newViewTestCtx(tx), false, addErrors); err != nil { return nil } @@ -225,14 +226,14 @@ func (ctx *TestContext) testRouterIdentityDeleteTest(t *testing.T) { edgeRouter.IsTunnelerEnabled = false edgeRouter.Name = eid.New() - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) - err = ctx.db.View(func(tx *bbolt.Tx) error { - if err := ctx.stores.EdgeRouter.CheckIntegrity(tx, false, addErrors); err != nil { + err = ctx.GetDb().View(func(tx *bbolt.Tx) error { + if err := ctx.stores.EdgeRouter.CheckIntegrity(ctx.newViewTestCtx(tx), false, addErrors); err != nil { return nil } - if err := ctx.stores.EdgeRouterPolicy.CheckIntegrity(tx, false, addErrors); err != nil { + if err := ctx.stores.EdgeRouterPolicy.CheckIntegrity(ctx.newViewTestCtx(tx), false, addErrors); err != nil { return nil } @@ -249,7 +250,7 @@ func (ctx *TestContext) testRouterIdentityDeleteTest(t *testing.T) { ctx.NoError(err) edgeRouter.IsTunnelerEnabled = true - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) } func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { @@ -270,14 +271,14 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { identities := make([]*Identity, 0) // goland complains of potential nil panic if we use var identities []*Identities for i := 0; i < 5; i++ { identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) } edgeRouters := make([]*EdgeRouter, 0) for i := 0; i < 5; i++ { edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) } @@ -320,34 +321,34 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { // no roles identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) stringz.Permutations(identityRolesAttrs, func(roles []string) { identity := newIdentity(eid.New(), identityTypeId, roles...) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) }) // no roles edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) stringz.Permutations(edgeRouterRoleAttrs, func(roles []string) { edgeRouter := newEdgeRouter(eid.New(), roles...) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) }) ctx.validateEdgeRouterPolicies(identities, edgeRouters, policies) for _, identity := range identities { - ctx.RequireDelete(identity) + boltztest.RequireDelete(ctx, identity) } for _, edgeRouter := range edgeRouters { - ctx.RequireDelete(edgeRouter) + boltztest.RequireDelete(ctx, edgeRouter) } identities = nil @@ -355,17 +356,17 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { stringz.Permutations(identityRolesAttrs, func(roles []string) { identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identity.RoleAttributes = roles - ctx.RequireUpdate(identity) + boltztest.RequireUpdate(ctx, identity) identities = append(identities, identity) }) stringz.Permutations(edgeRouterRoleAttrs, func(roles []string) { edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouter.RoleAttributes = roles - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) }) @@ -373,7 +374,7 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { // ensure policies get cleaned up for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after identities/edge routers @@ -382,7 +383,7 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { ctx.validateEdgeRouterPolicies(identities, edgeRouters, policies) for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after identities/edge routers and roles added after created @@ -393,14 +394,14 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { for _, identity := range identities { if len(identity.RoleAttributes) > 0 { identity.RoleAttributes = identity.RoleAttributes[1:] - ctx.RequireUpdate(identity) + boltztest.RequireUpdate(ctx, identity) } } for _, edgeRouter := range edgeRouters { if len(edgeRouter.RoleAttributes) > 0 { edgeRouter.RoleAttributes = edgeRouter.RoleAttributes[1:] - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) } } @@ -411,7 +412,7 @@ func (ctx *TestContext) testEdgeRouterPolicyRoleEvaluation(t *testing.T) { if len(policy.EdgeRouterRoles) > 0 { policy.EdgeRouterRoles = policy.EdgeRouterRoles[1:] } - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } ctx.validateEdgeRouterPolicies(identities, edgeRouters, policies) @@ -424,7 +425,7 @@ func (ctx *TestContext) createEdgeRouterPolicies(identityRoles, edgeRouterRoles policy.Semantic = SemanticAllOf if !oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } if i == 1 { policy.IdentityRoles = []string{identityRoles[0]} @@ -463,9 +464,9 @@ func (ctx *TestContext) createEdgeRouterPolicies(identityRoles, edgeRouterRoles policies = append(policies, policy) if oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } else { - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } } return policies @@ -501,8 +502,8 @@ func (ctx *TestContext) validateEdgeRouterPolicyIdentities(identities []*Identit func (ctx *TestContext) validateEdgeRouterPolicyDenormalization() { errorHolder := &errorz.ErrorHolderImpl{} - errorHolder.SetError(ctx.db.View(func(tx *bbolt.Tx) error { - return ctx.stores.EdgeRouterPolicy.CheckIntegrity(tx, false, func(err error, _ bool) { + errorHolder.SetError(ctx.GetDb().View(func(tx *bbolt.Tx) error { + return ctx.stores.EdgeRouterPolicy.CheckIntegrity(ctx.newViewTestCtx(tx), false, func(err error, _ bool) { errorHolder.SetError(err) }) })) diff --git a/controller/persistence/edge_router_store.go b/controller/persistence/edge_router_store.go index d87ed92aa..c7a26ab21 100644 --- a/controller/persistence/edge_router_store.go +++ b/controller/persistence/edge_router_store.go @@ -58,49 +58,15 @@ type EdgeRouter struct { AppData map[string]interface{} } -func (entity *EdgeRouter) LoadValues(store boltz.CrudStore, bucket *boltz.TypedBucket) { - _, err := store.GetParentStore().BaseLoadOneById(bucket.Tx(), entity.Id, &entity.Router) - bucket.SetError(err) - - entity.CertPem = bucket.GetString(FieldEdgeRouterCertPEM) - entity.IsVerified = bucket.GetBoolWithDefault(FieldEdgeRouterIsVerified, false) - entity.IsTunnelerEnabled = bucket.GetBoolWithDefault(FieldEdgeRouterIsTunnelerEnabled, entity.IsTunnelerEnabled) - - entity.UnverifiedFingerprint = bucket.GetString(FieldEdgeRouterUnverifiedFingerprint) - entity.UnverifiedCertPem = bucket.GetString(FieldEdgeRouterUnverifiedCertPEM) - - entity.RoleAttributes = bucket.GetStringList(FieldRoleAttributes) - entity.AppData = bucket.GetMap(FieldIdentityAppData) -} - -func (entity *EdgeRouter) SetValues(ctx *boltz.PersistContext) { - entity.Router.SetValues(ctx.GetParentContext()) - - store := ctx.Store.(*edgeRouterStoreImpl) - ctx.SetStringP(FieldEdgeRouterCertPEM, entity.CertPem) - ctx.SetBool(FieldEdgeRouterIsVerified, entity.IsVerified) - store.validateRoleAttributes(entity.RoleAttributes, ctx.Bucket) - ctx.SetStringList(FieldRoleAttributes, entity.RoleAttributes) - ctx.SetBool(FieldEdgeRouterIsTunnelerEnabled, entity.IsTunnelerEnabled) - ctx.Bucket.PutMap(FieldEdgeRouterAppData, entity.AppData, ctx.FieldChecker, false) - - ctx.SetStringP(FieldEdgeRouterUnverifiedFingerprint, entity.UnverifiedFingerprint) - ctx.SetStringP(FieldEdgeRouterUnverifiedCertPEM, entity.UnverifiedCertPem) - - // index change won't fire if we don't have any roles on create, but we need to evaluate if we match any #all roles - if ctx.IsCreate && len(entity.RoleAttributes) == 0 { - store.rolesChanged(ctx.MutateContext, []byte(entity.Id), nil, nil, ctx.Bucket) - } -} - func (entity *EdgeRouter) GetName() string { return entity.Name } +var _ EdgeRouterStore = (*edgeRouterStoreImpl)(nil) + type EdgeRouterStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*EdgeRouter, error) - LoadOneByName(tx *bbolt.Tx, id string) (*EdgeRouter, error) + NameIndexed + Store[*EdgeRouter] GetRoleAttributesIndex() boltz.SetReadIndex GetRoleAttributesCursorProvider(values []string, semantic string) (ast.SetCursorProvider, error) } @@ -114,14 +80,15 @@ func newEdgeRouterStore(stores *stores) *edgeRouterStoreImpl { } store := &edgeRouterStoreImpl{} - stores.Router.AddDeleteHandler(store.cleanupEdgeRouter) // do cleanup first - store.baseStore = newChildBaseStore(stores, stores.Router, parentMapper) + store.baseStore = newChildBaseStore[*EdgeRouter](stores, parentMapper, store, stores.Router, EdgeBucket) store.InitImpl(store) + + stores.Router.RegisterChildStoreStrategy(store) // do cleanup first return store } type edgeRouterStoreImpl struct { - *baseStore + *baseStore[*EdgeRouter] indexName boltz.ReadIndex indexRoleAttributes boltz.SetReadIndex @@ -138,8 +105,25 @@ type edgeRouterStoreImpl struct { servicesCollection boltz.RefCountedLinkCollection } -func (store *edgeRouterStoreImpl) NewStoreEntity() boltz.Entity { - return &EdgeRouter{} +func (store *edgeRouterStoreImpl) HandleUpdate(ctx boltz.MutateContext, entity *db.Router, checker boltz.FieldChecker) (bool, error) { + er, found, err := store.FindById(ctx.Tx(), entity.Id) + if err != nil { + return false, err + } + if !found { + return false, nil + } + + er.Router = *entity + return true, store.Update(ctx, er, checker) +} + +func (store *edgeRouterStoreImpl) HandleDelete(ctx boltz.MutateContext, entity *db.Router) error { + return store.cleanupEdgeRouter(ctx, entity.Id) +} + +func (store *edgeRouterStoreImpl) GetStore() boltz.Store { + return store } func (store *edgeRouterStoreImpl) GetRoleAttributesIndex() boltz.SetReadIndex { @@ -181,6 +165,44 @@ func (store *edgeRouterStoreImpl) initializeLinked() { }) } +func (store *edgeRouterStoreImpl) NewEntity() *EdgeRouter { + return &EdgeRouter{} +} + +func (store *edgeRouterStoreImpl) FillEntity(entity *EdgeRouter, bucket *boltz.TypedBucket) { + store.stores.Router.FillEntity(&entity.Router, store.getParentBucket(entity, bucket)) + + entity.CertPem = bucket.GetString(FieldEdgeRouterCertPEM) + entity.IsVerified = bucket.GetBoolWithDefault(FieldEdgeRouterIsVerified, false) + entity.IsTunnelerEnabled = bucket.GetBoolWithDefault(FieldEdgeRouterIsTunnelerEnabled, entity.IsTunnelerEnabled) + + entity.UnverifiedFingerprint = bucket.GetString(FieldEdgeRouterUnverifiedFingerprint) + entity.UnverifiedCertPem = bucket.GetString(FieldEdgeRouterUnverifiedCertPEM) + + entity.RoleAttributes = bucket.GetStringList(FieldRoleAttributes) + entity.AppData = bucket.GetMap(FieldIdentityAppData) + +} + +func (store *edgeRouterStoreImpl) PersistEntity(entity *EdgeRouter, ctx *boltz.PersistContext) { + store.stores.Router.PersistEntity(&entity.Router, ctx.GetParentContext()) + + ctx.SetStringP(FieldEdgeRouterCertPEM, entity.CertPem) + ctx.SetBool(FieldEdgeRouterIsVerified, entity.IsVerified) + store.validateRoleAttributes(entity.RoleAttributes, ctx.Bucket) + ctx.SetStringList(FieldRoleAttributes, entity.RoleAttributes) + ctx.SetBool(FieldEdgeRouterIsTunnelerEnabled, entity.IsTunnelerEnabled) + ctx.Bucket.PutMap(FieldEdgeRouterAppData, entity.AppData, ctx.FieldChecker, false) + + ctx.SetStringP(FieldEdgeRouterUnverifiedFingerprint, entity.UnverifiedFingerprint) + ctx.SetStringP(FieldEdgeRouterUnverifiedCertPEM, entity.UnverifiedCertPem) + + // index change won't fire if we don't have any roles on create, but we need to evaluate if we match any #all roles + if ctx.IsCreate && len(entity.RoleAttributes) == 0 { + store.rolesChanged(ctx.MutateContext, []byte(entity.Id), nil, nil, ctx.Bucket) + } +} + func (store *edgeRouterStoreImpl) rolesChanged(mutateCtx boltz.MutateContext, rowId []byte, _ []boltz.FieldTypeAndValue, new []boltz.FieldTypeAndValue, holder errorz.ErrorHolder) { // Recalculate edge router policy links ctx := &roleAttributeChangeContext{ @@ -209,28 +231,13 @@ func (store *edgeRouterStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *edgeRouterStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*EdgeRouter, error) { - entity := &EdgeRouter{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *edgeRouterStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*EdgeRouter, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - func (store *edgeRouterStoreImpl) cleanupEdgeRouter(ctx boltz.MutateContext, id string) error { if entity, _ := store.LoadOneById(ctx.Tx(), id); entity != nil { // Remove entity from EdgeRouterRoles in edge router policies if err := store.deleteEntityReferences(ctx.Tx(), entity, store.stores.edgeRouterPolicy.symbolEdgeRouterRoles); err != nil { return err } + // Remove entity from EdgeRouterRoles in service edge router policies if err := store.deleteEntityReferences(ctx.Tx(), entity, store.stores.serviceEdgeRouterPolicy.symbolEdgeRouterRoles); err != nil { return err @@ -353,7 +360,7 @@ func (self *routerIdentityConstraint) deleteAssociatedEntities(ctx *boltz.Indexi func (self *routerIdentityConstraint) Initialize(_ *bbolt.Tx, _ errorz.ErrorHolder) {} -func (self *routerIdentityConstraint) CheckIntegrity(_ *bbolt.Tx, _ bool, _ func(err error, fixed bool)) error { +func (self *routerIdentityConstraint) CheckIntegrity(_ boltz.MutateContext, _ bool, _ func(err error, fixed bool)) error { return nil } diff --git a/controller/persistence/edge_router_store_test.go b/controller/persistence/edge_router_store_test.go index ef5a594a2..3211e4a3a 100644 --- a/controller/persistence/edge_router_store_test.go +++ b/controller/persistence/edge_router_store_test.go @@ -4,7 +4,7 @@ import ( "github.com/google/uuid" "github.com/openziti/fabric/controller/db" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" + "github.com/openziti/storage/boltztest" "testing" ) @@ -28,31 +28,25 @@ func Test_EdgeRouterEvents(t *testing.T) { }, } - err := ctx.db.Update(func(tx *bbolt.Tx) error { - return ctx.stores.EdgeRouter.Create(boltz.NewMutateContext(tx), edgeRouter) - }) - ctx.NoError(err) - eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventCreate) - eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventCreate) + boltztest.RequireCreate(ctx, edgeRouter) + eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityCreated) + eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityCreated) eventChecker.RequireNoEvent() // check events generated by updating from the edge-router store newFp := uuid.NewString() - err = ctx.db.Update(func(tx *bbolt.Tx) error { - edgeRouter.Name = uuid.NewString() - edgeRouter.Fingerprint = &newFp - return ctx.stores.EdgeRouter.Update(boltz.NewMutateContext(tx), edgeRouter, nil) - }) - ctx.NoError(err) + edgeRouter.Name = uuid.NewString() + edgeRouter.Fingerprint = &newFp + boltztest.RequireUpdate(ctx, edgeRouter) - entity := eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventUpdate) + entity := eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityUpdated) r, ok := entity.(*db.Router) ctx.True(ok) ctx.Equal(edgeRouter.Name, r.Name) ctx.NotNil(r.Fingerprint) ctx.Equal(*edgeRouter.Fingerprint, *r.Fingerprint) - entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventUpdate) + entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityUpdated) er, ok := entity.(*EdgeRouter) ctx.True(ok) ctx.Equal(edgeRouter.Name, er.Name) @@ -63,21 +57,18 @@ func Test_EdgeRouterEvents(t *testing.T) { // check events generated by updating from the router store newFp = uuid.NewString() - err = ctx.db.Update(func(tx *bbolt.Tx) error { - edgeRouter.Name = uuid.NewString() - edgeRouter.Fingerprint = &newFp - return ctx.stores.Router.Update(boltz.NewMutateContext(tx), &edgeRouter.Router, nil) - }) - ctx.NoError(err) + edgeRouter.Name = uuid.NewString() + edgeRouter.Fingerprint = &newFp + boltztest.RequireUpdate(ctx, &edgeRouter.Router) - entity = eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventUpdate) + entity = eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityUpdated) r, ok = entity.(*db.Router) ctx.True(ok) ctx.Equal(edgeRouter.Name, r.Name) ctx.NotNil(r.Fingerprint) ctx.Equal(*edgeRouter.Fingerprint, *r.Fingerprint) - entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventUpdate) + entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityUpdated) er, ok = entity.(*EdgeRouter) ctx.True(ok) ctx.Equal(edgeRouter.Name, er.Name) @@ -85,32 +76,26 @@ func Test_EdgeRouterEvents(t *testing.T) { ctx.Equal(*edgeRouter.Fingerprint, *er.Fingerprint) // ensure setting fingerprint to nil works - err = ctx.db.Update(func(tx *bbolt.Tx) error { - edgeRouter.Fingerprint = nil - return ctx.stores.EdgeRouter.Update(boltz.NewMutateContext(tx), edgeRouter, nil) - }) - ctx.NoError(err) + edgeRouter.Fingerprint = nil + boltztest.RequireUpdate(ctx, edgeRouter) - entity = eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventUpdate) + entity = eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityUpdated) r, ok = entity.(*db.Router) ctx.True(ok) ctx.Equal(edgeRouter.Name, r.Name) ctx.Nil(edgeRouter.Fingerprint) ctx.Nil(r.Fingerprint) - entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventUpdate) + entity = eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityUpdated) er, ok = entity.(*EdgeRouter) ctx.True(ok) ctx.Equal(edgeRouter.Name, er.Name) ctx.Nil(er.Fingerprint) // check delete events - err = ctx.db.Update(func(tx *bbolt.Tx) error { - return ctx.stores.EdgeRouter.DeleteById(boltz.NewMutateContext(tx), edgeRouter.Id) - }) - ctx.NoError(err) - eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventDelete) - eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventDelete) + boltztest.RequireDelete(ctx, edgeRouter) + eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityDeleted) + eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityDeleted) eventChecker.RequireNoEvent() // check delete again, this time invoked from the child store @@ -125,19 +110,13 @@ func Test_EdgeRouterEvents(t *testing.T) { }, } - err = ctx.db.Update(func(tx *bbolt.Tx) error { - return ctx.stores.EdgeRouter.Create(boltz.NewMutateContext(tx), edgeRouter) - }) - ctx.NoError(err) - eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventCreate) - eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventCreate) + boltztest.RequireCreate(ctx, edgeRouter) + eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityCreated) + eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityCreated) eventChecker.RequireNoEvent() - err = ctx.db.Update(func(tx *bbolt.Tx) error { - return ctx.stores.Router.DeleteById(boltz.NewMutateContext(tx), edgeRouter.Id) - }) - ctx.NoError(err) - eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EventDelete) - eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EventDelete) + boltztest.RequireDelete(ctx, edgeRouter) + eventChecker.RequireEvent(boltz.TestEntityTypeParent, edgeRouter, boltz.EntityDeleted) + eventChecker.RequireEvent(boltz.TestEntityTypeChild, edgeRouter, boltz.EntityDeleted) eventChecker.RequireNoEvent() } diff --git a/controller/persistence/edge_service_store.go b/controller/persistence/edge_service_store.go index b3af6ef10..3d11c735b 100644 --- a/controller/persistence/edge_service_store.go +++ b/controller/persistence/edge_service_store.go @@ -48,43 +48,12 @@ func newEdgeService(name string, roleAttributes ...string) *EdgeService { } } -func (entity *EdgeService) LoadValues(store boltz.CrudStore, bucket *boltz.TypedBucket) { - _, err := store.GetParentStore().BaseLoadOneById(bucket.Tx(), entity.Id, &entity.Service) - bucket.SetError(err) - - entity.Name = bucket.GetStringOrError(FieldName) - entity.RoleAttributes = bucket.GetStringList(FieldRoleAttributes) - entity.Configs = bucket.GetStringList(EntityTypeConfigs) - - //default to true for old services w/o any value explicitly set - entity.EncryptionRequired = bucket.GetBoolWithDefault(FieldServiceEncryptionRequired, true) -} - -func (entity *EdgeService) SetValues(ctx *boltz.PersistContext) { - entity.Service.SetValues(ctx.GetParentContext()) - - store := ctx.Store.(*edgeServiceStoreImpl) - ctx.SetString(FieldName, entity.Name) - store.validateRoleAttributes(entity.RoleAttributes, ctx.Bucket) - ctx.SetStringList(FieldRoleAttributes, entity.RoleAttributes) - ctx.SetLinkedIds(EntityTypeConfigs, entity.Configs) - ctx.SetBool(FieldServiceEncryptionRequired, entity.EncryptionRequired) - - // index change won't fire if we don't have any roles on create, but we need to evaluate if we match any #all roles - if ctx.IsCreate && len(entity.RoleAttributes) == 0 { - store.rolesChanged(ctx.MutateContext, []byte(entity.Id), nil, nil, ctx.Bucket) - } -} - -func (entity *EdgeService) GetName() string { - return entity.Name -} +var _ EdgeServiceStore = (*edgeServiceStoreImpl)(nil) type EdgeServiceStore interface { - NameIndexedStore + NameIndexed + Store[*EdgeService] - LoadOneById(tx *bbolt.Tx, id string) (*EdgeService, error) - LoadOneByName(tx *bbolt.Tx, id string) (*EdgeService, error) IsBindableByIdentity(tx *bbolt.Tx, id string, identityId string) bool IsDialableByIdentity(tx *bbolt.Tx, id string, identityId string) bool GetRoleAttributesIndex() boltz.SetReadIndex @@ -100,15 +69,16 @@ func newEdgeServiceStore(stores *stores) *edgeServiceStoreImpl { } store := &edgeServiceStoreImpl{} - stores.Service.AddDeleteHandler(store.cleanupEdgeService) - store.baseStore = newChildBaseStore(stores, stores.Service, parentMapper) + store.baseStore = newChildBaseStore[*EdgeService](stores, parentMapper, store, stores.Service, EdgeBucket) store.InitImpl(store) + stores.Service.RegisterChildStoreStrategy(store) + return store } type edgeServiceStoreImpl struct { - *baseStore + *baseStore[*EdgeService] indexName boltz.ReadIndex indexRoleAttributes boltz.SetReadIndex @@ -128,8 +98,25 @@ type edgeServiceStoreImpl struct { edgeRoutersCollection boltz.RefCountedLinkCollection } -func (store *edgeServiceStoreImpl) NewStoreEntity() boltz.Entity { - return &EdgeService{} +func (store *edgeServiceStoreImpl) HandleUpdate(ctx boltz.MutateContext, entity *db.Service, checker boltz.FieldChecker) (bool, error) { + edgeService, found, err := store.FindById(ctx.Tx(), entity.Id) + if err != nil { + return false, err + } + if !found { + return false, nil + } + + edgeService.Service = *entity + return true, store.Update(ctx, edgeService, checker) +} + +func (store *edgeServiceStoreImpl) HandleDelete(ctx boltz.MutateContext, entity *db.Service) error { + return store.cleanupEdgeService(ctx, entity.Id) +} + +func (store *edgeServiceStoreImpl) GetStore() boltz.Store { + return store } func (store *edgeServiceStoreImpl) GetRoleAttributesIndex() boltz.SetReadIndex { @@ -168,6 +155,35 @@ func (store *edgeServiceStoreImpl) initializeLinked() { store.edgeRoutersCollection = store.AddRefCountedLinkCollection(store.symbolEdgeRouters, store.stores.edgeRouter.symbolServices) } +func (self *edgeServiceStoreImpl) NewEntity() *EdgeService { + return &EdgeService{} +} + +func (store *edgeServiceStoreImpl) FillEntity(entity *EdgeService, bucket *boltz.TypedBucket) { + store.stores.Service.FillEntity(&entity.Service, store.getParentBucket(entity, bucket)) + + entity.RoleAttributes = bucket.GetStringList(FieldRoleAttributes) + entity.Configs = bucket.GetStringList(EntityTypeConfigs) + + //default to true for old services w/o any value explicitly set + entity.EncryptionRequired = bucket.GetBoolWithDefault(FieldServiceEncryptionRequired, true) +} + +func (store *edgeServiceStoreImpl) PersistEntity(entity *EdgeService, ctx *boltz.PersistContext) { + store.stores.Service.PersistEntity(&entity.Service, ctx.GetParentContext()) + + ctx.SetString(FieldName, entity.Name) + store.validateRoleAttributes(entity.RoleAttributes, ctx.Bucket) + ctx.SetStringList(FieldRoleAttributes, entity.RoleAttributes) + ctx.SetLinkedIds(EntityTypeConfigs, entity.Configs) + ctx.SetBool(FieldServiceEncryptionRequired, entity.EncryptionRequired) + + // index change won't fire if we don't have any roles on create, but we need to evaluate if we match any #all roles + if ctx.IsCreate && len(entity.RoleAttributes) == 0 { + store.rolesChanged(ctx.MutateContext, []byte(entity.Id), nil, nil, ctx.Bucket) + } +} + func (store *edgeServiceStoreImpl) rolesChanged(mutateCtx boltz.MutateContext, rowId []byte, _ []boltz.FieldTypeAndValue, new []boltz.FieldTypeAndValue, holder errorz.ErrorHolder) { // Recalculate service policy links ctx := &roleAttributeChangeContext{ @@ -195,31 +211,7 @@ func (store *edgeServiceStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *edgeServiceStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*EdgeService, error) { - entity := &EdgeService{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *edgeServiceStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*EdgeService, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - -func (store *edgeServiceStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*EdgeService, error) { - entity := &EdgeService{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} - -func (store *edgeServiceStoreImpl) Update(ctx boltz.MutateContext, entity boltz.Entity, checker boltz.FieldChecker) error { +func (store *edgeServiceStoreImpl) Update(ctx boltz.MutateContext, entity *EdgeService, checker boltz.FieldChecker) error { if result := store.baseStore.Update(ctx, entity, checker); result != nil { return result } diff --git a/controller/persistence/edge_service_store_test.go b/controller/persistence/edge_service_store_test.go index 64719bc63..b04b88bb0 100644 --- a/controller/persistence/edge_service_store_test.go +++ b/controller/persistence/edge_service_store_test.go @@ -19,7 +19,9 @@ package persistence import ( "fmt" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/db" + "github.com/openziti/storage/boltztest" "testing" "time" @@ -48,7 +50,7 @@ func (ctx *TestContext) testServiceParentChild(_ *testing.T) { Name: eid.New(), } - ctx.RequireCreate(fabricService) + boltztest.RequireCreate(ctx, fabricService) err := ctx.GetDb().View(func(tx *bbolt.Tx) error { ctx.False(ctx.stores.EdgeService.IsEntityPresent(tx, fabricService.GetId())) @@ -65,7 +67,7 @@ func (ctx *TestContext) testServiceParentChild(_ *testing.T) { // Supporting extending a base type gets complicated with lower level indexes, since you're mixing an update // in the parent with a create in the child. Not worth fixing right now - ctx.Error(ctx.Update(edgeService)) + ctx.Error(boltztest.Update(ctx, edgeService)) // //err = ctx.GetDb().View(func(tx *bbolt.Tx) error { // query := fmt.Sprintf(`id = "%v" and name = "%v"`, fabricService.Id, edgeService.Name) @@ -85,7 +87,7 @@ func (ctx *TestContext) testCreateInvalidServices(_ *testing.T) { identity := ctx.RequireNewIdentity("test-user", false) apiSession := NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) edgeService := &EdgeService{ Service: db.Service{ @@ -94,18 +96,18 @@ func (ctx *TestContext) testCreateInvalidServices(_ *testing.T) { }, } - ctx.RequireCreate(edgeService) - err := ctx.Create(edgeService) + boltztest.RequireCreate(ctx, edgeService) + err := boltztest.Create(ctx, edgeService) ctx.EqualError(err, fmt.Sprintf("an entity of type service already exists with id %v", edgeService.Id)) edgeService.Id = eid.New() - err = ctx.Create(edgeService) + err = boltztest.Create(ctx, edgeService) ctx.EqualError(err, fmt.Sprintf("duplicate value '%v' in unique index on services store", edgeService.Name)) edgeService.Id = eid.New() edgeService.Name = eid.New() edgeService.TerminatorStrategy = eid.New() - err = ctx.Create(edgeService) + err = boltztest.Create(ctx, edgeService) ctx.EqualError(err, fmt.Sprintf("terminatorStrategy with name %v not found", edgeService.TerminatorStrategy)) } @@ -118,8 +120,8 @@ func (ctx *TestContext) testCreateServices(_ *testing.T) { Name: eid.New(), }, } - ctx.RequireCreate(edgeService) - ctx.ValidateBaseline(edgeService) + boltztest.RequireCreate(ctx, edgeService) + boltztest.ValidateBaseline(ctx, edgeService) } type serviceTestEntities struct { @@ -139,7 +141,7 @@ func (ctx *TestContext) createServiceTestEntities() *serviceTestEntities { role := eid.New() - ctx.RequireCreate(apiSession1) + boltztest.RequireCreate(ctx, apiSession1) servicePolicy := ctx.requireNewServicePolicy(PolicyTypeDial, ss(), ss(roleRef(role))) service1 := &EdgeService{ @@ -150,18 +152,18 @@ func (ctx *TestContext) createServiceTestEntities() *serviceTestEntities { RoleAttributes: []string{role}, } - ctx.RequireCreate(service1) + boltztest.RequireCreate(ctx, service1) service2 := ctx.RequireNewService(eid.New()) service2.Tags = map[string]interface{}{ "location": "NY", } - ctx.RequireUpdate(service2) + boltztest.RequireUpdate(ctx, service2) session1 := NewSession(apiSession1.Id, service1.Id) - ctx.RequireCreate(session1) + boltztest.RequireCreate(ctx, session1) session2 := NewSession(apiSession1.Id, service2.Id) - ctx.RequireCreate(session2) + boltztest.RequireCreate(ctx, session2) return &serviceTestEntities{ servicePolicy: servicePolicy, @@ -185,11 +187,6 @@ func (ctx *TestContext) testLoadQueryServices(_ *testing.T) { ctx.NotNil(service) ctx.EqualValues(entities.service1.Id, service.Id) - service, err = ctx.stores.EdgeService.LoadOneByName(tx, entities.service1.Name) - ctx.NoError(err) - ctx.NotNil(service) - ctx.EqualValues(entities.service1.Id, service.Id) - query := fmt.Sprintf(`anyOf(servicePolicies) = "%v"`, entities.servicePolicy.Id) ids, _, err := ctx.stores.EdgeService.QueryIds(tx, query) ctx.NoError(err) @@ -218,7 +215,9 @@ func (ctx *TestContext) testUpdateServices(_ *testing.T) { earlier := time.Now() time.Sleep(time.Millisecond * 50) - err := ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx := change.New().SetSource("test").NewMutateContext() + err := ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() original, err := ctx.stores.EdgeService.LoadOneById(tx, entities.service1.Id) ctx.NoError(err) ctx.NotNil(original) @@ -234,7 +233,7 @@ func (ctx *TestContext) testUpdateServices(_ *testing.T) { service.CreatedAt = now service.Tags = tags - err = ctx.stores.EdgeService.Update(boltz.NewMutateContext(tx), service, nil) + err = ctx.stores.EdgeService.Update(mutateCtx, service, nil) ctx.NoError(err) loaded, err := ctx.stores.EdgeService.LoadOneById(tx, entities.service1.Id) ctx.NoError(err) @@ -252,6 +251,6 @@ func (ctx *TestContext) testUpdateServices(_ *testing.T) { func (ctx *TestContext) testDeleteServices(_ *testing.T) { ctx.CleanupAll() entities := ctx.createServiceTestEntities() - ctx.RequireDelete(entities.service1, apiSessionsSessionsIdxPath) - ctx.RequireDelete(entities.service2, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, entities.service1, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, entities.service2, apiSessionsSessionsIdxPath) } diff --git a/controller/persistence/enrollment_store.go b/controller/persistence/enrollment_store.go index a9fefd94e..42c1fcab9 100644 --- a/controller/persistence/enrollment_store.go +++ b/controller/persistence/enrollment_store.go @@ -55,62 +55,33 @@ type Enrollment struct { Jwt string } +func (entity *Enrollment) GetEntityType() string { + return EntityTypeEnrollments +} + var enrollmentFieldMappings = map[string]string{ FieldEnrollIdentity: "identityId", FieldEnrollEdgeRouter: "edgeRouterId", FieldEnrollTransitRouter: "transitRouterId", } -func (entity *Enrollment) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.Token = bucket.GetStringWithDefault(FieldEnrollmentToken, "") - entity.Method = bucket.GetStringWithDefault(FieldEnrollmentMethod, "") - entity.IdentityId = bucket.GetString(FieldEnrollIdentity) - entity.EdgeRouterId = bucket.GetString(FieldEnrollEdgeRouter) - entity.TransitRouterId = bucket.GetString(FieldEnrollTransitRouter) - entity.ExpiresAt = bucket.GetTime(FieldEnrollmentExpiresAt) - entity.IssuedAt = bucket.GetTime(FieldEnrollmentIssuedAt) - entity.CaId = bucket.GetString(FieldEnrollmentCaId) - entity.Username = bucket.GetString(FieldEnrollmentUsername) - entity.Jwt = bucket.GetStringOrError(FieldEnrollmentJwt) -} - -func (entity *Enrollment) SetValues(ctx *boltz.PersistContext) { - ctx.WithFieldOverrides(enrollmentFieldMappings) - - ctx.SetString(FieldEnrollmentToken, entity.Token) - ctx.SetString(FieldEnrollmentMethod, entity.Method) - ctx.SetTimeP(FieldEnrollmentExpiresAt, entity.ExpiresAt) - ctx.SetStringP(FieldEnrollIdentity, entity.IdentityId) - ctx.SetStringP(FieldEnrollEdgeRouter, entity.EdgeRouterId) - ctx.SetStringP(FieldEnrollTransitRouter, entity.TransitRouterId) - ctx.SetStringP(FieldEnrollmentCaId, entity.CaId) - ctx.SetStringP(FieldEnrollmentUsername, entity.Username) - ctx.SetTimeP(FieldEnrollmentIssuedAt, entity.IssuedAt) - ctx.SetString(FieldEnrollmentJwt, entity.Jwt) -} - -func (entity *Enrollment) GetEntityType() string { - return EntityTypeEnrollments -} +var _ EnrollmentStore = (*enrollmentStoreImpl)(nil) type EnrollmentStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*Enrollment, error) + Store[*Enrollment] LoadOneByToken(tx *bbolt.Tx, token string) (*Enrollment, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*Enrollment, error) } func newEnrollmentStore(stores *stores) *enrollmentStoreImpl { - store := &enrollmentStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeEnrollments), - } + store := &enrollmentStoreImpl{} + store.baseStore = newBaseStore[*Enrollment](stores, store) store.InitImpl(store) return store } type enrollmentStoreImpl struct { - *baseStore + *baseStore[*Enrollment] tokenIndex boltz.ReadIndex symbolIdentity boltz.EntitySymbol symbolEdgeRouter boltz.EntitySymbol @@ -118,10 +89,6 @@ type enrollmentStoreImpl struct { symbolCa boltz.EntitySymbol } -func (store *enrollmentStoreImpl) NewStoreEntity() boltz.Entity { - return &Enrollment{} -} - func (store *enrollmentStoreImpl) initializeLocal() { store.AddExtEntitySymbols() @@ -140,12 +107,36 @@ func (store *enrollmentStoreImpl) initializeLinked() { store.AddNullableFkIndex(store.symbolCa, store.stores.ca.symbolEnrollments) } -func (store *enrollmentStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Enrollment, error) { - entity := &Enrollment{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *enrollmentStoreImpl) NewEntity() *Enrollment { + return &Enrollment{} +} + +func (store *enrollmentStoreImpl) FillEntity(entity *Enrollment, bucket *boltz.TypedBucket) { + entity.Token = bucket.GetStringWithDefault(FieldEnrollmentToken, "") + entity.Method = bucket.GetStringWithDefault(FieldEnrollmentMethod, "") + entity.IdentityId = bucket.GetString(FieldEnrollIdentity) + entity.EdgeRouterId = bucket.GetString(FieldEnrollEdgeRouter) + entity.TransitRouterId = bucket.GetString(FieldEnrollTransitRouter) + entity.ExpiresAt = bucket.GetTime(FieldEnrollmentExpiresAt) + entity.IssuedAt = bucket.GetTime(FieldEnrollmentIssuedAt) + entity.CaId = bucket.GetString(FieldEnrollmentCaId) + entity.Username = bucket.GetString(FieldEnrollmentUsername) + entity.Jwt = bucket.GetStringOrError(FieldEnrollmentJwt) +} + +func (store *enrollmentStoreImpl) PersistEntity(entity *Enrollment, ctx *boltz.PersistContext) { + ctx.WithFieldOverrides(enrollmentFieldMappings) + + ctx.SetString(FieldEnrollmentToken, entity.Token) + ctx.SetString(FieldEnrollmentMethod, entity.Method) + ctx.SetTimeP(FieldEnrollmentExpiresAt, entity.ExpiresAt) + ctx.SetStringP(FieldEnrollIdentity, entity.IdentityId) + ctx.SetStringP(FieldEnrollEdgeRouter, entity.EdgeRouterId) + ctx.SetStringP(FieldEnrollTransitRouter, entity.TransitRouterId) + ctx.SetStringP(FieldEnrollmentCaId, entity.CaId) + ctx.SetStringP(FieldEnrollmentUsername, entity.Username) + ctx.SetTimeP(FieldEnrollmentIssuedAt, entity.IssuedAt) + ctx.SetString(FieldEnrollmentJwt, entity.Jwt) } func (store *enrollmentStoreImpl) LoadOneByToken(tx *bbolt.Tx, token string) (*Enrollment, error) { @@ -155,11 +146,3 @@ func (store *enrollmentStoreImpl) LoadOneByToken(tx *bbolt.Tx, token string) (*E } return nil, nil } - -func (store *enrollmentStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*Enrollment, error) { - entity := &Enrollment{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} diff --git a/controller/persistence/eventual_event_store.go b/controller/persistence/eventual_event_store.go index 35ab639dc..23324881b 100644 --- a/controller/persistence/eventual_event_store.go +++ b/controller/persistence/eventual_event_store.go @@ -19,7 +19,6 @@ package persistence import ( "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -33,59 +32,25 @@ type EventualEvent struct { Data []byte } -func (entity *EventualEvent) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Type = bucket.GetStringOrError(FieldEventualEventType) - entity.Data = bucket.Get([]byte(FieldEventualEventData)) - -} - -func (entity *EventualEvent) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldEventualEventType, entity.Type) - ctx.Bucket.SetError(ctx.Bucket.Put([]byte(FieldEventualEventData), entity.Data)) -} - func (entity *EventualEvent) GetEntityType() string { return EntityTypeEventualEvents } +var _ EventualEventStore = (*eventualEventStoreImpl)(nil) + type EventualEventStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*EventualEvent, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*EventualEvent, error) + Store[*EventualEvent] } func newEventualEventStore(stores *stores) *eventualEventStoreImpl { - store := &eventualEventStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeEventualEvents), - } + store := &eventualEventStoreImpl{} + store.baseStore = newBaseStore[*EventualEvent](stores, store) store.InitImpl(store) return store } type eventualEventStoreImpl struct { - *baseStore -} - -func (store *eventualEventStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*EventualEvent, error) { - entity := &EventualEvent{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *eventualEventStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*EventualEvent, error) { - entity := &EventualEvent{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} - -func (store *eventualEventStoreImpl) NewStoreEntity() boltz.Entity { - return &EventualEvent{} + *baseStore[*EventualEvent] } func (store *eventualEventStoreImpl) initializeLocal() { @@ -93,5 +58,20 @@ func (store *eventualEventStoreImpl) initializeLocal() { store.AddSymbol(FieldEventualEventData, ast.NodeTypeOther) } -func (store *eventualEventStoreImpl) initializeLinked() { +func (store *eventualEventStoreImpl) initializeLinked() {} + +func (store *eventualEventStoreImpl) NewEntity() *EventualEvent { + return &EventualEvent{} +} + +func (store *eventualEventStoreImpl) FillEntity(entity *EventualEvent, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Type = bucket.GetStringOrError(FieldEventualEventType) + entity.Data = bucket.Get([]byte(FieldEventualEventData)) +} + +func (store *eventualEventStoreImpl) PersistEntity(entity *EventualEvent, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldEventualEventType, entity.Type) + ctx.Bucket.SetError(ctx.Bucket.Put([]byte(FieldEventualEventData), entity.Data)) } diff --git a/controller/persistence/eventual_eventer.go b/controller/persistence/eventual_eventer.go index 02857cef9..885f8785b 100644 --- a/controller/persistence/eventual_eventer.go +++ b/controller/persistence/eventual_eventer.go @@ -21,6 +21,7 @@ import ( "github.com/kataras/go-events" "github.com/lucsky/cuid" "github.com/michaelquigley/pfxlog" + "github.com/openziti/fabric/controller/change" "github.com/openziti/storage/boltz" cmap "github.com/orcaman/concurrent-map/v2" "github.com/pkg/errors" @@ -347,8 +348,8 @@ func (a *EventualEventerBbolt) AddEventualEventWithCtx(ctx boltz.MutateContext, var err error if ctx == nil { - err = a.dbProvider.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) + ctx = change.New().SetSource("eventual.eventer").SetChangeAuthorType("controller").NewMutateContext() + err = a.dbProvider.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { return a.store.Create(ctx, event) }) } else { @@ -437,8 +438,8 @@ func (a *EventualEventerBbolt) Trigger() (<-chan struct{}, error) { // deleteEventualEvent removes an eventual event by id from the bbolt backend store. func (a *EventualEventerBbolt) deleteEventualEvent(id string) error { - err := a.dbProvider.GetDb().Update(func(tx *bbolt.Tx) error { - ctx := boltz.NewMutateContext(tx) + ctx := change.New().SetSource("eventual.eventer").SetChangeAuthorType("controller").NewMutateContext() + err := a.dbProvider.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { return a.store.DeleteById(ctx, id) }) diff --git a/controller/persistence/external_jwt_signer_store.go b/controller/persistence/external_jwt_signer_store.go index 1b1e6d7a7..b507fbe15 100644 --- a/controller/persistence/external_jwt_signer_store.go +++ b/controller/persistence/external_jwt_signer_store.go @@ -22,7 +22,6 @@ import ( "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" "strings" "time" ) @@ -68,7 +67,68 @@ func (entity *ExternalJwtSigner) GetName() string { return entity.Name } -func (entity *ExternalJwtSigner) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *ExternalJwtSigner) GetEntityType() string { + return EntityTypeExternalJwtSigners +} + +var _ ExternalJwtSignerStore = (*externalJwtSignerStoreImpl)(nil) + +type ExternalJwtSignerStore interface { + Store[*ExternalJwtSigner] +} + +func newExternalJwtSignerStore(stores *stores) *externalJwtSignerStoreImpl { + store := &externalJwtSignerStoreImpl{} + store.baseStore = newBaseStore[*ExternalJwtSigner](stores, store) + store.InitImpl(store) + return store +} + +type externalJwtSignerStoreImpl struct { + *baseStore[*ExternalJwtSigner] + indexName boltz.ReadIndex + symbolFingerprint boltz.EntitySymbol + symbolAuthPolicies boltz.EntitySetSymbol + fingerprintIndex boltz.ReadIndex + symbolKid boltz.EntitySymbol + kidIndex boltz.ReadIndex + symbolIssuer boltz.EntitySymbol + issuerIndex boltz.ReadIndex +} + +func (store *externalJwtSignerStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + store.indexName = store.addUniqueNameField() + + store.symbolFingerprint = store.AddSymbol(FieldExternalJwtSignerFingerprint, ast.NodeTypeString) + store.fingerprintIndex = store.AddNullableUniqueIndex(store.symbolFingerprint) + + store.symbolKid = store.AddSymbol(FieldExternalJwtSignerKid, ast.NodeTypeString) + store.kidIndex = store.AddNullableUniqueIndex(store.symbolKid) + + store.symbolIssuer = store.AddSymbol(FieldExternalJwtSignerIssuer, ast.NodeTypeString) + store.issuerIndex = store.AddUniqueIndex(store.symbolIssuer) + + store.AddSymbol(FieldExternalJwtSignerCertPem, ast.NodeTypeString) + store.AddSymbol(FieldExternalJwtSignerCommonName, ast.NodeTypeString) + store.AddSymbol(FieldExternalJwtSignerNotAfter, ast.NodeTypeDatetime) + store.AddSymbol(FieldExternalJwtSignerNotBefore, ast.NodeTypeDatetime) + store.AddSymbol(FieldExternalJwtSignerEnabled, ast.NodeTypeBool) + store.AddSymbol(FieldExternalJwtSignerClaimsProperty, ast.NodeTypeString) + store.AddSymbol(FieldExternalJwtSignerUseExternalId, ast.NodeTypeBool) + store.AddSymbol(FieldExternalJwtSignerAudience, ast.NodeTypeString) + + store.symbolAuthPolicies = store.AddFkSetSymbol(FieldExternalJwtSignerAuthPolicies, store.stores.authPolicy) +} + +func (store *externalJwtSignerStoreImpl) initializeLinked() { +} + +func (store *externalJwtSignerStoreImpl) NewEntity() *ExternalJwtSigner { + return &ExternalJwtSigner{} +} + +func (store *externalJwtSignerStoreImpl) FillEntity(entity *ExternalJwtSigner, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringWithDefault(FieldName, "") entity.CertPem = bucket.GetString(FieldExternalJwtSignerCertPem) @@ -86,7 +146,7 @@ func (entity *ExternalJwtSigner) LoadValues(_ boltz.CrudStore, bucket *boltz.Typ entity.Audience = bucket.GetString(FieldExternalJwtSignerAudience) } -func (entity *ExternalJwtSigner) SetValues(ctx *boltz.PersistContext) { +func (store *externalJwtSignerStoreImpl) PersistEntity(entity *ExternalJwtSigner, ctx *boltz.PersistContext) { entity.SetBaseValues(ctx) ctx.SetString(FieldName, entity.Name) ctx.SetStringP(FieldExternalJwtSignerCertPem, entity.CertPem) @@ -128,102 +188,11 @@ func (entity *ExternalJwtSigner) SetValues(ctx *boltz.PersistContext) { } if jwksEndpoint != nil && certPem != nil { - existingName := FieldExternalJwtSignerCertPem - existingValue := certPem - if jwksEndpoint != nil { - existingName = FieldExternalJwtSignerJwksEndpoint - existingValue = jwksEndpoint - } - ctx.Bucket.SetError(apierror.NewBadRequestFieldError(*errorz.NewFieldError("only one of jwksEndpoint or certPem may be defined", existingName, existingValue))) + ctx.Bucket.SetError(apierror.NewBadRequestFieldError( + *errorz.NewFieldError("only one of jwksEndpoint or certPem may be defined", FieldExternalJwtSignerJwksEndpoint, jwksEndpoint))) } } -func (entity *ExternalJwtSigner) GetEntityType() string { - return EntityTypeExternalJwtSigners -} - -type ExternalJwtSignerStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*ExternalJwtSigner, error) - LoadOneByName(tx *bbolt.Tx, id string) (*ExternalJwtSigner, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*ExternalJwtSigner, error) -} - -func newExternalJwtSignerStore(stores *stores) *externalJwtSignerStoreImpl { - store := &externalJwtSignerStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeExternalJwtSigners), - } - store.InitImpl(store) - return store -} - -type externalJwtSignerStoreImpl struct { - *baseStore - indexName boltz.ReadIndex - symbolFingerprint boltz.EntitySymbol - symbolAuthPolicies boltz.EntitySetSymbol - fingerprintIndex boltz.ReadIndex - symbolKid boltz.EntitySymbol - kidIndex boltz.ReadIndex - symbolIssuer boltz.EntitySymbol - issuerIndex boltz.ReadIndex -} - -func (store *externalJwtSignerStoreImpl) NewStoreEntity() boltz.Entity { - return &ExternalJwtSigner{} -} - -func (store *externalJwtSignerStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - store.indexName = store.addUniqueNameField() - - store.symbolFingerprint = store.AddSymbol(FieldExternalJwtSignerFingerprint, ast.NodeTypeString) - store.fingerprintIndex = store.AddNullableUniqueIndex(store.symbolFingerprint) - - store.symbolKid = store.AddSymbol(FieldExternalJwtSignerKid, ast.NodeTypeString) - store.kidIndex = store.AddNullableUniqueIndex(store.symbolKid) - - store.symbolIssuer = store.AddSymbol(FieldExternalJwtSignerIssuer, ast.NodeTypeString) - store.issuerIndex = store.AddUniqueIndex(store.symbolIssuer) - - store.AddSymbol(FieldExternalJwtSignerCertPem, ast.NodeTypeString) - store.AddSymbol(FieldExternalJwtSignerCommonName, ast.NodeTypeString) - store.AddSymbol(FieldExternalJwtSignerNotAfter, ast.NodeTypeDatetime) - store.AddSymbol(FieldExternalJwtSignerNotBefore, ast.NodeTypeDatetime) - store.AddSymbol(FieldExternalJwtSignerEnabled, ast.NodeTypeBool) - store.AddSymbol(FieldExternalJwtSignerClaimsProperty, ast.NodeTypeString) - store.AddSymbol(FieldExternalJwtSignerUseExternalId, ast.NodeTypeBool) - store.AddSymbol(FieldExternalJwtSignerAudience, ast.NodeTypeString) - - store.symbolAuthPolicies = store.AddFkSetSymbol(FieldExternalJwtSignerAuthPolicies, store.stores.authPolicy) -} - -func (store *externalJwtSignerStoreImpl) initializeLinked() { -} - -func (store *externalJwtSignerStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ExternalJwtSigner, error) { - entity := &ExternalJwtSigner{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *externalJwtSignerStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*ExternalJwtSigner, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - -func (store *externalJwtSignerStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*ExternalJwtSigner, error) { - entity := &ExternalJwtSigner{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} func (store *externalJwtSignerStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { ids, _, err := store.stores.authPolicy.QueryIds(ctx.Tx(), fmt.Sprintf(`anyOf(%s) = "%s"`, FieldAuthPolicyPrimaryExtJwtAllowedSigners, id)) diff --git a/controller/persistence/identity_store.go b/controller/persistence/identity_store.go index dfcccd5cb..dea9a47da 100644 --- a/controller/persistence/identity_store.go +++ b/controller/persistence/identity_store.go @@ -110,6 +110,14 @@ type Identity struct { Disabled bool } +func (entity *Identity) GetEntityType() string { + return EntityTypeIdentities +} + +func (entity *Identity) GetName() string { + return entity.Name +} + type ServiceConfig struct { ServiceId string ConfigId string @@ -117,7 +125,100 @@ type ServiceConfig struct { var identityFieldMappings = map[string]string{FieldIdentityType: "identityTypeId"} -func (entity *Identity) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +var _ IdentityStore = (*identityStoreImpl)(nil) + +type IdentityStore interface { + NameIndexed + Store[*Identity] + + GetRoleAttributesIndex() boltz.SetReadIndex + GetRoleAttributesCursorProvider(values []string, semantic string) (ast.SetCursorProvider, error) + + AssignServiceConfigs(tx *bbolt.Tx, identityId string, serviceConfigs ...ServiceConfig) error + RemoveServiceConfigs(tx *bbolt.Tx, identityId string, serviceConfigs ...ServiceConfig) error + GetServiceConfigs(tx *bbolt.Tx, identityId string) ([]ServiceConfig, error) + LoadServiceConfigsByServiceAndType(tx *bbolt.Tx, identityId string, configTypes map[string]struct{}) map[string]map[string]map[string]interface{} + GetIdentityServicesCursorProvider(identityId string) ast.SetCursorProvider +} + +func newIdentityStore(stores *stores) *identityStoreImpl { + store := &identityStoreImpl{} + store.baseStore = newBaseStore[*Identity](stores, store) + store.InitImpl(store) + return store +} + +type identityStoreImpl struct { + *baseStore[*Identity] + + indexName boltz.ReadIndex + indexRoleAttributes boltz.SetReadIndex + + symbolRoleAttributes boltz.EntitySetSymbol + symbolAuthenticators boltz.EntitySetSymbol + symbolIdentityTypeId boltz.EntitySymbol + symbolAuthPolicyId boltz.EntitySymbol + symbolEnrollments boltz.EntitySetSymbol + + symbolEdgeRouterPolicies boltz.EntitySetSymbol + symbolServicePolicies boltz.EntitySetSymbol + symbolEdgeRouters boltz.EntitySetSymbol + symbolBindServices boltz.EntitySetSymbol + symbolDialServices boltz.EntitySetSymbol + + edgeRoutersCollection boltz.RefCountedLinkCollection + bindServicesCollection boltz.RefCountedLinkCollection + dialServicesCollection boltz.RefCountedLinkCollection + symbolExternalId boltz.EntitySymbol + externalIdIndex boltz.ReadIndex +} + +func (store *identityStoreImpl) GetRoleAttributesIndex() boltz.SetReadIndex { + return store.indexRoleAttributes +} + +func (store *identityStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + + store.symbolRoleAttributes = store.AddPublicSetSymbol(FieldRoleAttributes, ast.NodeTypeString) + store.indexRoleAttributes = store.AddSetIndex(store.symbolRoleAttributes) + + store.indexName = store.addUniqueNameField() + store.symbolEdgeRouters = store.AddFkSetSymbol(db.EntityTypeRouters, store.stores.edgeRouter) + store.symbolBindServices = store.AddFkSetSymbol(FieldIdentityBindServices, store.stores.edgeService) + store.symbolDialServices = store.AddFkSetSymbol(FieldIdentityDialServices, store.stores.edgeService) + store.symbolEdgeRouterPolicies = store.AddFkSetSymbol(EntityTypeEdgeRouterPolicies, store.stores.edgeRouterPolicy) + store.symbolServicePolicies = store.AddFkSetSymbol(EntityTypeServicePolicies, store.stores.servicePolicy) + store.symbolEnrollments = store.AddFkSetSymbol(FieldIdentityEnrollments, store.stores.enrollment) + store.symbolAuthenticators = store.AddFkSetSymbol(FieldIdentityAuthenticators, store.stores.authenticator) + store.symbolExternalId = store.AddSymbol(FieldIdentityExternalId, ast.NodeTypeString) + store.externalIdIndex = store.AddNullableUniqueIndex(store.symbolExternalId) + + store.symbolIdentityTypeId = store.AddFkSymbol(FieldIdentityType, store.stores.identityType) + store.symbolAuthPolicyId = store.AddFkSymbol(FieldIdentityAuthPolicyId, store.stores.authPolicy) + + store.AddFkConstraint(store.symbolAuthPolicyId, true, boltz.CascadeNone) + + store.AddSymbol(FieldIdentityIsAdmin, ast.NodeTypeBool) + store.AddSymbol(FieldIdentityIsDefaultAdmin, ast.NodeTypeBool) + + store.indexRoleAttributes.AddListener(store.rolesChanged) +} + +func (store *identityStoreImpl) initializeLinked() { + store.AddLinkCollection(store.symbolEdgeRouterPolicies, store.stores.edgeRouterPolicy.symbolIdentities) + store.AddLinkCollection(store.symbolServicePolicies, store.stores.servicePolicy.symbolIdentities) + + store.edgeRoutersCollection = store.AddRefCountedLinkCollection(store.symbolEdgeRouters, store.stores.edgeRouter.symbolIdentities) + store.bindServicesCollection = store.AddRefCountedLinkCollection(store.symbolBindServices, store.stores.edgeService.symbolBindIdentities) + store.dialServicesCollection = store.AddRefCountedLinkCollection(store.symbolDialServices, store.stores.edgeService.symbolDialIdentities) +} + +func (store *identityStoreImpl) NewEntity() *Identity { + return &Identity{} +} + +func (store *identityStoreImpl) FillEntity(entity *Identity, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) entity.IdentityTypeId = bucket.GetStringWithDefault(FieldIdentityType, "") @@ -169,12 +270,11 @@ func (entity *Identity) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) } } -func (entity *Identity) SetValues(ctx *boltz.PersistContext) { +func (store *identityStoreImpl) PersistEntity(entity *Identity, ctx *boltz.PersistContext) { ctx.WithFieldOverrides(identityFieldMappings) entity.SetBaseValues(ctx) - store := ctx.Store.(*identityStoreImpl) ctx.SetString(FieldName, entity.Name) ctx.SetBool(FieldIdentityIsDefaultAdmin, entity.IsDefaultAdmin) ctx.SetBool(FieldIdentityIsAdmin, entity.IsAdmin) @@ -218,7 +318,7 @@ func (entity *Identity) SetValues(ctx *boltz.PersistContext) { ctx.SetString(FieldIdentitySdkInfoAppVersion, entity.SdkInfo.AppVersion) } - serviceStore := ctx.Store.(*identityStoreImpl).stores.Service + serviceStore := store.stores.Service if ctx.ProceedWithSet(FieldIdentityServiceHostingPrecedences) { mapBucket, err := ctx.Bucket.EmptyBucket(FieldIdentityServiceHostingPrecedences) @@ -255,107 +355,6 @@ func (entity *Identity) SetValues(ctx *boltz.PersistContext) { } } -func (entity *Identity) GetEntityType() string { - return EntityTypeIdentities -} - -func (entity *Identity) GetName() string { - return entity.Name -} - -type IdentityStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*Identity, error) - LoadOneByName(tx *bbolt.Tx, id string) (*Identity, error) - - GetRoleAttributesIndex() boltz.SetReadIndex - GetRoleAttributesCursorProvider(values []string, semantic string) (ast.SetCursorProvider, error) - - AssignServiceConfigs(tx *bbolt.Tx, identityId string, serviceConfigs ...ServiceConfig) error - RemoveServiceConfigs(tx *bbolt.Tx, identityId string, serviceConfigs ...ServiceConfig) error - GetServiceConfigs(tx *bbolt.Tx, identityId string) ([]ServiceConfig, error) - LoadServiceConfigsByServiceAndType(tx *bbolt.Tx, identityId string, configTypes map[string]struct{}) map[string]map[string]map[string]interface{} - GetIdentityServicesCursorProvider(identityId string) ast.SetCursorProvider -} - -func newIdentityStore(stores *stores) *identityStoreImpl { - store := &identityStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeIdentities), - } - store.InitImpl(store) - return store -} - -type identityStoreImpl struct { - *baseStore - - indexName boltz.ReadIndex - indexRoleAttributes boltz.SetReadIndex - - symbolRoleAttributes boltz.EntitySetSymbol - symbolAuthenticators boltz.EntitySetSymbol - symbolIdentityTypeId boltz.EntitySymbol - symbolAuthPolicyId boltz.EntitySymbol - symbolEnrollments boltz.EntitySetSymbol - - symbolEdgeRouterPolicies boltz.EntitySetSymbol - symbolServicePolicies boltz.EntitySetSymbol - symbolEdgeRouters boltz.EntitySetSymbol - symbolBindServices boltz.EntitySetSymbol - symbolDialServices boltz.EntitySetSymbol - - edgeRoutersCollection boltz.RefCountedLinkCollection - bindServicesCollection boltz.RefCountedLinkCollection - dialServicesCollection boltz.RefCountedLinkCollection - symbolExternalId boltz.EntitySymbol - externalIdIndex boltz.ReadIndex -} - -func (store *identityStoreImpl) NewStoreEntity() boltz.Entity { - return &Identity{} -} - -func (store *identityStoreImpl) GetRoleAttributesIndex() boltz.SetReadIndex { - return store.indexRoleAttributes -} - -func (store *identityStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - - store.symbolRoleAttributes = store.AddPublicSetSymbol(FieldRoleAttributes, ast.NodeTypeString) - store.indexRoleAttributes = store.AddSetIndex(store.symbolRoleAttributes) - - store.indexName = store.addUniqueNameField() - store.symbolEdgeRouters = store.AddFkSetSymbol(db.EntityTypeRouters, store.stores.edgeRouter) - store.symbolBindServices = store.AddFkSetSymbol(FieldIdentityBindServices, store.stores.edgeService) - store.symbolDialServices = store.AddFkSetSymbol(FieldIdentityDialServices, store.stores.edgeService) - store.symbolEdgeRouterPolicies = store.AddFkSetSymbol(EntityTypeEdgeRouterPolicies, store.stores.edgeRouterPolicy) - store.symbolServicePolicies = store.AddFkSetSymbol(EntityTypeServicePolicies, store.stores.servicePolicy) - store.symbolEnrollments = store.AddFkSetSymbol(FieldIdentityEnrollments, store.stores.enrollment) - store.symbolAuthenticators = store.AddFkSetSymbol(FieldIdentityAuthenticators, store.stores.authenticator) - store.symbolExternalId = store.AddSymbol(FieldIdentityExternalId, ast.NodeTypeString) - store.externalIdIndex = store.AddNullableUniqueIndex(store.symbolExternalId) - - store.symbolIdentityTypeId = store.AddFkSymbol(FieldIdentityType, store.stores.identityType) - store.symbolAuthPolicyId = store.AddFkSymbol(FieldIdentityAuthPolicyId, store.stores.authPolicy) - - store.AddFkConstraint(store.symbolAuthPolicyId, true, boltz.CascadeNone) - - store.AddSymbol(FieldIdentityIsAdmin, ast.NodeTypeBool) - store.AddSymbol(FieldIdentityIsDefaultAdmin, ast.NodeTypeBool) - - store.indexRoleAttributes.AddListener(store.rolesChanged) -} - -func (store *identityStoreImpl) initializeLinked() { - store.AddLinkCollection(store.symbolEdgeRouterPolicies, store.stores.edgeRouterPolicy.symbolIdentities) - store.AddLinkCollection(store.symbolServicePolicies, store.stores.servicePolicy.symbolIdentities) - - store.edgeRoutersCollection = store.AddRefCountedLinkCollection(store.symbolEdgeRouters, store.stores.edgeRouter.symbolIdentities) - store.bindServicesCollection = store.AddRefCountedLinkCollection(store.symbolBindServices, store.stores.edgeService.symbolBindIdentities) - store.dialServicesCollection = store.AddRefCountedLinkCollection(store.symbolDialServices, store.stores.edgeService.symbolDialIdentities) -} - func (store *identityStoreImpl) rolesChanged(mutateCtx boltz.MutateContext, rowId []byte, _ []boltz.FieldTypeAndValue, new []boltz.FieldTypeAndValue, holder errorz.ErrorHolder) { ctx := &roleAttributeChangeContext{ tx: mutateCtx.Tx(), @@ -381,23 +380,6 @@ func (store *identityStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *identityStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Identity, error) { - entity := &Identity{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - - return entity, nil -} - -func (store *identityStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*Identity, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - func (store *identityStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { for _, enrollmentId := range store.GetRelatedEntitiesIdList(ctx.Tx(), id, FieldIdentityEnrollments) { if err := store.stores.enrollment.DeleteById(ctx, enrollmentId); err != nil { @@ -417,8 +399,12 @@ func (store *identityStoreImpl) DeleteById(ctx boltz.MutateContext, id string) e } if entity.IdentityTypeId == RouterIdentityType { if !ctx.IsSystemContext() { - if router, _ := store.stores.Router.LoadOneByName(ctx.Tx(), entity.Name); router != nil { - err := errors.Errorf("cannot delete router identity %v until associated router is deleted", entity.Name) + router, err := store.stores.Router.FindByName(ctx.Tx(), entity.Name) + if err != nil { + return errorz.NewEntityCanNotBeDeletedFrom(err) + } + if router != nil { + err = errors.Errorf("cannot delete router identity %v until associated router is deleted", entity.Name) return errorz.NewEntityCanNotBeDeletedFrom(err) } } diff --git a/controller/persistence/identity_store_test.go b/controller/persistence/identity_store_test.go index bb406d66f..9ed3ff9ec 100644 --- a/controller/persistence/identity_store_test.go +++ b/controller/persistence/identity_store_test.go @@ -3,7 +3,9 @@ package persistence import ( "fmt" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "github.com/pkg/errors" "go.etcd.io/bbolt" "testing" @@ -22,14 +24,14 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { identity := ctx.RequireNewIdentity(eid.New(), false) clientConfigTypeId := "" - err := ctx.GetDb().Update(func(tx *bbolt.Tx) error { + err := ctx.GetDb().View(func(tx *bbolt.Tx) error { clientConfigTypeId = string(ctx.stores.ConfigType.GetNameIndex().Read(tx, []byte("ziti-tunneler-client.v1"))) return nil }) ctx.NoError(err) serverConfigTypeId := "" - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + err = ctx.GetDb().View(func(tx *bbolt.Tx) error { serverConfigTypeId = string(ctx.stores.ConfigType.GetNameIndex().Read(tx, []byte("ziti-tunneler-server.v1"))) return nil }) @@ -39,22 +41,23 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { "hostname": "foo.yourcompany.com", "port": int64(22), }) - ctx.RequireCreate(config) + boltztest.RequireCreate(ctx, config) config2 := newConfig(eid.New(), clientConfigTypeId, map[string]interface{}{ "hostname": "bar.yourcompany.com", "port": int64(23), }) - ctx.RequireCreate(config2) + boltztest.RequireCreate(ctx, config2) config3 := newConfig(eid.New(), serverConfigTypeId, map[string]interface{}{ "hostname": "baz.yourcompany.com", "port": int64(24), }) - ctx.RequireCreate(config3) + boltztest.RequireCreate(ctx, config3) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { - err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id, + mutateCtx := change.New().SetSource("test").NewMutateContext() + err = ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + err := ctx.stores.Identity.AssignServiceConfigs(mutateCtx.Tx(), identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id}, ServiceConfig{ServiceId: service.Id, ConfigId: config2.Id}) ctx.EqualError(err, fmt.Sprintf("multiple service configs provided for identity %v of config type %v", identity.Id, clientConfigTypeId)) @@ -62,7 +65,9 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { }) ctx.NoError(err) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx = change.New().SetSource("test").NewMutateContext() + err = ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id}) ctx.NoError(err) @@ -83,7 +88,9 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { }) ctx.NoError(err) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx = change.New().SetSource("test").NewMutateContext() + err = ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() err := ctx.stores.Identity.RemoveServiceConfigs(tx, identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id}) ctx.NoError(err) @@ -96,17 +103,19 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { }) ctx.NoError(err) - ctx.RequireDelete(config) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + boltztest.RequireDelete(ctx, config) + err = ctx.GetDb().View(func(tx *bbolt.Tx) error { serviceConfigs := ctx.getServiceConfigs(tx, identity.Id, "all") ctx.Equal(0, len(serviceConfigs)) return nil }) ctx.NoError(err) - ctx.RequireCreate(config) + boltztest.RequireCreate(ctx, config) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx = change.New().SetSource("test").NewMutateContext() + err = ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() err := ctx.stores.Identity.AssignServiceConfigs(tx, identity.Id, ServiceConfig{ServiceId: service.Id, ConfigId: config.Id}, ServiceConfig{ServiceId: service.Id, ConfigId: config3.Id}) @@ -139,9 +148,9 @@ func (ctx *TestContext) testIdentityServiceConfigs(_ *testing.T) { }) ctx.NoError(err) - ctx.RequireDelete(identity) + boltztest.RequireDelete(ctx, identity) - err = ctx.GetDb().Update(func(tx *bbolt.Tx) error { + err = ctx.GetDb().View(func(tx *bbolt.Tx) error { identityServices := ctx.getIdentityServices(tx, config.Id) ctx.Equal(0, len(identityServices)) diff --git a/controller/persistence/identity_type_store.go b/controller/persistence/identity_type_store.go index b21dacc0b..7e850003c 100644 --- a/controller/persistence/identity_type_store.go +++ b/controller/persistence/identity_type_store.go @@ -18,7 +18,6 @@ package persistence import ( "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -34,43 +33,29 @@ func (entity *IdentityType) GetName() string { return entity.Name } -func (entity *IdentityType) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Name = bucket.GetStringOrError(FieldName) -} - -func (entity *IdentityType) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldName, entity.Name) -} - func (entity *IdentityType) GetEntityType() string { return EntityTypeIdentityTypes } +var _ IdentityTypeStore = (*IdentityTypeStoreImpl)(nil) + type IdentityTypeStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*IdentityType, error) - LoadOneByName(tx *bbolt.Tx, id string) (*IdentityType, error) + NameIndexed + Store[*IdentityType] } func newIdentityTypeStore(stores *stores) *IdentityTypeStoreImpl { - store := &IdentityTypeStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeIdentityTypes), - } + store := &IdentityTypeStoreImpl{} + store.baseStore = newBaseStore[*IdentityType](stores, store) store.InitImpl(store) return store } type IdentityTypeStoreImpl struct { - *baseStore + *baseStore[*IdentityType] indexName boltz.ReadIndex } -func (store *IdentityTypeStoreImpl) NewStoreEntity() boltz.Entity { - return &IdentityType{} -} - func (store *IdentityTypeStoreImpl) initializeLocal() { store.AddExtEntitySymbols() store.indexName = store.addUniqueNameField() @@ -84,26 +69,16 @@ func (store *IdentityTypeStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *IdentityTypeStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*IdentityType, error) { - entity := &IdentityType{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *IdentityTypeStoreImpl) NewEntity() *IdentityType { + return &IdentityType{} } -func (store *IdentityTypeStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*IdentityType, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil +func (store *IdentityTypeStoreImpl) FillEntity(entity *IdentityType, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Name = bucket.GetStringOrError(FieldName) } -func (store *IdentityTypeStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*IdentityType, error) { - entity := &IdentityType{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil +func (store *IdentityTypeStoreImpl) PersistEntity(entity *IdentityType, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldName, entity.Name) } diff --git a/controller/persistence/mfa_store.go b/controller/persistence/mfa_store.go index f10e2de61..922e57158 100644 --- a/controller/persistence/mfa_store.go +++ b/controller/persistence/mfa_store.go @@ -20,7 +20,6 @@ import ( "github.com/google/uuid" "github.com/openziti/edge/eid" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -49,57 +48,32 @@ func NewMfa(identityId string) *Mfa { } } -func (entity *Mfa) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.IdentityId = bucket.GetStringOrError(FieldMfaIdentity) - entity.IsVerified = bucket.GetBoolWithDefault(FieldMfaIsVerified, false) - entity.RecoveryCodes = bucket.GetStringList(FieldMfaRecoveryCodes) - entity.Salt = bucket.GetStringOrError(FieldMfaSalt) - entity.Secret = bucket.GetStringWithDefault(FieldMfaSecret, "") -} - -func (entity *Mfa) SetValues(ctx *boltz.PersistContext) { - entity.SetBaseValues(ctx) - ctx.SetString(FieldMfaIdentity, entity.IdentityId) - ctx.SetBool(FieldMfaIsVerified, entity.IsVerified) - ctx.SetStringList(FieldMfaRecoveryCodes, entity.RecoveryCodes) - ctx.SetString(FieldMfaSalt, entity.Salt) - ctx.SetString(FieldMfaSecret, entity.Secret) -} - func (entity *Mfa) GetEntityType() string { return EntityTypeMfas } +var _ MfaStore = (*MfaStoreImpl)(nil) + type MfaStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*Mfa, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*Mfa, error) + Store[*Mfa] } func newMfaStore(stores *stores) *MfaStoreImpl { - store := &MfaStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeMfas), - } - + store := &MfaStoreImpl{} + store.baseStore = newBaseStore[*Mfa](stores, store) store.InitImpl(store) return store } type SecretStore interface { GetSecret() []byte - } type MfaStoreImpl struct { - *baseStore + *baseStore[*Mfa] symbolIdentity boltz.EntitySymbol } -func (store *MfaStoreImpl) NewStoreEntity() boltz.Entity { - return &Mfa{} -} - func (store *MfaStoreImpl) initializeLocal() { store.AddExtEntitySymbols() store.symbolIdentity = store.AddFkSymbol(FieldMfaIdentity, store.stores.identity) @@ -107,21 +81,26 @@ func (store *MfaStoreImpl) initializeLocal() { store.AddFkConstraint(store.symbolIdentity, false, boltz.CascadeDelete) } -func (store *MfaStoreImpl) initializeLinked() { +func (store *MfaStoreImpl) initializeLinked() {} + +func (store *MfaStoreImpl) NewEntity() *Mfa { + return &Mfa{} } -func (store *MfaStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Mfa, error) { - entity := &Mfa{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil +func (store *MfaStoreImpl) FillEntity(entity *Mfa, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.IdentityId = bucket.GetStringOrError(FieldMfaIdentity) + entity.IsVerified = bucket.GetBoolWithDefault(FieldMfaIsVerified, false) + entity.RecoveryCodes = bucket.GetStringList(FieldMfaRecoveryCodes) + entity.Salt = bucket.GetStringOrError(FieldMfaSalt) + entity.Secret = bucket.GetStringWithDefault(FieldMfaSecret, "") } -func (store *MfaStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*Mfa, error) { - entity := &Mfa{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil +func (store *MfaStoreImpl) PersistEntity(entity *Mfa, ctx *boltz.PersistContext) { + entity.SetBaseValues(ctx) + ctx.SetString(FieldMfaIdentity, entity.IdentityId) + ctx.SetBool(FieldMfaIsVerified, entity.IsVerified) + ctx.SetStringList(FieldMfaRecoveryCodes, entity.RecoveryCodes) + ctx.SetString(FieldMfaSalt, entity.Salt) + ctx.SetString(FieldMfaSecret, entity.Secret) } diff --git a/controller/persistence/migration_initialize.go b/controller/persistence/migration_initialize.go index bf4902bb2..c84195f46 100644 --- a/controller/persistence/migration_initialize.go +++ b/controller/persistence/migration_initialize.go @@ -620,7 +620,7 @@ func (m *Migrations) addPostureCheckTypes(step *boltz.MigrationStep) { iOS, } - types := []*PostureCheckOs{ + types := []*PostureCheckType{ { BaseExtEntity: boltz.BaseExtEntity{ Id: "OS", diff --git a/controller/persistence/migration_v16.go b/controller/persistence/migration_v16.go index 201968cf2..0a160364b 100644 --- a/controller/persistence/migration_v16.go +++ b/controller/persistence/migration_v16.go @@ -31,7 +31,7 @@ func (m *Migrations) removeOrphanedOttCaEnrollments(step *boltz.MigrationStep) { } //clear caIds that are invalid via CheckIntegrity - err := m.stores.Enrollment.CheckIntegrity(step.Ctx.Tx(), true, func(err error, fixed bool) { + err := m.stores.Enrollment.CheckIntegrity(step.Ctx, true, func(err error, fixed bool) { if !fixed { pfxlog.Logger().Errorf("unfixable error during orphaned ottca enrollment integrity check: %v", err) } diff --git a/controller/persistence/migration_v23.go b/controller/persistence/migration_v23.go index 865227401..d25f7d5cf 100644 --- a/controller/persistence/migration_v23.go +++ b/controller/persistence/migration_v23.go @@ -21,7 +21,7 @@ func (m *Migrations) addProcessMultiPostureCheck(step *boltz.MigrationStep) { OsVersions: []string{}, } - processCheckType := &PostureCheckOs{ + processCheckType := &PostureCheckType{ BaseExtEntity: boltz.BaseExtEntity{ Id: "PROCESS_MULTI", CreatedAt: time.Now(), diff --git a/controller/persistence/policy_common.go b/controller/persistence/policy_common.go index c2a6f7a47..67ecdd96c 100644 --- a/controller/persistence/policy_common.go +++ b/controller/persistence/policy_common.go @@ -18,15 +18,15 @@ type serviceEventHandler struct { events []*ServiceEvent } -func (self *serviceEventHandler) addServiceUpdatedEvent(store *baseStore, tx *bbolt.Tx, serviceId []byte) { - cursor := store.stores.edgeService.bindIdentitiesCollection.IterateLinks(tx, serviceId, true) +func (self *serviceEventHandler) addServiceUpdatedEvent(stores *stores, tx *bbolt.Tx, serviceId []byte) { + cursor := stores.edgeService.bindIdentitiesCollection.IterateLinks(tx, serviceId, true) for cursor != nil && cursor.IsValid() { self.addServiceEvent(tx, cursor.Current(), serviceId, ServiceUpdated) cursor.Next() } - cursor = store.stores.edgeService.dialIdentitiesCollection.IterateLinks(tx, serviceId, true) + cursor = stores.edgeService.dialIdentitiesCollection.IterateLinks(tx, serviceId, true) for cursor != nil && cursor.IsValid() { self.addServiceEvent(tx, cursor.Current(), serviceId, ServiceUpdated) cursor.Next() @@ -79,7 +79,7 @@ func (self *roleAttributeChangeContext) addServicePolicyEvent(identityId, servic self.addServiceEvent(self.tx, identityId, serviceId, eventType) } -func (store *baseStore) validateRoleAttributes(attributes []string, holder errorz.ErrorHolder) { +func (store *baseStore[E]) validateRoleAttributes(attributes []string, holder errorz.ErrorHolder) { for _, attr := range attributes { if strings.HasPrefix(attr, "#") { holder.SetError(errorz.NewFieldError("role attributes may not be prefixed with #", "roleAttributes", attr)) @@ -92,7 +92,7 @@ func (store *baseStore) validateRoleAttributes(attributes []string, holder error } } -func (store *baseStore) updateServicePolicyRelatedRoles(ctx *roleAttributeChangeContext, entityId []byte, newRoleAttributes []boltz.FieldTypeAndValue) { +func (store *baseStore[E]) updateServicePolicyRelatedRoles(ctx *roleAttributeChangeContext, entityId []byte, newRoleAttributes []boltz.FieldTypeAndValue) { cursor := ctx.rolesSymbol.GetStore().IterateIds(ctx.tx, ast.BoolNodeTrue) entityRoles := FieldValuesToIds(newRoleAttributes) @@ -135,7 +135,7 @@ func (store *baseStore) updateServicePolicyRelatedRoles(ctx *roleAttributeChange ctx.denormLinkCollection = store.stores.postureCheck.dialServicesCollection ctx.changeHandler = func(fromId, toId []byte, add bool) { pfxlog.Logger().Warnf("posture check %v -> service %v - included? %v", string(fromId), string(toId), add) - ctx.addServiceUpdatedEvent(store, ctx.tx, toId) + ctx.addServiceUpdatedEvent(store.stores, ctx.tx, toId) } } } else if isServices { @@ -152,7 +152,7 @@ func (store *baseStore) updateServicePolicyRelatedRoles(ctx *roleAttributeChange ctx.denormLinkCollection = store.stores.postureCheck.bindServicesCollection ctx.changeHandler = func(fromId, toId []byte, add bool) { pfxlog.Logger().Warnf("posture check %v -> service %v - included? %v", string(fromId), string(toId), add) - ctx.addServiceUpdatedEvent(store, ctx.tx, toId) + ctx.addServiceUpdatedEvent(store.stores, ctx.tx, toId) } } evaluatePolicyAgainstEntity(ctx, semantic, entityId, policyId, ids, roles, entityRoles) @@ -199,7 +199,7 @@ func EvaluatePolicy(ctx *roleAttributeChangeContext, policy Policy, roleAttribut } } -func validateEntityIds(tx *bbolt.Tx, store boltz.ListStore, field string, ids []string) error { +func validateEntityIds(tx *bbolt.Tx, store boltz.Store, field string, ids []string) error { var invalid []string for _, val := range ids { if !store.IsEntityPresent(tx, val) { @@ -297,10 +297,10 @@ func ProcessEntityPolicyUnmatched(ctx *roleAttributeChangeContext, entityId, pol type denormCheckCtx struct { name string - tx *bbolt.Tx - sourceStore boltz.CrudStore - targetStore boltz.CrudStore - policyStore boltz.CrudStore + mutateCtx boltz.MutateContext + sourceStore boltz.Store + targetStore boltz.Store + policyStore boltz.Store sourceCollection boltz.LinkCollection targetCollection boltz.LinkCollection targetDenormCollection boltz.RefCountedLinkCollection @@ -310,18 +310,19 @@ type denormCheckCtx struct { } func validatePolicyDenormalization(ctx *denormCheckCtx) error { - for sourceCursor := ctx.sourceStore.IterateIds(ctx.tx, ast.BoolNodeTrue); sourceCursor.IsValid(); sourceCursor.Next() { + tx := ctx.mutateCtx.Tx() + for sourceCursor := ctx.sourceStore.IterateIds(tx, ast.BoolNodeTrue); sourceCursor.IsValid(); sourceCursor.Next() { sourceEntityId := sourceCursor.Current() - for targetCursor := ctx.targetStore.IterateIds(ctx.tx, ast.BoolNodeTrue); targetCursor.IsValid(); targetCursor.Next() { + for targetCursor := ctx.targetStore.IterateIds(tx, ast.BoolNodeTrue); targetCursor.IsValid(); targetCursor.Next() { targetEntityId := targetCursor.Current() var relatedPolicies []string - for policyCursor := ctx.policyStore.IterateIds(ctx.tx, ast.BoolNodeTrue); policyCursor.IsValid(); policyCursor.Next() { + for policyCursor := ctx.policyStore.IterateIds(tx, ast.BoolNodeTrue); policyCursor.IsValid(); policyCursor.Next() { policyId := policyCursor.Current() if ctx.policyFilter == nil || ctx.policyFilter(policyId) { - sourceRelated := isRelatedByLinkCollection(ctx.tx, ctx.sourceCollection, policyId, sourceEntityId) - targetRelated := isRelatedByLinkCollection(ctx.tx, ctx.targetCollection, policyId, targetEntityId) + sourceRelated := isRelatedByLinkCollection(tx, ctx.sourceCollection, policyId, sourceEntityId) + targetRelated := isRelatedByLinkCollection(tx, ctx.targetCollection, policyId, targetEntityId) if sourceRelated && targetRelated { relatedPolicies = append(relatedPolicies, string(policyId)) } @@ -331,9 +332,9 @@ func validatePolicyDenormalization(ctx *denormCheckCtx) error { var sourceLinkCount, targetLinkCount *int32 var err error if ctx.repair { - sourceLinkCount, targetLinkCount, err = ctx.targetDenormCollection.SetLinkCount(ctx.tx, sourceEntityId, targetEntityId, linkCount) + sourceLinkCount, targetLinkCount, err = ctx.targetDenormCollection.SetLinkCount(tx, sourceEntityId, targetEntityId, linkCount) } else { - sourceLinkCount, targetLinkCount = ctx.targetDenormCollection.GetLinkCounts(ctx.tx, sourceEntityId, targetEntityId) + sourceLinkCount, targetLinkCount = ctx.targetDenormCollection.GetLinkCounts(tx, sourceEntityId, targetEntityId) } if err != nil { return err diff --git a/controller/persistence/posture_check_mac.go b/controller/persistence/posture_check_mac.go index 98cd4b782..35e56e1cb 100644 --- a/controller/persistence/posture_check_mac.go +++ b/controller/persistence/posture_check_mac.go @@ -36,7 +36,7 @@ type PostureCheckMacAddresses struct { MacAddresses []string } -func (entity *PostureCheckMacAddresses) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckMacAddresses) LoadValues(bucket *boltz.TypedBucket) { for _, macAddress := range bucket.GetStringList(FieldPostureCheckMacAddresses) { macAddress = cleanMacAddress(macAddress) entity.MacAddresses = append(entity.MacAddresses, macAddress) diff --git a/controller/persistence/posture_check_mfa.go b/controller/persistence/posture_check_mfa.go index 4acfde474..cf03080c0 100644 --- a/controller/persistence/posture_check_mfa.go +++ b/controller/persistence/posture_check_mfa.go @@ -43,7 +43,7 @@ func newPostureCheckMfa() PostureCheckSubType { } } -func (entity *PostureCheckMfa) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckMfa) LoadValues(bucket *boltz.TypedBucket) { entity.TimeoutSeconds = bucket.GetInt64WithDefault(FieldPostureCheckMfaTimeoutSeconds, -1) if entity.TimeoutSeconds <= 0 { diff --git a/controller/persistence/posture_check_os.go b/controller/persistence/posture_check_os.go index c79e0a17d..abc2b63da 100644 --- a/controller/persistence/posture_check_os.go +++ b/controller/persistence/posture_check_os.go @@ -41,7 +41,7 @@ func newPostureCheckOperatingSystem() PostureCheckSubType { } } -func (entity *PostureCheckOperatingSystem) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckOperatingSystem) LoadValues(bucket *boltz.TypedBucket) { cursor := bucket.Cursor() diff --git a/controller/persistence/posture_check_process.go b/controller/persistence/posture_check_process.go index 92709967b..384efef87 100644 --- a/controller/persistence/posture_check_process.go +++ b/controller/persistence/posture_check_process.go @@ -44,7 +44,7 @@ func newPostureCheckProcess() PostureCheckSubType { } } -func (entity *PostureCheckProcess) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckProcess) LoadValues(bucket *boltz.TypedBucket) { entity.OperatingSystem = bucket.GetStringOrError(FieldPostureCheckProcessOs) entity.Path = bucket.GetStringOrError(FieldPostureCheckProcessPath) entity.Hashes = bucket.GetStringList(FieldPostureCheckProcessHashes) diff --git a/controller/persistence/posture_check_process_multi.go b/controller/persistence/posture_check_process_multi.go index 39d775a7a..76ae023c3 100644 --- a/controller/persistence/posture_check_process_multi.go +++ b/controller/persistence/posture_check_process_multi.go @@ -48,7 +48,7 @@ func newPostureCheckProcessMulti() PostureCheckSubType { } } -func (entity *PostureCheckProcessMulti) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckProcessMulti) LoadValues(bucket *boltz.TypedBucket) { entity.Semantic = bucket.GetStringOrError(FieldSemantic) processesBucket := bucket.GetBucket(FieldPostureCheckProcessMultiProcesses) diff --git a/controller/persistence/posture_check_store.go b/controller/persistence/posture_check_store.go index 53d4461eb..ac7dbf18a 100644 --- a/controller/persistence/posture_check_store.go +++ b/controller/persistence/posture_check_store.go @@ -53,7 +53,7 @@ var postureCheckSubTypeMap = map[string]newPostureCheckSubType{ type newPostureCheckSubType func() PostureCheckSubType type PostureCheckSubType interface { - LoadValues(store boltz.CrudStore, bucket *boltz.TypedBucket) + LoadValues(bucket *boltz.TypedBucket) SetValues(ctx *boltz.PersistContext, bucket *boltz.TypedBucket) } @@ -77,7 +77,43 @@ func (entity *PostureCheck) GetName() string { return entity.Name } -func (entity *PostureCheck) LoadValues(store boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheck) GetEntityType() string { + return EntityTypePostureChecks +} + +type PostureCheckStore interface { + Store[*PostureCheck] + LoadOneById(tx *bbolt.Tx, id string) (*PostureCheck, error) + GetRoleAttributesIndex() boltz.SetReadIndex + GetRoleAttributesCursorProvider(filters []string, semantic string) (ast.SetCursorProvider, error) +} + +func newPostureCheckStore(stores *stores) *postureCheckStoreImpl { + store := &postureCheckStoreImpl{} + store.baseStore = newBaseStore[*PostureCheck](stores, store) + store.InitImpl(store) + return store +} + +type postureCheckStoreImpl struct { + *baseStore[*PostureCheck] + indexName boltz.ReadIndex + indexRoleAttributes boltz.SetReadIndex + + symbolServicePolicies boltz.EntitySetSymbol + symbolRoleAttributes boltz.EntitySetSymbol + symbolBindServices boltz.EntitySetSymbol + symbolDialServices boltz.EntitySetSymbol + + bindServicesCollection boltz.RefCountedLinkCollection + dialServicesCollection boltz.RefCountedLinkCollection +} + +func (store *postureCheckStoreImpl) NewEntity() *PostureCheck { + return &PostureCheck{} +} + +func (store *postureCheckStoreImpl) FillEntity(entity *PostureCheck, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) entity.TypeId = bucket.GetStringOrError(FieldPostureCheckTypeId) @@ -91,10 +127,10 @@ func (entity *PostureCheck) LoadValues(store boltz.CrudStore, bucket *boltz.Type childBucket := bucket.GetOrCreateBucket(entity.TypeId) - entity.SubType.LoadValues(store, childBucket) + entity.SubType.LoadValues(childBucket) } -func (entity *PostureCheck) SetValues(ctx *boltz.PersistContext) { +func (store *postureCheckStoreImpl) PersistEntity(entity *PostureCheck, ctx *boltz.PersistContext) { entity.SetBaseValues(ctx) ctx.SetString(FieldName, entity.Name) ctx.SetString(FieldPostureCheckTypeId, entity.TypeId) @@ -106,51 +142,11 @@ func (entity *PostureCheck) SetValues(ctx *boltz.PersistContext) { entity.SubType.SetValues(ctx, childBucket) // index change won't fire if we don't have any roles on create, but we need to evaluate if we match any #all roles - store := ctx.Store.(*postureCheckStoreImpl) if ctx.IsCreate && len(entity.RoleAttributes) == 0 { store.rolesChanged(ctx.MutateContext, []byte(entity.Id), nil, nil, ctx.Bucket) } } -func (entity *PostureCheck) GetEntityType() string { - return EntityTypePostureChecks -} - -type PostureCheckStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*PostureCheck, error) - LoadOneByName(tx *bbolt.Tx, id string) (*PostureCheck, error) - LoadOneByQuery(tx *bbolt.Tx, query string) (*PostureCheck, error) - GetRoleAttributesIndex() boltz.SetReadIndex - GetRoleAttributesCursorProvider(filters []string, semantic string) (ast.SetCursorProvider, error) -} - -func newPostureCheckStore(stores *stores) *postureCheckStoreImpl { - store := &postureCheckStoreImpl{ - baseStore: newBaseStore(stores, EntityTypePostureChecks), - } - store.InitImpl(store) - return store -} - -type postureCheckStoreImpl struct { - *baseStore - indexName boltz.ReadIndex - indexRoleAttributes boltz.SetReadIndex - - symbolServicePolicies boltz.EntitySetSymbol - symbolRoleAttributes boltz.EntitySetSymbol - symbolBindServices boltz.EntitySetSymbol - symbolDialServices boltz.EntitySetSymbol - - bindServicesCollection boltz.RefCountedLinkCollection - dialServicesCollection boltz.RefCountedLinkCollection -} - -func (store *postureCheckStoreImpl) NewStoreEntity() boltz.Entity { - return &PostureCheck{} -} - func (store *postureCheckStoreImpl) GetRoleAttributesIndex() boltz.SetReadIndex { return store.indexRoleAttributes } @@ -183,30 +179,6 @@ func (store *postureCheckStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *postureCheckStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*PostureCheck, error) { - entity := &PostureCheck{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *postureCheckStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*PostureCheck, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - -func (store *postureCheckStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*PostureCheck, error) { - entity := &PostureCheck{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} - func (store *postureCheckStoreImpl) DeleteById(ctx boltz.MutateContext, id string) error { if entity, _ := store.LoadOneById(ctx.Tx(), id); entity != nil { // Remove entity from PostureCheckRoles in service policies @@ -219,7 +191,7 @@ func (store *postureCheckStoreImpl) DeleteById(ctx boltz.MutateContext, id strin return store.baseStore.DeleteById(ctx, id) } -func (store *postureCheckStoreImpl) Update(ctx boltz.MutateContext, entity boltz.Entity, checker boltz.FieldChecker) error { +func (store *postureCheckStoreImpl) Update(ctx boltz.MutateContext, entity *PostureCheck, checker boltz.FieldChecker) error { store.createServiceChangeEvents(ctx.Tx(), entity.GetId()) return store.baseStore.Update(ctx, entity, checker) } @@ -229,13 +201,13 @@ func (store *postureCheckStoreImpl) createServiceChangeEvents(tx *bbolt.Tx, id s cursor := store.bindServicesCollection.IterateLinks(tx, []byte(id), true) for cursor.IsValid() { - eh.addServiceUpdatedEvent(store.baseStore, tx, cursor.Current()) + eh.addServiceUpdatedEvent(store.stores, tx, cursor.Current()) cursor.Next() } cursor = store.dialServicesCollection.IterateLinks(tx, []byte(id), true) for cursor.IsValid() { - eh.addServiceUpdatedEvent(store.baseStore, tx, cursor.Current()) + eh.addServiceUpdatedEvent(store.stores, tx, cursor.Current()) cursor.Next() } } diff --git a/controller/persistence/posture_check_type_store.go b/controller/persistence/posture_check_type_store.go index 317ef9444..aa47f0b91 100644 --- a/controller/persistence/posture_check_type_store.go +++ b/controller/persistence/posture_check_type_store.go @@ -18,24 +18,63 @@ package persistence import ( "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( FieldPostureCheckTypeOperatingSystems = "operatingSystems" ) -type PostureCheckOs struct { +type PostureCheckType struct { boltz.BaseExtEntity Name string OperatingSystems []OperatingSystem } -func (entity *PostureCheckOs) GetName() string { +func (entity *PostureCheckType) GetName() string { return entity.Name } -func (entity *PostureCheckOs) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckType) GetEntityType() string { + return EntityTypePostureCheckTypes +} + +var _ PostureCheckTypeStore = (*postureCheckTypeStoreImpl)(nil) + +type PostureCheckTypeStore interface { + NameIndexed + Store[*PostureCheckType] +} + +func newPostureCheckTypeStore(stores *stores) *postureCheckTypeStoreImpl { + store := &postureCheckTypeStoreImpl{} + store.baseStore = newBaseStore[*PostureCheckType](stores, store) + store.InitImpl(store) + return store +} + +type postureCheckTypeStoreImpl struct { + *baseStore[*PostureCheckType] + indexName boltz.ReadIndex +} + +func (store *postureCheckTypeStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + store.indexName = store.addUniqueNameField() +} + +func (store *postureCheckTypeStoreImpl) initializeLinked() { + // no links +} + +func (store *postureCheckTypeStoreImpl) GetNameIndex() boltz.ReadIndex { + return store.indexName +} + +func (*postureCheckTypeStoreImpl) NewEntity() *PostureCheckType { + return &PostureCheckType{} +} + +func (*postureCheckTypeStoreImpl) FillEntity(entity *PostureCheckType, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) @@ -58,7 +97,7 @@ func (entity *PostureCheckOs) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedB } } -func (entity *PostureCheckOs) SetValues(ctx *boltz.PersistContext) { +func (*postureCheckTypeStoreImpl) PersistEntity(entity *PostureCheckType, ctx *boltz.PersistContext) { entity.SetBaseValues(ctx) ctx.SetString(FieldName, entity.Name) @@ -83,67 +122,3 @@ func (entity *PostureCheckOs) SetValues(ctx *boltz.PersistContext) { existing.SetStringList(FieldPostureCheckOsVersions, os.OsVersions, ctx.FieldChecker) } } - -func (entity *PostureCheckOs) GetEntityType() string { - return EntityTypePostureCheckTypes -} - -type PostureCheckTypeStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*PostureCheckOs, error) - LoadOneByName(tx *bbolt.Tx, id string) (*PostureCheckOs, error) -} - -func newPostureCheckTypeStore(stores *stores) *postureCheckTypeStoreImpl { - store := &postureCheckTypeStoreImpl{ - baseStore: newBaseStore(stores, EntityTypePostureCheckTypes), - } - store.InitImpl(store) - return store -} - -type postureCheckTypeStoreImpl struct { - *baseStore - indexName boltz.ReadIndex -} - -func (store *postureCheckTypeStoreImpl) NewStoreEntity() boltz.Entity { - return &PostureCheckOs{} -} - -func (store *postureCheckTypeStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - store.indexName = store.addUniqueNameField() -} - -func (store *postureCheckTypeStoreImpl) initializeLinked() { - // no links -} - -func (store *postureCheckTypeStoreImpl) GetNameIndex() boltz.ReadIndex { - return store.indexName -} - -func (store *postureCheckTypeStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*PostureCheckOs, error) { - entity := &PostureCheckOs{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *postureCheckTypeStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*PostureCheckOs, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - -func (store *postureCheckTypeStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*PostureCheckOs, error) { - entity := &PostureCheckOs{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil -} diff --git a/controller/persistence/posture_check_windows_domain.go b/controller/persistence/posture_check_windows_domain.go index 450fe00e1..07313d7ce 100644 --- a/controller/persistence/posture_check_windows_domain.go +++ b/controller/persistence/posture_check_windows_domain.go @@ -34,7 +34,7 @@ func newPostureCheckWindowsDomain() PostureCheckSubType { } } -func (entity *PostureCheckWindowsDomains) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *PostureCheckWindowsDomains) LoadValues(bucket *boltz.TypedBucket) { entity.Domains = bucket.GetStringList(FieldPostureCheckDomains) } diff --git a/controller/persistence/service_edge_router_policy_store.go b/controller/persistence/service_edge_router_policy_store.go index 43b01344c..2d1412e14 100644 --- a/controller/persistence/service_edge_router_policy_store.go +++ b/controller/persistence/service_edge_router_policy_store.go @@ -4,11 +4,10 @@ import ( "fmt" "github.com/openziti/edge/eid" "github.com/openziti/fabric/controller/db" - "github.com/openziti/storage/ast" - "github.com/openziti/storage/boltz" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" - "go.etcd.io/bbolt" + "github.com/openziti/storage/ast" + "github.com/openziti/storage/boltz" "sort" ) @@ -36,7 +35,63 @@ func (entity *ServiceEdgeRouterPolicy) GetSemantic() string { return entity.Semantic } -func (entity *ServiceEdgeRouterPolicy) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *ServiceEdgeRouterPolicy) GetEntityType() string { + return EntityTypeServiceEdgeRouterPolicies +} + +var _ ServiceEdgeRouterPolicyStore = (*serviceEdgeRouterPolicyStoreImpl)(nil) + +type ServiceEdgeRouterPolicyStore interface { + NameIndexed + Store[*ServiceEdgeRouterPolicy] +} + +func newServiceEdgeRouterPolicyStore(stores *stores) *serviceEdgeRouterPolicyStoreImpl { + store := &serviceEdgeRouterPolicyStoreImpl{} + store.baseStore = newBaseStore[*ServiceEdgeRouterPolicy](stores, store) + store.InitImpl(store) + return store +} + +type serviceEdgeRouterPolicyStoreImpl struct { + *baseStore[*ServiceEdgeRouterPolicy] + + indexName boltz.ReadIndex + symbolSemantic boltz.EntitySymbol + symbolServiceRoles boltz.EntitySetSymbol + symbolEdgeRouterRoles boltz.EntitySetSymbol + symbolServices boltz.EntitySetSymbol + symbolEdgeRouters boltz.EntitySetSymbol + + serviceCollection boltz.LinkCollection + edgeRouterCollection boltz.LinkCollection +} + +func (store *serviceEdgeRouterPolicyStoreImpl) GetNameIndex() boltz.ReadIndex { + return store.indexName +} + +func (store *serviceEdgeRouterPolicyStoreImpl) NewEntity() *ServiceEdgeRouterPolicy { + return &ServiceEdgeRouterPolicy{} +} + +func (store *serviceEdgeRouterPolicyStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + + store.indexName = store.addUniqueNameField() + store.symbolSemantic = store.AddSymbol(FieldSemantic, ast.NodeTypeString) + store.symbolServiceRoles = store.AddPublicSetSymbol(FieldServiceRoles, ast.NodeTypeString) + store.symbolEdgeRouterRoles = store.AddPublicSetSymbol(FieldEdgeRouterRoles, ast.NodeTypeString) + store.symbolServices = store.AddFkSetSymbol(db.EntityTypeServices, store.stores.edgeService) + store.symbolEdgeRouters = store.AddFkSetSymbol(db.EntityTypeRouters, store.stores.edgeRouter) +} + +func (store *serviceEdgeRouterPolicyStoreImpl) initializeLinked() { + store.edgeRouterCollection = store.AddLinkCollection(store.symbolEdgeRouters, store.stores.edgeRouter.symbolServiceEdgeRouterPolicies) + store.serviceCollection = store.AddLinkCollection(store.symbolServices, store.stores.edgeService.symbolServiceEdgeRouterPolicies) +} + +func (store *serviceEdgeRouterPolicyStoreImpl) FillEntity(entity *ServiceEdgeRouterPolicy, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) entity.Semantic = bucket.GetStringWithDefault(FieldSemantic, SemanticAllOf) @@ -44,7 +99,7 @@ func (entity *ServiceEdgeRouterPolicy) LoadValues(_ boltz.CrudStore, bucket *bol entity.EdgeRouterRoles = bucket.GetStringList(FieldEdgeRouterRoles) } -func (entity *ServiceEdgeRouterPolicy) SetValues(ctx *boltz.PersistContext) { +func (store *serviceEdgeRouterPolicyStoreImpl) PersistEntity(entity *ServiceEdgeRouterPolicy, ctx *boltz.PersistContext) { if err := validateRolesAndIds(FieldServiceRoles, entity.ServiceRoles); err != nil { ctx.Bucket.SetError(err) } @@ -77,84 +132,12 @@ func (entity *ServiceEdgeRouterPolicy) SetValues(ctx *boltz.PersistContext) { } } -func (entity *ServiceEdgeRouterPolicy) GetEntityType() string { - return EntityTypeServiceEdgeRouterPolicies -} - -type ServiceEdgeRouterPolicyStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*ServiceEdgeRouterPolicy, error) - LoadOneByName(tx *bbolt.Tx, id string) (*ServiceEdgeRouterPolicy, error) -} - -func newServiceEdgeRouterPolicyStore(stores *stores) *serviceEdgeRouterPolicyStoreImpl { - store := &serviceEdgeRouterPolicyStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeServiceEdgeRouterPolicies), - } - store.InitImpl(store) - return store -} - -type serviceEdgeRouterPolicyStoreImpl struct { - *baseStore - - indexName boltz.ReadIndex - symbolSemantic boltz.EntitySymbol - symbolServiceRoles boltz.EntitySetSymbol - symbolEdgeRouterRoles boltz.EntitySetSymbol - symbolServices boltz.EntitySetSymbol - symbolEdgeRouters boltz.EntitySetSymbol - - serviceCollection boltz.LinkCollection - edgeRouterCollection boltz.LinkCollection -} - -func (store *serviceEdgeRouterPolicyStoreImpl) GetNameIndex() boltz.ReadIndex { - return store.indexName -} - -func (store *serviceEdgeRouterPolicyStoreImpl) NewStoreEntity() boltz.Entity { - return &ServiceEdgeRouterPolicy{} -} - -func (store *serviceEdgeRouterPolicyStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - - store.indexName = store.addUniqueNameField() - store.symbolSemantic = store.AddSymbol(FieldSemantic, ast.NodeTypeString) - store.symbolServiceRoles = store.AddPublicSetSymbol(FieldServiceRoles, ast.NodeTypeString) - store.symbolEdgeRouterRoles = store.AddPublicSetSymbol(FieldEdgeRouterRoles, ast.NodeTypeString) - store.symbolServices = store.AddFkSetSymbol(db.EntityTypeServices, store.stores.edgeService) - store.symbolEdgeRouters = store.AddFkSetSymbol(db.EntityTypeRouters, store.stores.edgeRouter) -} - -func (store *serviceEdgeRouterPolicyStoreImpl) initializeLinked() { - store.edgeRouterCollection = store.AddLinkCollection(store.symbolEdgeRouters, store.stores.edgeRouter.symbolServiceEdgeRouterPolicies) - store.serviceCollection = store.AddLinkCollection(store.symbolServices, store.stores.edgeService.symbolServiceEdgeRouterPolicies) -} - -func (store *serviceEdgeRouterPolicyStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ServiceEdgeRouterPolicy, error) { - entity := &ServiceEdgeRouterPolicy{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *serviceEdgeRouterPolicyStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*ServiceEdgeRouterPolicy, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - /* Optimizations -1. When changing policies if only ids have changed, only add/remove ids from groups as needed -2. When related entities added/changed, only evaluate policies against that one entity (service/edge router/service), - and just add/remove/ignore -3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) + 1. When changing policies if only ids have changed, only add/remove ids from groups as needed + 2. When related entities added/changed, only evaluate policies against that one entity (service/edge router/service), + and just add/remove/ignore + 3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) */ func (store *serviceEdgeRouterPolicyStoreImpl) edgeRouterRolesUpdated(persistCtx *boltz.PersistContext, policy *ServiceEdgeRouterPolicy) { ctx := &roleAttributeChangeContext{ @@ -194,10 +177,10 @@ func (store *serviceEdgeRouterPolicyStoreImpl) DeleteById(ctx boltz.MutateContex return store.BaseStore.DeleteById(ctx, id) } -func (store *serviceEdgeRouterPolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, errorSink func(err error, fixed bool)) error { +func (store *serviceEdgeRouterPolicyStoreImpl) CheckIntegrity(mutateCtx boltz.MutateContext, fix bool, errorSink func(err error, fixed bool)) error { ctx := &denormCheckCtx{ name: "service-edge-router-policies", - tx: tx, + mutateCtx: mutateCtx, sourceStore: store.stores.edgeService, targetStore: store.stores.edgeRouter, policyStore: store, @@ -211,5 +194,5 @@ func (store *serviceEdgeRouterPolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix return err } - return store.BaseStore.CheckIntegrity(tx, fix, errorSink) + return store.BaseStore.CheckIntegrity(mutateCtx, fix, errorSink) } diff --git a/controller/persistence/service_edge_router_policy_store_test.go b/controller/persistence/service_edge_router_policy_store_test.go index 50173f4a0..576d8eefa 100644 --- a/controller/persistence/service_edge_router_policy_store_test.go +++ b/controller/persistence/service_edge_router_policy_store_test.go @@ -6,6 +6,7 @@ import ( "github.com/openziti/fabric/controller/db" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "sort" "testing" @@ -26,14 +27,14 @@ func (ctx *TestContext) testCreateServiceEdgeRouterPolicy(_ *testing.T) { ctx.CleanupAll() policy := newServiceEdgeRouterPolicy(eid.New()) - ctx.RequireCreate(policy) - ctx.ValidateBaseline(policy) + boltztest.RequireCreate(ctx, policy) + boltztest.ValidateBaseline(ctx, policy) err := ctx.GetDb().View(func(tx *bbolt.Tx) error { ctx.Equal(0, len(ctx.stores.ServiceEdgeRouterPolicy.GetRelatedEntitiesIdList(tx, policy.Id, db.EntityTypeRouters))) ctx.Equal(0, len(ctx.stores.ServiceEdgeRouterPolicy.GetRelatedEntitiesIdList(tx, policy.Id, db.EntityTypeServices))) - testPolicy, err := ctx.stores.ServiceEdgeRouterPolicy.LoadOneByName(tx, policy.Name) + testPolicy, err := ctx.stores.ServiceEdgeRouterPolicy.LoadOneById(tx, policy.Id) ctx.NoError(err) ctx.NotNil(testPolicy) ctx.Equal(policy.Name, testPolicy.Name) @@ -50,54 +51,54 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyInvalidValues(_ *testing.T) { policy := newServiceEdgeRouterPolicy(eid.New()) invalidId := eid.New() policy.ServiceRoles = []string{entityRef(invalidId)} - err := ctx.Create(policy) + err := boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) policy.ServiceRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'serviceRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServiceEdgeRouterPolicyServices([]*EdgeService{service}, []*ServiceEdgeRouterPolicy{policy}) policy.ServiceRoles = append(policy.ServiceRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) // test edgeRouter roles policy.ServiceRoles = nil policy.EdgeRouterRoles = []string{entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) policy.EdgeRouterRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'edgeRouterRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServiceEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*ServiceEdgeRouterPolicy{policy}) policy.EdgeRouterRoles = append(policy.EdgeRouterRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'edgeRouterRoles' is invalid: no routers found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } func (ctx *TestContext) testServiceEdgeRouterPolicyUpdateDeleteRefs(_ *testing.T) { @@ -106,58 +107,58 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyUpdateDeleteRefs(_ *testing.T // test service roles policy := newServiceEdgeRouterPolicy(eid.New()) service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServiceEdgeRouterPolicyServices([]*EdgeService{service}, []*ServiceEdgeRouterPolicy{policy}) - ctx.RequireDelete(service) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.ServiceRoles), "service id should have been removed from service roles") service = newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServiceEdgeRouterPolicyServices([]*EdgeService{service}, []*ServiceEdgeRouterPolicy{policy}) service.Name = eid.New() - ctx.RequireUpdate(service) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.ServiceRoles, entityRef(service.Id))) ctx.validateServiceEdgeRouterPolicyServices([]*EdgeService{service}, []*ServiceEdgeRouterPolicy{policy}) - ctx.RequireDelete(service) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.ServiceRoles), "service name should have been removed from service roles") // test edgeRouter roles edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServiceEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*ServiceEdgeRouterPolicy{policy}) - ctx.RequireDelete(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.EdgeRouterRoles), "edgeRouter id should have been removed from edgeRouter roles") edgeRouter = newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) policy.EdgeRouterRoles = []string{entityRef(edgeRouter.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServiceEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*ServiceEdgeRouterPolicy{policy}) edgeRouter.Name = eid.New() - ctx.RequireUpdate(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.EdgeRouterRoles, entityRef(edgeRouter.Id))) ctx.validateServiceEdgeRouterPolicyEdgeRouters([]*EdgeRouter{edgeRouter}, []*ServiceEdgeRouterPolicy{policy}) - ctx.RequireDelete(edgeRouter) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, edgeRouter) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.EdgeRouterRoles), "edgeRouter name should have been removed from edgeRouter roles") } @@ -176,14 +177,14 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) var services []*EdgeService for i := 0; i < 5; i++ { service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) } var edgeRouters []*EdgeRouter for i := 0; i < 5; i++ { edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) } @@ -226,34 +227,34 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) // no roles service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) stringz.Permutations(serviceRolesAttrs, func(roles []string) { service := newEdgeService(eid.New(), roles...) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) }) // no roles edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) stringz.Permutations(edgeRouterRoleAttrs, func(roles []string) { edgeRouter := newEdgeRouter(eid.New(), roles...) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) }) ctx.validateServiceEdgeRouterPolicies(services, edgeRouters, policies) for _, service := range services { - ctx.RequireDelete(service) + boltztest.RequireDelete(ctx, service) } for _, edgeRouter := range edgeRouters { - ctx.RequireDelete(edgeRouter) + boltztest.RequireDelete(ctx, edgeRouter) } services = nil @@ -261,17 +262,17 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) stringz.Permutations(serviceRolesAttrs, func(roles []string) { service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) service.RoleAttributes = roles - ctx.RequireUpdate(service) + boltztest.RequireUpdate(ctx, service) services = append(services, service) }) stringz.Permutations(edgeRouterRoleAttrs, func(roles []string) { edgeRouter := newEdgeRouter(eid.New()) - ctx.RequireCreate(edgeRouter) + boltztest.RequireCreate(ctx, edgeRouter) edgeRouter.RoleAttributes = roles - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) edgeRouters = append(edgeRouters, edgeRouter) }) @@ -279,7 +280,7 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) // ensure policies get cleaned up for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after services/edge routers @@ -288,7 +289,7 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) ctx.validateServiceEdgeRouterPolicies(services, edgeRouters, policies) for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after services/edge routers and roles added after created @@ -299,14 +300,14 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) for _, service := range services { if len(service.RoleAttributes) > 0 { service.RoleAttributes = service.RoleAttributes[1:] - ctx.RequireUpdate(service) + boltztest.RequireUpdate(ctx, service) } } for _, edgeRouter := range edgeRouters { if len(edgeRouter.RoleAttributes) > 0 { edgeRouter.RoleAttributes = edgeRouter.RoleAttributes[1:] - ctx.RequireUpdate(edgeRouter) + boltztest.RequireUpdate(ctx, edgeRouter) } } @@ -317,7 +318,7 @@ func (ctx *TestContext) testServiceEdgeRouterPolicyRoleEvaluation(_ *testing.T) if len(policy.EdgeRouterRoles) > 0 { policy.EdgeRouterRoles = policy.EdgeRouterRoles[1:] } - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } ctx.validateServiceEdgeRouterPolicies(services, edgeRouters, policies) @@ -330,7 +331,7 @@ func (ctx *TestContext) createServiceEdgeRouterPolicies(serviceRoles, edgeRouter policy.Semantic = SemanticAllOf if !oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } if i == 1 { policy.ServiceRoles = []string{serviceRoles[0]} @@ -369,9 +370,9 @@ func (ctx *TestContext) createServiceEdgeRouterPolicies(serviceRoles, edgeRouter policies = append(policies, policy) if oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } else { - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } } return policies @@ -428,8 +429,8 @@ func (ctx *TestContext) validateServiceEdgeRouterPolicyEdgeRouters(edgeRouters [ func (ctx *TestContext) validateServiceEdgeRouterPolicyDenormalization() { errorHolder := &errorz.ErrorHolderImpl{} - errorHolder.SetError(ctx.db.View(func(tx *bbolt.Tx) error { - return ctx.stores.ServiceEdgeRouterPolicy.CheckIntegrity(tx, false, func(err error, _ bool) { + errorHolder.SetError(ctx.GetDb().View(func(tx *bbolt.Tx) error { + return ctx.stores.ServiceEdgeRouterPolicy.CheckIntegrity(ctx.newViewTestCtx(tx), false, func(err error, _ bool) { errorHolder.SetError(err) }) })) diff --git a/controller/persistence/service_policy_store.go b/controller/persistence/service_policy_store.go index 161b6bb4b..75df182e1 100644 --- a/controller/persistence/service_policy_store.go +++ b/controller/persistence/service_policy_store.go @@ -4,11 +4,10 @@ import ( "fmt" "github.com/openziti/edge/eid" "github.com/openziti/fabric/controller/db" - "github.com/openziti/storage/ast" - "github.com/openziti/storage/boltz" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" - "go.etcd.io/bbolt" + "github.com/openziti/storage/ast" + "github.com/openziti/storage/boltz" "math/rand" "sort" ) @@ -71,7 +70,79 @@ func (entity *ServicePolicy) GetSemantic() string { return entity.Semantic } -func (entity *ServicePolicy) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { +func (entity *ServicePolicy) GetEntityType() string { + return EntityTypeServicePolicies +} + +func (entity *ServicePolicy) GetPolicyTypeName() string { + return entity.PolicyType.String() +} + +var _ ServicePolicyStore = (*servicePolicyStoreImpl)(nil) + +type ServicePolicyStore interface { + NameIndexed + Store[*ServicePolicy] +} + +func newServicePolicyStore(stores *stores) *servicePolicyStoreImpl { + store := &servicePolicyStoreImpl{} + store.baseStore = newBaseStore[*ServicePolicy](stores, store) + store.InitImpl(store) + return store +} + +type servicePolicyStoreImpl struct { + *baseStore[*ServicePolicy] + + indexName boltz.ReadIndex + symbolPolicyType boltz.EntitySymbol + symbolSemantic boltz.EntitySymbol + + symbolIdentityRoles boltz.EntitySetSymbol + symbolServiceRoles boltz.EntitySetSymbol + symbolPostureCheckRoles boltz.EntitySetSymbol + + symbolIdentities boltz.EntitySetSymbol + symbolServices boltz.EntitySetSymbol + symbolPostureChecks boltz.EntitySetSymbol + + identityCollection boltz.LinkCollection + serviceCollection boltz.LinkCollection + postureCheckCollection boltz.LinkCollection +} + +func (store *servicePolicyStoreImpl) GetNameIndex() boltz.ReadIndex { + return store.indexName +} + +func (store *servicePolicyStoreImpl) NewEntity() *ServicePolicy { + return &ServicePolicy{} +} + +func (store *servicePolicyStoreImpl) initializeLocal() { + store.AddExtEntitySymbols() + + store.indexName = store.addUniqueNameField() + store.symbolPolicyType = store.AddSymbol(FieldServicePolicyType, ast.NodeTypeInt64) + store.symbolSemantic = store.AddSymbol(FieldSemantic, ast.NodeTypeString) + + store.symbolIdentityRoles = store.AddPublicSetSymbol(FieldIdentityRoles, ast.NodeTypeString) + store.symbolServiceRoles = store.AddPublicSetSymbol(FieldServiceRoles, ast.NodeTypeString) + store.symbolPostureCheckRoles = store.AddPublicSetSymbol(FieldPostureCheckRoles, ast.NodeTypeString) + + store.symbolIdentities = store.AddFkSetSymbol(EntityTypeIdentities, store.stores.identity) + store.symbolServices = store.AddFkSetSymbol(db.EntityTypeServices, store.stores.edgeService) + store.symbolPostureChecks = store.AddFkSetSymbol(EntityTypePostureChecks, store.stores.postureCheck) +} + +func (store *servicePolicyStoreImpl) initializeLinked() { + store.serviceCollection = store.AddLinkCollection(store.symbolServices, store.stores.edgeService.symbolServicePolicies) + store.identityCollection = store.AddLinkCollection(store.symbolIdentities, store.stores.identity.symbolServicePolicies) + store.postureCheckCollection = store.AddLinkCollection(store.symbolPostureChecks, store.stores.postureCheck.symbolServicePolicies) +} + +func (store *servicePolicyStoreImpl) FillEntity(entity *ServicePolicy, bucket *boltz.TypedBucket) { entity.LoadBaseValues(bucket) entity.Name = bucket.GetStringOrError(FieldName) entity.PolicyType = PolicyType(bucket.GetInt32WithDefault(FieldServicePolicyType, int32(PolicyTypeDial))) @@ -81,7 +152,7 @@ func (entity *ServicePolicy) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBu entity.PostureCheckRoles = bucket.GetStringList(FieldPostureCheckRoles) } -func (entity *ServicePolicy) SetValues(ctx *boltz.PersistContext) { +func (store *servicePolicyStoreImpl) PersistEntity(entity *ServicePolicy, ctx *boltz.PersistContext) { if ctx.ProceedWithSet(FieldServicePolicyType) { if entity.PolicyType != PolicyTypeBind && entity.PolicyType != PolicyTypeDial { ctx.Bucket.SetError(errorz.NewFieldError("invalid policy type", FieldServicePolicyType, entity.PolicyType)) @@ -136,100 +207,12 @@ func (entity *ServicePolicy) SetValues(ctx *boltz.PersistContext) { } } -func (entity *ServicePolicy) GetEntityType() string { - return EntityTypeServicePolicies -} - -func (entity *ServicePolicy) GetPolicyTypeName() string { - return entity.PolicyType.String() -} - -type ServicePolicyStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*ServicePolicy, error) - LoadOneByName(tx *bbolt.Tx, id string) (*ServicePolicy, error) -} - -func newServicePolicyStore(stores *stores) *servicePolicyStoreImpl { - store := &servicePolicyStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeServicePolicies), - } - store.InitImpl(store) - return store -} - -type servicePolicyStoreImpl struct { - *baseStore - - indexName boltz.ReadIndex - symbolPolicyType boltz.EntitySymbol - symbolSemantic boltz.EntitySymbol - - symbolIdentityRoles boltz.EntitySetSymbol - symbolServiceRoles boltz.EntitySetSymbol - symbolPostureCheckRoles boltz.EntitySetSymbol - - symbolIdentities boltz.EntitySetSymbol - symbolServices boltz.EntitySetSymbol - symbolPostureChecks boltz.EntitySetSymbol - - identityCollection boltz.LinkCollection - serviceCollection boltz.LinkCollection - postureCheckCollection boltz.LinkCollection -} - -func (store *servicePolicyStoreImpl) GetNameIndex() boltz.ReadIndex { - return store.indexName -} - -func (store *servicePolicyStoreImpl) NewStoreEntity() boltz.Entity { - return &ServicePolicy{} -} - -func (store *servicePolicyStoreImpl) initializeLocal() { - store.AddExtEntitySymbols() - - store.indexName = store.addUniqueNameField() - store.symbolPolicyType = store.AddSymbol(FieldServicePolicyType, ast.NodeTypeInt64) - store.symbolSemantic = store.AddSymbol(FieldSemantic, ast.NodeTypeString) - - store.symbolIdentityRoles = store.AddPublicSetSymbol(FieldIdentityRoles, ast.NodeTypeString) - store.symbolServiceRoles = store.AddPublicSetSymbol(FieldServiceRoles, ast.NodeTypeString) - store.symbolPostureCheckRoles = store.AddPublicSetSymbol(FieldPostureCheckRoles, ast.NodeTypeString) - - store.symbolIdentities = store.AddFkSetSymbol(EntityTypeIdentities, store.stores.identity) - store.symbolServices = store.AddFkSetSymbol(db.EntityTypeServices, store.stores.edgeService) - store.symbolPostureChecks = store.AddFkSetSymbol(EntityTypePostureChecks, store.stores.postureCheck) -} - -func (store *servicePolicyStoreImpl) initializeLinked() { - store.serviceCollection = store.AddLinkCollection(store.symbolServices, store.stores.edgeService.symbolServicePolicies) - store.identityCollection = store.AddLinkCollection(store.symbolIdentities, store.stores.identity.symbolServicePolicies) - store.postureCheckCollection = store.AddLinkCollection(store.symbolPostureChecks, store.stores.postureCheck.symbolServicePolicies) -} - -func (store *servicePolicyStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*ServicePolicy, error) { - entity := &ServicePolicy{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err - } - return entity, nil -} - -func (store *servicePolicyStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*ServicePolicy, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) - } - return nil, nil -} - /* Optimizations -1. When changing policies if only ids have changed, only add/remove ids from groups as needed -2. When related entities added/changed, only evaluate policies against that one entity (identity/edge router/service), - and just add/remove/ignore -3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) + 1. When changing policies if only ids have changed, only add/remove ids from groups as needed + 2. When related entities added/changed, only evaluate policies against that one entity (identity/edge router/service), + and just add/remove/ignore + 3. Related entity deletes should be handled automatically by FK Indexes on those entities (need to verify the reverse as well/deleting policy) */ func (store *servicePolicyStoreImpl) serviceRolesUpdated(persistCtx *boltz.PersistContext, policy *ServicePolicy) { ctx := &roleAttributeChangeContext{ @@ -287,7 +270,7 @@ func (store *servicePolicyStoreImpl) postureCheckRolesUpdated(persistCtx *boltz. } ctx.changeHandler = func(fromId, toId []byte, add bool) { - ctx.addServiceUpdatedEvent(store.baseStore, ctx.tx, toId) + ctx.addServiceUpdatedEvent(store.stores, ctx.tx, toId) } if policy.PolicyType == PolicyTypeDial { @@ -315,10 +298,10 @@ func (store *servicePolicyStoreImpl) DeleteById(ctx boltz.MutateContext, id stri return store.BaseStore.DeleteById(ctx, id) } -func (store *servicePolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, errorSink func(err error, fixed bool)) error { +func (store *servicePolicyStoreImpl) CheckIntegrity(mutateCtx boltz.MutateContext, fix bool, errorSink func(err error, fixed bool)) error { ctx := &denormCheckCtx{ name: "service-policies/bind", - tx: tx, + mutateCtx: mutateCtx, sourceStore: store.stores.identity, targetStore: store.stores.edgeService, policyStore: store, @@ -329,7 +312,7 @@ func (store *servicePolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, erro repair: fix, policyFilter: func(policyId []byte) bool { policyType := PolicyTypeInvalid - if result := boltz.FieldToInt32(store.symbolPolicyType.Eval(tx, policyId)); result != nil { + if result := boltz.FieldToInt32(store.symbolPolicyType.Eval(mutateCtx.Tx(), policyId)); result != nil { policyType = PolicyType(*result) } return policyType == PolicyTypeBind @@ -341,7 +324,7 @@ func (store *servicePolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, erro ctx = &denormCheckCtx{ name: "service-policies/dial", - tx: tx, + mutateCtx: mutateCtx, sourceStore: store.stores.identity, targetStore: store.stores.edgeService, policyStore: store, @@ -352,7 +335,7 @@ func (store *servicePolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, erro repair: fix, policyFilter: func(policyId []byte) bool { policyType := PolicyTypeInvalid - if result := boltz.FieldToInt32(store.symbolPolicyType.Eval(tx, policyId)); result != nil { + if result := boltz.FieldToInt32(store.symbolPolicyType.Eval(mutateCtx.Tx(), policyId)); result != nil { policyType = PolicyType(*result) } return policyType == PolicyTypeDial @@ -363,5 +346,5 @@ func (store *servicePolicyStoreImpl) CheckIntegrity(tx *bbolt.Tx, fix bool, erro return err } - return store.BaseStore.CheckIntegrity(tx, fix, errorSink) + return store.BaseStore.CheckIntegrity(mutateCtx, fix, errorSink) } diff --git a/controller/persistence/service_policy_store_test.go b/controller/persistence/service_policy_store_test.go index fe437c694..efc8f4f73 100644 --- a/controller/persistence/service_policy_store_test.go +++ b/controller/persistence/service_policy_store_test.go @@ -6,6 +6,7 @@ import ( "github.com/openziti/fabric/controller/db" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "sort" "testing" @@ -26,14 +27,14 @@ func (ctx *TestContext) testCreateServicePolicy(_ *testing.T) { ctx.CleanupAll() policy := newServicePolicy(eid.New()) - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) err := ctx.GetDb().View(func(tx *bbolt.Tx) error { - ctx.ValidateBaseline(policy) + boltztest.ValidateBaseline(ctx, policy) ctx.Equal(0, len(ctx.stores.ServicePolicy.GetRelatedEntitiesIdList(tx, policy.Id, db.EntityTypeServices))) ctx.Equal(0, len(ctx.stores.ServicePolicy.GetRelatedEntitiesIdList(tx, policy.Id, EntityTypeIdentities))) - testPolicy, err := ctx.stores.ServicePolicy.LoadOneByName(tx, policy.Name) + testPolicy, err := ctx.stores.ServicePolicy.LoadOneById(tx, policy.Id) ctx.NoError(err) ctx.NotNil(testPolicy) ctx.Equal(policy.Name, testPolicy.Name) @@ -50,55 +51,55 @@ func (ctx *TestContext) testServicePolicyInvalidValues(_ *testing.T) { policy := newServicePolicy(eid.New()) invalidId := eid.New() policy.IdentityRoles = []string{entityRef(invalidId)} - err := ctx.Create(policy) + err := boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) policy.IdentityRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'identityRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) identityTypeId := ctx.getIdentityTypeId() identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServicePolicyIdentities([]*Identity{identity}, []*ServicePolicy{policy}) policy.IdentityRoles = append(policy.IdentityRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'identityRoles' is invalid: no identities found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) // test service roles policy.IdentityRoles = nil policy.ServiceRoles = []string{entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) policy.ServiceRoles = []string{AllRole, roleRef("other")} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v %v]' for 'serviceRoles' is invalid: if using %v, it should be the only role specified", AllRole, roleRef("other"), AllRole)) service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id), entityRef(invalidId)} - err = ctx.Create(policy) + err = boltztest.Create(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServicePolicyServices([]*EdgeService{service}, []*ServicePolicy{policy}) policy.ServiceRoles = append(policy.ServiceRoles, entityRef(invalidId)) - err = ctx.Update(policy) + err = boltztest.Update(ctx, policy) ctx.EqualError(err, fmt.Sprintf("the value '[%v]' for 'serviceRoles' is invalid: no services found with the given ids", invalidId)) - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } func (ctx *TestContext) testServicePolicyUpdateDeleteRefs(_ *testing.T) { @@ -108,58 +109,58 @@ func (ctx *TestContext) testServicePolicyUpdateDeleteRefs(_ *testing.T) { policy := newServicePolicy(eid.New()) identityTypeId := ctx.getIdentityTypeId() identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) ctx.validateServicePolicyIdentities([]*Identity{identity}, []*ServicePolicy{policy}) - ctx.RequireDelete(identity) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.IdentityRoles), "identity id should have been removed from identity roles") identity = newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) policy.IdentityRoles = []string{entityRef(identity.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServicePolicyIdentities([]*Identity{identity}, []*ServicePolicy{policy}) identity.Name = eid.New() - ctx.RequireUpdate(identity) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.IdentityRoles, entityRef(identity.Id))) ctx.validateServicePolicyIdentities([]*Identity{identity}, []*ServicePolicy{policy}) - ctx.RequireDelete(identity) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, identity) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.IdentityRoles), "identity name should have been removed from identity roles") // test service roles service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServicePolicyServices([]*EdgeService{service}, []*ServicePolicy{policy}) - ctx.RequireDelete(service) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.ServiceRoles), "service id should have been removed from service roles") service = newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) policy.ServiceRoles = []string{entityRef(service.Id)} - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) ctx.validateServicePolicyServices([]*EdgeService{service}, []*ServicePolicy{policy}) service.Name = eid.New() - ctx.RequireUpdate(service) - ctx.RequireReload(policy) + boltztest.RequireUpdate(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.True(stringz.Contains(policy.ServiceRoles, entityRef(service.Id))) ctx.validateServicePolicyServices([]*EdgeService{service}, []*ServicePolicy{policy}) - ctx.RequireDelete(service) - ctx.RequireReload(policy) + boltztest.RequireDelete(ctx, service) + boltztest.RequireReload(ctx, policy) ctx.Equal(0, len(policy.ServiceRoles), "service name should have been removed from service roles") } @@ -180,14 +181,14 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { identities := make([]*Identity, 0, 5) for i := 0; i < 5; i++ { identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) } services := make([]*EdgeService, 0, 5) for i := 0; i < 5; i++ { service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) } @@ -230,34 +231,34 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { // no roles identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) stringz.Permutations(identityRolesAttrs, func(roles []string) { identity := newIdentity(eid.New(), identityTypeId, roles...) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identities = append(identities, identity) }) // no roles service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) stringz.Permutations(serviceRoleAttrs, func(roles []string) { service := newEdgeService(eid.New(), roles...) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) services = append(services, service) }) ctx.validateServicePolicies(identities, services, policies) for _, identity := range identities { - ctx.RequireDelete(identity) + boltztest.RequireDelete(ctx, identity) } for _, service := range services { - ctx.RequireDelete(service) + boltztest.RequireDelete(ctx, service) } identities = nil @@ -265,17 +266,17 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { stringz.Permutations(identityRolesAttrs, func(roles []string) { identity := newIdentity(eid.New(), identityTypeId) - ctx.RequireCreate(identity) + boltztest.RequireCreate(ctx, identity) identity.RoleAttributes = roles - ctx.RequireUpdate(identity) + boltztest.RequireUpdate(ctx, identity) identities = append(identities, identity) }) stringz.Permutations(serviceRoleAttrs, func(roles []string) { service := newEdgeService(eid.New()) - ctx.RequireCreate(service) + boltztest.RequireCreate(ctx, service) service.RoleAttributes = roles - ctx.RequireUpdate(service) + boltztest.RequireUpdate(ctx, service) services = append(services, service) }) @@ -283,7 +284,7 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { // ensure policies get cleaned up for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after identities/edge routers @@ -292,7 +293,7 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { ctx.validateServicePolicies(identities, services, policies) for _, policy := range policies { - ctx.RequireDelete(policy) + boltztest.RequireDelete(ctx, policy) } // test with policies created after identities/edge routers and roles added after created @@ -303,14 +304,14 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { for _, identity := range identities { if len(identity.RoleAttributes) > 0 { identity.RoleAttributes = identity.RoleAttributes[1:] - ctx.RequireUpdate(identity) + boltztest.RequireUpdate(ctx, identity) } } for _, service := range services { if len(service.RoleAttributes) > 0 { service.RoleAttributes = service.RoleAttributes[1:] - ctx.RequireUpdate(service) + boltztest.RequireUpdate(ctx, service) } } @@ -321,7 +322,7 @@ func (ctx *TestContext) testServicePolicyRoleEvaluation(_ *testing.T) { if len(policy.ServiceRoles) > 0 { policy.ServiceRoles = policy.ServiceRoles[1:] } - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } ctx.validateServicePolicies(identities, services, policies) @@ -332,7 +333,7 @@ func (ctx *TestContext) createServicePolicies(identityRoles, serviceRoles []stri for i := 0; i < 9; i++ { policy := newServicePolicy(eid.New()) if !oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } if i == 1 { policy.IdentityRoles = []string{identityRoles[0]} @@ -371,9 +372,9 @@ func (ctx *TestContext) createServicePolicies(identityRoles, serviceRoles []stri policies = append(policies, policy) if oncreate { - ctx.RequireCreate(policy) + boltztest.RequireCreate(ctx, policy) } else { - ctx.RequireUpdate(policy) + boltztest.RequireUpdate(ctx, policy) } } return policies @@ -430,8 +431,8 @@ func (ctx *TestContext) validateServicePolicyServices(services []*EdgeService, p func (ctx *TestContext) validateServicePolicyDenormalization() { errorHolder := &errorz.ErrorHolderImpl{} - errorHolder.SetError(ctx.db.View(func(tx *bbolt.Tx) error { - return ctx.stores.ServicePolicy.CheckIntegrity(tx, false, func(err error, _ bool) { + errorHolder.SetError(ctx.GetDb().View(func(tx *bbolt.Tx) error { + return ctx.stores.ServicePolicy.CheckIntegrity(ctx.newViewTestCtx(tx), false, func(err error, _ bool) { errorHolder.SetError(err) }) })) diff --git a/controller/persistence/session_store.go b/controller/persistence/session_store.go index 2ead1d8e8..6c9d8c1bd 100644 --- a/controller/persistence/session_store.go +++ b/controller/persistence/session_store.go @@ -51,67 +51,27 @@ type Session struct { ServicePolicies []string } -func (entity *Session) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { - entity.LoadBaseValues(bucket) - entity.Token = bucket.GetStringOrError(FieldSessionToken) - entity.ApiSessionId = bucket.GetStringOrError(FieldSessionApiSession) - entity.ServiceId = bucket.GetStringOrError(FieldSessionService) - entity.IdentityId = bucket.GetStringWithDefault(FieldSessionIdentity, "") - entity.Type = bucket.GetStringWithDefault(FieldSessionType, "Dial") - entity.ServicePolicies = bucket.GetStringList(FieldSessionServicePolicies) -} - -func (entity *Session) SetValues(ctx *boltz.PersistContext) { - if entity.Type == "" { - entity.Type = SessionTypeDial - } - - if !stringz.Contains(validSessionTypes, entity.Type) { - ctx.Bucket.SetError(errorz.NewFieldError("invalid session type", FieldSessionType, entity.Type)) - return - } - - entity.SetBaseValues(ctx) - if ctx.IsCreate { - ctx.SetString(FieldSessionToken, entity.Token) - ctx.SetString(FieldSessionApiSession, entity.ApiSessionId) - ctx.SetString(FieldSessionService, entity.ServiceId) - - sessionStore := ctx.Store.(*sessionStoreImpl) - _, identityId := sessionStore.stores.apiSession.symbolIdentity.Eval(ctx.Tx(), []byte(entity.ApiSessionId)) - entity.IdentityId = string(identityId) - - ctx.SetString(FieldSessionIdentity, entity.IdentityId) - ctx.SetString(FieldSessionType, entity.Type) - } - ctx.SetStringList(FieldSessionServicePolicies, entity.ServicePolicies) - - if entity.ApiSession == nil { - entity.ApiSession, _ = ctx.Store.(*sessionStoreImpl).stores.apiSession.LoadOneById(ctx.Bucket.Tx(), entity.ApiSessionId) - } -} - func (entity *Session) GetEntityType() string { return EntityTypeSessions } +var _ SessionStore = (*sessionStoreImpl)(nil) + type SessionStore interface { - Store - LoadOneById(tx *bbolt.Tx, id string) (*Session, error) + Store[*Session] LoadOneByToken(tx *bbolt.Tx, token string) (*Session, error) GetTokenIndex() boltz.ReadIndex } func newSessionStore(stores *stores) *sessionStoreImpl { - store := &sessionStoreImpl{ - baseStore: newBaseStore(stores, EntityTypeSessions), - } + store := &sessionStoreImpl{} + store.baseStore = newBaseStore[*Session](stores, store) store.InitImpl(store) return store } type sessionStoreImpl struct { - *baseStore + *baseStore[*Session] indexToken boltz.ReadIndex symbolApiSession boltz.EntitySymbol @@ -119,7 +79,7 @@ type sessionStoreImpl struct { symbolServicePolicies boltz.EntitySetSymbol } -func (store *sessionStoreImpl) NewStoreEntity() boltz.Entity { +func (store *sessionStoreImpl) NewEntity() *Session { return &Session{} } @@ -150,12 +110,44 @@ func (store *sessionStoreImpl) initializeLocal() { func (store *sessionStoreImpl) initializeLinked() {} -func (store *sessionStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Session, error) { - entity := &Session{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err +func (*sessionStoreImpl) FillEntity(entity *Session, bucket *boltz.TypedBucket) { + entity.LoadBaseValues(bucket) + entity.Token = bucket.GetStringOrError(FieldSessionToken) + entity.ApiSessionId = bucket.GetStringOrError(FieldSessionApiSession) + entity.ServiceId = bucket.GetStringOrError(FieldSessionService) + entity.IdentityId = bucket.GetStringWithDefault(FieldSessionIdentity, "") + entity.Type = bucket.GetStringWithDefault(FieldSessionType, "Dial") + entity.ServicePolicies = bucket.GetStringList(FieldSessionServicePolicies) +} + +func (*sessionStoreImpl) PersistEntity(entity *Session, ctx *boltz.PersistContext) { + if entity.Type == "" { + entity.Type = SessionTypeDial + } + + if !stringz.Contains(validSessionTypes, entity.Type) { + ctx.Bucket.SetError(errorz.NewFieldError("invalid session type", FieldSessionType, entity.Type)) + return + } + + entity.SetBaseValues(ctx) + if ctx.IsCreate { + ctx.SetString(FieldSessionToken, entity.Token) + ctx.SetString(FieldSessionApiSession, entity.ApiSessionId) + ctx.SetString(FieldSessionService, entity.ServiceId) + + sessionStore := ctx.Store.(*sessionStoreImpl) + _, identityId := sessionStore.stores.apiSession.symbolIdentity.Eval(ctx.Tx(), []byte(entity.ApiSessionId)) + entity.IdentityId = string(identityId) + + ctx.SetString(FieldSessionIdentity, entity.IdentityId) + ctx.SetString(FieldSessionType, entity.Type) + } + ctx.SetStringList(FieldSessionServicePolicies, entity.ServicePolicies) + + if entity.ApiSession == nil { + entity.ApiSession, _ = ctx.Store.(*sessionStoreImpl).stores.apiSession.LoadOneById(ctx.Bucket.Tx(), entity.ApiSessionId) } - return entity, nil } func (store *sessionStoreImpl) LoadOneByToken(tx *bbolt.Tx, token string) (*Session, error) { @@ -170,7 +162,7 @@ type sessionApiSessionIndex struct { apiSessionSymbol boltz.EntitySymbol serviceSymbol boltz.EntitySymbol sessionTypeSymbol boltz.EntitySymbol - apiSessionStore boltz.ListStore + apiSessionStore boltz.Store } func (self *sessionApiSessionIndex) ProcessBeforeUpdate(*boltz.IndexingContext) {} @@ -212,6 +204,6 @@ func (self *sessionApiSessionIndex) ProcessBeforeDelete(*boltz.IndexingContext) func (self *sessionApiSessionIndex) Initialize(*bbolt.Tx, errorz.ErrorHolder) {} -func (self *sessionApiSessionIndex) CheckIntegrity(*bbolt.Tx, bool, func(err error, fixed bool)) error { +func (self *sessionApiSessionIndex) CheckIntegrity(boltz.MutateContext, bool, func(err error, fixed bool)) error { return nil } diff --git a/controller/persistence/session_store_test.go b/controller/persistence/session_store_test.go index 8aaed131a..abb65a855 100644 --- a/controller/persistence/session_store_test.go +++ b/controller/persistence/session_store_test.go @@ -21,9 +21,11 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/db" "github.com/openziti/foundation/v2/stringz" "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "go.etcd.io/bbolt" "testing" "time" @@ -49,31 +51,31 @@ func (ctx *TestContext) testCreateInvalidSessions(_ *testing.T) { identity := ctx.RequireNewIdentity("test-user", false) apiSession := NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) service := ctx.RequireNewService("test-service") session := NewSession("", service.Id) - err := ctx.Create(session) + err := boltztest.Create(ctx, session) ctx.EqualError(err, "fk constraint on sessions.apiSession does not allow null or empty values") session.ApiSessionId = "invalid-id" - err = ctx.Create(session) + err = boltztest.Create(ctx, session) ctx.EqualError(err, fmt.Sprintf("apiSession with id %v not found", session.ApiSessionId)) session.ApiSessionId = apiSession.Id session.ServiceId = "" - err = ctx.Create(session) + err = boltztest.Create(ctx, session) ctx.EqualError(err, "fk constraint on sessions.service does not allow null or empty values") session.ServiceId = "invalid-id" - err = ctx.Create(session) + err = boltztest.Create(ctx, session) ctx.EqualError(err, fmt.Sprintf("service with id %v not found", session.ServiceId)) session.ServiceId = service.Id - err = ctx.Create(session) + err = boltztest.Create(ctx, session) ctx.NoError(err) - err = ctx.Create(session) + err = boltztest.Create(ctx, session) ctx.EqualError(err, fmt.Sprintf("an entity of type session already exists with id %v", session.Id)) } @@ -82,12 +84,12 @@ func (ctx *TestContext) testUpdateInvalidSessions(_ *testing.T) { identity := ctx.RequireNewIdentity("test-user", false) apiSession := NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) service := ctx.RequireNewService("test-service") session := NewSession(apiSession.Id, service.Id) - ctx.RequireCreate(session) + boltztest.RequireCreate(ctx, session) token := session.Token @@ -96,9 +98,9 @@ func (ctx *TestContext) testUpdateInvalidSessions(_ *testing.T) { session.Token = "different token" session.IdentityId = "different id" session.Type = PolicyTypeBindName - ctx.RequireUpdate(session) + boltztest.RequireUpdate(ctx, session) - err := ctx.db.View(func(tx *bbolt.Tx) error { + err := ctx.GetDb().View(func(tx *bbolt.Tx) error { loaded, err := ctx.stores.Session.LoadOneById(tx, session.Id) ctx.NoError(err) ctx.NotNil(loaded) @@ -111,9 +113,9 @@ func (ctx *TestContext) testUpdateInvalidSessions(_ *testing.T) { }) ctx.NoError(err) - ctx.RequireDelete(session, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, session, apiSessionsSessionsIdxPath) - err = ctx.Update(session) + err = boltztest.Update(ctx, session) ctx.EqualError(err, fmt.Sprintf("session with id %v not found", session.Id)) } @@ -124,23 +126,23 @@ func (ctx *TestContext) testCreateSessions(_ *testing.T) { identity := ctx.RequireNewIdentity("Jojo", false) apiSession := NewApiSession(identity.Id) - ctx.RequireCreate(apiSession) + boltztest.RequireCreate(ctx, apiSession) service := ctx.RequireNewService("test-service") session := NewSession(apiSession.Id, service.Id) - ctx.RequireCreate(session) - ctx.ValidateBaseline(session, compareOpts) + boltztest.RequireCreate(ctx, session) + boltztest.ValidateBaseline(ctx, session, compareOpts) service2 := ctx.RequireNewService("test-service-2") session3 := NewSession(apiSession.Id, service2.Id) session3.Tags = ctx.CreateTags() - ctx.RequireCreate(session3) - ctx.ValidateBaseline(session3, compareOpts) + boltztest.RequireCreate(ctx, session3) + boltztest.ValidateBaseline(ctx, session3, compareOpts) - ctx.RequireDelete(service2, apiSessionsSessionsIdxPath) - ctx.ValidateDeleted(session3.Id, apiSessionsSessionsIdxPath) - ctx.RequireReload(session) + boltztest.RequireDelete(ctx, service2, apiSessionsSessionsIdxPath) + boltztest.ValidateDeleted(ctx, session3.Id, apiSessionsSessionsIdxPath) + boltztest.RequireReload(ctx, session) - err := ctx.Delete(apiSession) + err := boltztest.Delete(ctx, apiSession) ctx.NoError(err) done, err := ctx.GetStores().EventualEventer.Trigger() @@ -153,14 +155,8 @@ func (ctx *TestContext) testCreateSessions(_ *testing.T) { } - ctx.ValidateDeleted(session.Id) - ctx.ValidateDeleted(apiSession.GetId()) -} - -func (ctx *TestContext) RequireDelete(entity boltz.Entity, ignoredPaths ...string) { - err := ctx.Delete(entity) - ctx.NoError(err) - ctx.ValidateDeleted(entity.GetId(), ignoredPaths...) + boltztest.ValidateDeleted(ctx, session.Id) + boltztest.ValidateDeleted(ctx, apiSession.GetId()) } type sessionTestEntities struct { @@ -178,24 +174,24 @@ func (ctx *TestContext) createSessionTestEntities() *sessionTestEntities { identity1 := ctx.RequireNewIdentity("admin1", true) apiSession1 := NewApiSession(identity1.Id) - ctx.RequireCreate(apiSession1) + boltztest.RequireCreate(ctx, apiSession1) apiSession2 := NewApiSession(identity1.Id) - ctx.RequireCreate(apiSession2) + boltztest.RequireCreate(ctx, apiSession2) service1 := ctx.RequireNewService(eid.New()) service2 := ctx.RequireNewService(eid.New()) session1 := NewSession(apiSession1.Id, service1.Id) - ctx.RequireCreate(session1) + boltztest.RequireCreate(ctx, session1) session2 := NewSession(apiSession2.Id, service2.Id) - ctx.RequireCreate(session2) + boltztest.RequireCreate(ctx, session2) session3 := NewSession(apiSession2.Id, service2.Id) session3.Type = PolicyTypeBindName - ctx.RequireCreate(session3) + boltztest.RequireCreate(ctx, session3) return &sessionTestEntities{ identity1: identity1, @@ -238,7 +234,9 @@ func (ctx *TestContext) testUpdateSessions(_ *testing.T) { earlier := time.Now() time.Sleep(time.Millisecond * 50) - err := ctx.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx := change.New().SetSource("test").NewMutateContext() + err := ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { + tx := mutateCtx.Tx() original, err := ctx.stores.Session.LoadOneById(tx, entities.session1.Id) ctx.NoError(err) ctx.NotNil(original) @@ -253,7 +251,7 @@ func (ctx *TestContext) testUpdateSessions(_ *testing.T) { session.CreatedAt = now session.Tags = tags - err = ctx.stores.Session.Update(boltz.NewMutateContext(tx), session, nil) + err = ctx.stores.Session.Update(mutateCtx, session, nil) ctx.NoError(err) loaded, err := ctx.stores.Session.LoadOneById(tx, entities.session1.Id) ctx.NoError(err) @@ -271,9 +269,9 @@ func (ctx *TestContext) testUpdateSessions(_ *testing.T) { func (ctx *TestContext) testDeleteSessions(_ *testing.T) { ctx.CleanupAll() entities := ctx.createSessionTestEntities() - ctx.RequireDelete(entities.session1, apiSessionsSessionsIdxPath) - ctx.RequireDelete(entities.session2, apiSessionsSessionsIdxPath) - ctx.RequireDelete(entities.session3, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, entities.session1, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, entities.session2, apiSessionsSessionsIdxPath) + boltztest.RequireDelete(ctx, entities.session3, apiSessionsSessionsIdxPath) } func NewSession(apiSessionId, serviceId string) *Session { diff --git a/controller/persistence/stores.go b/controller/persistence/stores.go index 055d8247e..fbcfd0f27 100644 --- a/controller/persistence/stores.go +++ b/controller/persistence/stores.go @@ -17,6 +17,7 @@ package persistence import ( + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/db" "github.com/openziti/foundation/v2/errorz" "github.com/openziti/storage/ast" @@ -50,7 +51,7 @@ type Stores struct { EdgeService EdgeServiceStore Identity IdentityStore IdentityType IdentityTypeStore - Index boltz.ListStore + Index boltz.Store Session SessionStore ServiceEdgeRouterPolicy ServiceEdgeRouterPolicyStore ServicePolicy ServicePolicyStore @@ -60,7 +61,7 @@ type Stores struct { PostureCheck PostureCheckStore PostureCheckType PostureCheckTypeStore Mfa MfaStore - storeMap map[reflect.Type]boltz.CrudStore + storeMap map[reflect.Type]boltz.Store } func (stores *Stores) addStoresToIntegrityCheck(fabricStores *db.Stores) { @@ -69,7 +70,7 @@ func (stores *Stores) addStoresToIntegrityCheck(fabricStores *db.Stores) { f := val.Field(i) if f.CanInterface() { // filter by the edge Store interface, so we don't recheck fabric stores, which are already being checked - if store, ok := f.Interface().(Store); ok { + if store, ok := f.Interface().(boltz.Store); ok { fabricStores.AddCheckable(store) } } @@ -81,8 +82,8 @@ func (stores *Stores) buildStoreMap() { for i := 0; i < val.NumField(); i++ { f := val.Field(i) if f.CanInterface() { - if store, ok := f.Interface().(boltz.CrudStore); ok { - entityType := reflect.TypeOf(store.NewStoreEntity()) + if store, ok := f.Interface().(boltz.Store); ok && store.GetEntityType() != "indexes" { + entityType := store.GetEntityReflectType() stores.storeMap[entityType] = store } } @@ -118,17 +119,17 @@ func (stores *Stores) GetEntityCounts(dbProvider DbProvider) (map[string]int64, return result, nil } -func (stores *Stores) getStoresForInit() []Store { - var result []Store +func (stores *Stores) getStoresForInit() []initializableStore { + var result []initializableStore for _, crudStore := range stores.storeMap { - if store, ok := crudStore.(Store); ok { + if store, ok := crudStore.(initializableStore); ok { result = append(result, store) } } return result } -func (stores *Stores) GetStoreForEntity(entity boltz.Entity) boltz.CrudStore { +func (stores *Stores) GetStoreForEntity(entity boltz.Entity) boltz.Store { return stores.storeMap[reflect.TypeOf(entity)] } @@ -231,22 +232,31 @@ func NewBoltStores(dbProvider DbProvider) (*Stores, error) { PostureCheckType: internalStores.postureCheckType, Mfa: internalStores.mfa, - storeMap: make(map[reflect.Type]boltz.CrudStore), + storeMap: make(map[reflect.Type]boltz.Store), } externalStores.EventualEventer = internalStores.EventualEventer // The Index store is used for querying indexes. It's a convenient store with only a single value (id), which // is only ever queried using an index set cursor - externalStores.Index = boltz.NewBaseStore("invalid", func(id string) error { - return errors.Errorf("should never happen") - }) - externalStores.Index.AddIdSymbol("id", ast.NodeTypeString) + indexStoreDef := boltz.StoreDefinition[boltz.ExtEntity]{ + EntityType: "indexes", + BasePath: []string{db.RootBucket}, + EntityNotFoundF: func(id string) error { + panic(errors.New("programming error")) + }, + } + + indexStore := boltz.NewBaseStore(indexStoreDef) + indexStore.AddIdSymbol("id", ast.NodeTypeString) + + externalStores.Index = indexStore externalStores.buildStoreMap() storeList := externalStores.getStoresForInit() - err := dbProvider.GetDb().Update(func(tx *bbolt.Tx) error { + mutateCtx := change.New().SetSource("system.initialization").SetChangeAuthorType("controller").NewMutateContext() + err := dbProvider.GetDb().Update(mutateCtx, func(ctx boltz.MutateContext) error { for _, store := range storeList { store.initializeLocal() } @@ -254,7 +264,7 @@ func NewBoltStores(dbProvider DbProvider) (*Stores, error) { store.initializeLinked() } for _, store := range storeList { - store.initializeIndexes(tx, errorHolder) + store.initializeIndexes(ctx.Tx(), errorHolder) } return nil }) @@ -267,3 +277,21 @@ func NewBoltStores(dbProvider DbProvider) (*Stores, error) { } return externalStores, nil } + +func newBaseStore[E boltz.ExtEntity](stores *stores, strategy boltz.EntityStrategy[E]) *baseStore[E] { + return &baseStore[E]{ + stores: stores, + BaseStore: boltz.NewBaseStore(db.NewStoreDefinition[E](strategy)), + } +} + +func newChildBaseStore[E boltz.ExtEntity](stores *stores, parentMapper func(entity boltz.Entity) boltz.Entity, strategy boltz.EntityStrategy[E], parent boltz.Store, path string) *baseStore[E] { + def := db.NewStoreDefinition[E](strategy) + def.BasePath = []string{path} + def.Parent = parent + def.ParentMapper = parentMapper + return &baseStore[E]{ + stores: stores, + BaseStore: boltz.NewBaseStore[E](def), + } +} diff --git a/controller/persistence/testing.go b/controller/persistence/testing.go index 212b1aa2e..745ffe03a 100644 --- a/controller/persistence/testing.go +++ b/controller/persistence/testing.go @@ -19,6 +19,7 @@ package persistence import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/eid" + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/command" "github.com/openziti/fabric/controller/db" "github.com/openziti/fabric/controller/network" @@ -31,6 +32,7 @@ import ( "github.com/openziti/identity" "github.com/openziti/metrics" "github.com/openziti/storage/boltz" + "github.com/openziti/storage/boltztest" "github.com/pkg/errors" "go.etcd.io/bbolt" "testing" @@ -115,8 +117,7 @@ func (p *testDbProvider) GetManagers() *network.Managers { } type TestContext struct { - boltz.BaseTestContext - db boltz.Db + boltztest.BaseTestContext n *network.Network stores *Stores closeNotify chan struct{} @@ -126,13 +127,16 @@ func NewTestContext(t *testing.T) *TestContext { xt.GlobalRegistry().RegisterFactory(xt_smartrouting.NewFactory()) result := &TestContext{ - BaseTestContext: *boltz.NewTestContext(t), - closeNotify: make(chan struct{}, 1), + closeNotify: make(chan struct{}, 1), } - result.Impl = result + result.BaseTestContext = *boltztest.NewTestContext(t, result.GetStoreForEntity) return result } +func (ctx *TestContext) newViewTestCtx(tx *bbolt.Tx) boltz.MutateContext { + return boltz.NewTxMutateContext(change.New().SetSource("test").GetContext(), tx) +} + func (ctx *TestContext) GetNetwork() *network.Network { return ctx.n } @@ -147,10 +151,10 @@ func (ctx *TestContext) GetStores() *Stores { } func (ctx *TestContext) GetDb() boltz.Db { - return ctx.db + return ctx.BaseTestContext.GetDb() } -func (ctx *TestContext) GetStoreForEntity(entity boltz.Entity) boltz.CrudStore { +func (ctx *TestContext) GetStoreForEntity(entity boltz.Entity) boltz.Store { if _, ok := entity.(*db.Service); ok { return ctx.n.GetStores().Service } @@ -162,23 +166,12 @@ func (ctx *TestContext) GetDbProvider() DbProvider { } func (ctx *TestContext) Init() { - ctx.BaseTestContext.InitDbFile() - ctx.InitWithDbFile(ctx.GetDbFile().Name()) -} - -func (ctx *TestContext) InitWithDbFile(path string) { - if path == "" { - ctx.BaseTestContext.InitDbFile() - path = ctx.GetDbFile().Name() - } - - var err error - ctx.db, err = db.Open(path) - ctx.NoError(err) + ctx.BaseTestContext.InitDb(db.Open) dbProvider := ctx.GetDbProvider() config := newTestConfig(ctx) + var err error ctx.n, err = network.NewNetwork(config) ctx.NoError(err) @@ -201,18 +194,18 @@ func (ctx *TestContext) requireNewServicePolicy(policyType PolicyType, identityR IdentityRoles: identityRoles, ServiceRoles: serviceRoles, } - ctx.RequireCreate(entity) + boltztest.RequireCreate(ctx, entity) return entity } func (ctx *TestContext) RequireNewIdentity(name string, isAdmin bool) *Identity { - identity := &Identity{ + identityEntity := &Identity{ BaseExtEntity: *boltz.NewExtEntity(eid.New(), nil), Name: name, IsAdmin: isAdmin, } - ctx.RequireCreate(identity) - return identity + boltztest.RequireCreate(ctx, identityEntity) + return identityEntity } func (ctx *TestContext) RequireNewService(name string) *EdgeService { @@ -222,7 +215,7 @@ func (ctx *TestContext) RequireNewService(name string) *EdgeService { Name: name, }, } - ctx.RequireCreate(edgeService) + boltztest.RequireCreate(ctx, edgeService) return edgeService } @@ -241,7 +234,7 @@ func (ctx *TestContext) getRelatedIds(entity boltz.Entity, field string) []strin } func (ctx *TestContext) CleanupAll() { - stores := []boltz.CrudStore{ + stores := []boltz.Store{ ctx.stores.Session, ctx.stores.ApiSession, ctx.stores.Service, @@ -254,10 +247,11 @@ func (ctx *TestContext) CleanupAll() { ctx.stores.ServicePolicy, ctx.stores.ServiceEdgeRouterPolicy, } - _ = ctx.GetDb().Update(func(tx *bbolt.Tx) error { - mutateContext := boltz.NewMutateContext(tx) + + mutateCtx := change.New().SetSource("test.cleanup").NewMutateContext() + _ = ctx.GetDb().Update(mutateCtx, func(mutateCtx boltz.MutateContext) error { for _, store := range stores { - if err := store.DeleteWhere(mutateContext, `true limit none`); err != nil { + if err := store.DeleteWhere(mutateCtx, `true limit none`); err != nil { pfxlog.Logger().WithError(err).Errorf("failure while cleaning up %v", store.GetEntityType()) return err } diff --git a/controller/persistence/transit_router_store.go b/controller/persistence/transit_router_store.go index b75370ee9..f97260171 100644 --- a/controller/persistence/transit_router_store.go +++ b/controller/persistence/transit_router_store.go @@ -20,7 +20,6 @@ import ( "fmt" "github.com/openziti/fabric/controller/db" "github.com/openziti/storage/boltz" - "go.etcd.io/bbolt" ) const ( @@ -38,43 +37,15 @@ type TransitRouter struct { UnverifiedFingerprint *string } -func (entity *TransitRouter) LoadValues(store boltz.CrudStore, bucket *boltz.TypedBucket) { - _, err := store.GetParentStore().BaseLoadOneById(bucket.Tx(), entity.Id, &entity.Router) - bucket.SetError(err) - - if bucket.Bucket == nil { - entity.IsVerified = true - entity.IsBase = true - return - } - - entity.IsVerified = bucket.GetBoolWithDefault(FieldTransitRouterIsVerified, false) - entity.Enrollments = bucket.GetStringList(FieldTransitRouterEnrollments) - entity.UnverifiedFingerprint = bucket.GetString(FieldEdgeRouterUnverifiedFingerprint) - entity.UnverifiedCertPem = bucket.GetString(FieldEdgeRouterUnverifiedCertPEM) -} - -func (entity *TransitRouter) SetValues(ctx *boltz.PersistContext) { - entity.Router.SetValues(ctx.GetParentContext()) - if ctx.Bucket != nil { - ctx.SetBool(FieldTransitRouterIsVerified, entity.IsVerified) - ctx.SetStringP(FieldEdgeRouterUnverifiedFingerprint, entity.UnverifiedFingerprint) - ctx.SetStringP(FieldEdgeRouterUnverifiedCertPEM, entity.UnverifiedCertPem) - } -} - -func (entity *TransitRouter) GetEntityType() string { - return db.EntityTypeRouters -} - func (entity *TransitRouter) GetName() string { return entity.Name } +var _ TransitRouterStore = (*transitRouterStoreImpl)(nil) + type TransitRouterStore interface { - NameIndexedStore - LoadOneById(tx *bbolt.Tx, id string) (*TransitRouter, error) - LoadOneByName(tx *bbolt.Tx, id string) (*TransitRouter, error) + NameIndexed + Store[*TransitRouter] } func newTransitRouterStore(stores *stores) *transitRouterStoreImpl { @@ -86,20 +57,42 @@ func newTransitRouterStore(stores *stores) *transitRouterStoreImpl { } store := &transitRouterStoreImpl{} - stores.Router.AddDeleteHandler(store.cleanupEnrollments) // do cleanup first - store.baseStore = newExtendedBaseStore(stores, stores.Router, parentMapper, TransitRouterPath) + store.baseStore = newChildBaseStore[*TransitRouter](stores, parentMapper, store, stores.Router, TransitRouterPath) + store.Extended() + store.InitImpl(store) return store } type transitRouterStoreImpl struct { - *baseStore + *baseStore[*TransitRouter] indexName boltz.ReadIndex symbolEnrollments boltz.EntitySetSymbol } -func (store *transitRouterStoreImpl) NewStoreEntity() boltz.Entity { +func (store *transitRouterStoreImpl) HandleUpdate(ctx boltz.MutateContext, entity *db.Router, checker boltz.FieldChecker) (bool, error) { + er, found, err := store.FindById(ctx.Tx(), entity.Id) + if err != nil { + return false, err + } + if !found { + return false, nil + } + + er.Router = *entity + return true, store.Update(ctx, er, checker) +} + +func (store *transitRouterStoreImpl) HandleDelete(ctx boltz.MutateContext, entity *db.Router) error { + return store.cleanupEnrollments(ctx, entity.Id) +} + +func (store *transitRouterStoreImpl) GetStore() boltz.Store { + return store +} + +func (store *transitRouterStoreImpl) NewEntity() *TransitRouter { return &TransitRouter{} } @@ -116,28 +109,28 @@ func (store *transitRouterStoreImpl) GetNameIndex() boltz.ReadIndex { return store.indexName } -func (store *transitRouterStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*TransitRouter, error) { - entity := &TransitRouter{} - if err := store.baseLoadOneById(tx, id, entity); err != nil { - return nil, err +func (store *transitRouterStoreImpl) FillEntity(entity *TransitRouter, bucket *boltz.TypedBucket) { + store.stores.Router.FillEntity(&entity.Router, store.getParentBucket(entity, bucket)) + + if bucket.Bucket == nil { + entity.IsVerified = true + entity.IsBase = true + return } - return entity, nil + + entity.IsVerified = bucket.GetBoolWithDefault(FieldTransitRouterIsVerified, false) + entity.Enrollments = bucket.GetStringList(FieldTransitRouterEnrollments) + entity.UnverifiedFingerprint = bucket.GetString(FieldEdgeRouterUnverifiedFingerprint) + entity.UnverifiedCertPem = bucket.GetString(FieldEdgeRouterUnverifiedCertPEM) } -func (store *transitRouterStoreImpl) LoadOneByName(tx *bbolt.Tx, name string) (*TransitRouter, error) { - id := store.indexName.Read(tx, []byte(name)) - if id != nil { - return store.LoadOneById(tx, string(id)) +func (store *transitRouterStoreImpl) PersistEntity(entity *TransitRouter, ctx *boltz.PersistContext) { + store.stores.Router.PersistEntity(&entity.Router, ctx.GetParentContext()) + if ctx.Bucket != nil { + ctx.SetBool(FieldTransitRouterIsVerified, entity.IsVerified) + ctx.SetStringP(FieldEdgeRouterUnverifiedFingerprint, entity.UnverifiedFingerprint) + ctx.SetStringP(FieldEdgeRouterUnverifiedCertPEM, entity.UnverifiedCertPem) } - return nil, nil -} - -func (store *transitRouterStoreImpl) LoadOneByQuery(tx *bbolt.Tx, query string) (*TransitRouter, error) { - entity := &TransitRouter{} - if found, err := store.BaseLoadOneByQuery(tx, query, entity); !found || err != nil { - return nil, err - } - return entity, nil } func (store *transitRouterStoreImpl) cleanupEnrollments(ctx boltz.MutateContext, id string) error { diff --git a/controller/response/context.go b/controller/response/context.go index a597cf9eb..9455f7632 100644 --- a/controller/response/context.go +++ b/controller/response/context.go @@ -18,7 +18,9 @@ package response import ( "errors" + "fmt" "github.com/openziti/edge/controller/model" + "github.com/openziti/fabric/controller/change" "net/http" "time" ) @@ -92,3 +94,17 @@ func (rc *RequestContext) GetEntitySubId() (string, error) { return rc.entitySubId, nil } + +func (rc *RequestContext) NewChangeContext() *change.Context { + src := fmt.Sprintf("rest[auth=edge/host=%v/method=%v/remote=%v]", rc.GetRequest().Host, rc.GetRequest().Method, rc.GetRequest().RemoteAddr) + changeCtx := change.New().SetSource(src) + + if rc.Identity != nil { + changeCtx.SetChangeAuthorId(rc.Identity.Id).SetChangeAuthorName(rc.Identity.Name) + } + + if rc.Request.Form.Has("traceId") { + changeCtx.SetTraceId(rc.Request.Form.Get("traceId")) + } + return changeCtx +} diff --git a/events/dispatcher_api_session.go b/events/dispatcher_api_session.go index 5835d0573..f878e5cc3 100644 --- a/events/dispatcher_api_session.go +++ b/events/dispatcher_api_session.go @@ -18,7 +18,6 @@ package events import ( "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" "github.com/openziti/foundation/v2/stringz" "github.com/openziti/storage/boltz" @@ -44,22 +43,11 @@ func (self *Dispatcher) RemoveApiSessionEventHandler(handler ApiSessionEventHand } func (self *Dispatcher) initApiSessionEvents(stores *persistence.Stores) { - stores.ApiSession.AddListener(boltz.EventCreate, self.apiSessionCreated) - stores.ApiSession.AddListener(boltz.EventDelete, self.apiSessionDeleted) + stores.ApiSession.AddEntityEventListenerF(self.apiSessionCreated, boltz.EntityCreated) + stores.ApiSession.AddEntityEventListenerF(self.apiSessionDeleted, boltz.EntityDeleted) } -func (self *Dispatcher) apiSessionCreated(args ...interface{}) { - var apiSession *persistence.ApiSession - if len(args) == 1 { - apiSession, _ = args[0].(*persistence.ApiSession) - } - - if apiSession == nil { - log := pfxlog.Logger() - log.Error("could not cast event args to event details") - return - } - +func (self *Dispatcher) apiSessionCreated(apiSession *persistence.ApiSession) { event := &ApiSessionEvent{ Namespace: ApiSessionEventNS, EventType: ApiSessionEventTypeCreated, @@ -75,18 +63,7 @@ func (self *Dispatcher) apiSessionCreated(args ...interface{}) { } } -func (self *Dispatcher) apiSessionDeleted(args ...interface{}) { - var apiSession *persistence.ApiSession - if len(args) == 1 { - apiSession, _ = args[0].(*persistence.ApiSession) - } - - if apiSession == nil { - log := pfxlog.Logger() - log.Error("could not cast event args to event details") - return - } - +func (self *Dispatcher) apiSessionDeleted(apiSession *persistence.ApiSession) { event := &ApiSessionEvent{ Namespace: ApiSessionEventNS, EventType: ApiSessionEventTypeDeleted, diff --git a/events/dispatcher_session.go b/events/dispatcher_session.go index 0f87f968d..e64fb0178 100644 --- a/events/dispatcher_session.go +++ b/events/dispatcher_session.go @@ -18,7 +18,6 @@ package events import ( "fmt" - "github.com/michaelquigley/pfxlog" "github.com/openziti/edge/controller/persistence" "github.com/openziti/foundation/v2/stringz" "github.com/openziti/storage/boltz" @@ -44,22 +43,11 @@ func (self *Dispatcher) RemoveSessionEventHandler(handler SessionEventHandler) { } func (self *Dispatcher) initSessionEvents(stores *persistence.Stores) { - stores.Session.AddListener(boltz.EventCreate, self.sessionCreated) - stores.Session.AddListener(boltz.EventDelete, self.sessionDeleted) + stores.Session.AddEntityEventListenerF(self.sessionCreated, boltz.EntityCreated) + stores.Session.AddEntityEventListenerF(self.sessionDeleted, boltz.EntityDeleted) } -func (self *Dispatcher) sessionCreated(args ...interface{}) { - var session *persistence.Session - if len(args) == 1 { - session, _ = args[0].(*persistence.Session) - } - - if session == nil { - log := pfxlog.Logger() - log.Error("could not cast event args to event details") - return - } - +func (self *Dispatcher) sessionCreated(session *persistence.Session) { event := &SessionEvent{ Namespace: SessionEventNS, EventType: SessionEventTypeCreated, @@ -68,7 +56,7 @@ func (self *Dispatcher) sessionCreated(args ...interface{}) { Timestamp: time.Now(), Token: session.Token, ApiSessionId: session.ApiSessionId, - IdentityId: session.ApiSession.IdentityId, + IdentityId: session.IdentityId, ServiceId: session.ServiceId, } @@ -77,18 +65,7 @@ func (self *Dispatcher) sessionCreated(args ...interface{}) { } } -func (self *Dispatcher) sessionDeleted(args ...interface{}) { - var session *persistence.Session - if len(args) == 1 { - session, _ = args[0].(*persistence.Session) - } - - if session == nil { - log := pfxlog.Logger() - log.Error("could not cast event args to event details") - return - } - +func (self *Dispatcher) sessionDeleted(session *persistence.Session) { event := &SessionEvent{ Namespace: SessionEventNS, EventType: SessionEventTypeDeleted, diff --git a/go.mod b/go.mod index 7ac08cec3..d7c9e0372 100644 --- a/go.mod +++ b/go.mod @@ -28,16 +28,16 @@ require ( github.com/miekg/dns v1.1.53 github.com/mitchellh/mapstructure v1.5.0 github.com/netfoundry/secretstream v0.1.5 - github.com/openziti/channel/v2 v2.0.60 + github.com/openziti/channel/v2 v2.0.62 github.com/openziti/edge-api v0.25.11 - github.com/openziti/fabric v0.22.94 + github.com/openziti/fabric v0.23.0 github.com/openziti/foundation/v2 v2.0.21 github.com/openziti/identity v1.0.47 github.com/openziti/jwks v1.0.3 github.com/openziti/metrics v1.2.19 github.com/openziti/sdk-golang v0.18.76 - github.com/openziti/storage v0.1.49 - github.com/openziti/transport/v2 v2.0.74 + github.com/openziti/storage v0.2.0 + github.com/openziti/transport/v2 v2.0.75 github.com/openziti/x509-claims v1.0.3 github.com/openziti/xweb/v2 v2.0.2 github.com/orcaman/concurrent-map/v2 v2.0.1 @@ -112,7 +112,8 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/rabbitmq/amqp091-go v1.8.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.2 // indirect + github.com/shirou/gopsutil/v3 v3.23.3 // indirect + github.com/shoenig/go-m1cpu v0.1.5 // indirect github.com/speps/go-hashids v2.0.0+incompatible // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect @@ -123,7 +124,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect golang.org/x/mod v0.7.0 // indirect golang.org/x/net v0.9.0 // indirect golang.org/x/term v0.7.0 // indirect diff --git a/go.sum b/go.sum index 900b1b67f..afa38ac67 100644 --- a/go.sum +++ b/go.sum @@ -453,12 +453,12 @@ github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7 github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openziti/channel/v2 v2.0.60 h1:TytQ0fyBH2zHJUzYsAjHrbVCR/e9tOSAroEhZKOBusg= -github.com/openziti/channel/v2 v2.0.60/go.mod h1:Iz/TYnJ3h1AWIpkYTD7vQBhfDJp+G7z7zmgWB7grEvc= +github.com/openziti/channel/v2 v2.0.62 h1:WmNYAugoyQ2HFu2VEhOH4WExzXsX6+dzSQDzNfHf5M8= +github.com/openziti/channel/v2 v2.0.62/go.mod h1:TS2FJs1GuCZXUfSFfptrNWKeTuQRO7YJ9K7C2jWMznA= github.com/openziti/edge-api v0.25.11 h1:HHjDgoybPZGRZ+tM2udehI+U5Xv991iGED8E6CtDb9w= github.com/openziti/edge-api v0.25.11/go.mod h1:PBFMYELgr7JUuaCqHobq1U+WESsutzgEDoELU/9qFOg= -github.com/openziti/fabric v0.22.94 h1:/wp92+2+sIPaW7g676yDcTRhE4i9/BjejyGcdSZHOBE= -github.com/openziti/fabric v0.22.94/go.mod h1:TuuifUPNO9krOofHNjXv21K0Prx/IPf+C90sF1kpfbQ= +github.com/openziti/fabric v0.23.0 h1:JXaHBb31+4hEsv04IUNxs11+s3nupQtzckR+cEIySuE= +github.com/openziti/fabric v0.23.0/go.mod h1:p5EI0s0LvNi6HipLR+PWDon89C3dhfyX/jac/3cwmpA= github.com/openziti/foundation/v2 v2.0.21 h1:3EDDmSunsbd2DlULuY/vqj12LHRZOknH/m3lf6Ws5Nw= github.com/openziti/foundation/v2 v2.0.21/go.mod h1:02GW3jFSSlfLwYwuTIldP/S4w7eCKqlzL6ajFSGHNPA= github.com/openziti/identity v1.0.47 h1:Zc1wL4yMq6hcmbgNR6d3gSkGCiK3IJYd9i4obBNBMPw= @@ -469,10 +469,10 @@ github.com/openziti/metrics v1.2.19 h1:gQO3e2lUotRHBdGUXYBPWMIErIyyF5hw0EakwQbJz github.com/openziti/metrics v1.2.19/go.mod h1:ovvxTpDBxGLcVLHgPTFFvwT4ur8p4Z76BPUhIE5iwqc= github.com/openziti/sdk-golang v0.18.76 h1:D+UW1lpGHBBgfVrObpauq9RvJV/TFPdEEshfuPkiMcI= github.com/openziti/sdk-golang v0.18.76/go.mod h1:kw/5rWDLwx52iwW/4a0VRQMUi7GPSI3aETx+G5TvdFQ= -github.com/openziti/storage v0.1.49 h1:luRsssYlGhpiJxjgc+FWF/yd2JLs9IKfeKID/5Hknrg= -github.com/openziti/storage v0.1.49/go.mod h1:Le2VFNL67YewLtaCnGNXPLH18Yrh/EMxeJ/eXxTOwak= -github.com/openziti/transport/v2 v2.0.74 h1:sFy395WPYWedArh4mBXtNb+FGR3gymk8cR/b6rCUltQ= -github.com/openziti/transport/v2 v2.0.74/go.mod h1:xMoDhxk9FFQoVyh4YL2h1hOshE5Aqlabd4mctmK1TWU= +github.com/openziti/storage v0.2.0 h1:uwSoZQEZCzxp4+KZEi7fOWezbm0knmcCbRhni/DGHSo= +github.com/openziti/storage v0.2.0/go.mod h1:rJjLObUtJBNcm7MvnTr4DHCXZ+ppg0OMeoJ5tfi1aJI= +github.com/openziti/transport/v2 v2.0.75 h1:KZmnyRH1SOXSI6DXqDRsbRxRJE2cWv5EDCiQqC+R+hQ= +github.com/openziti/transport/v2 v2.0.75/go.mod h1:xMoDhxk9FFQoVyh4YL2h1hOshE5Aqlabd4mctmK1TWU= github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0= github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE= github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU= @@ -524,8 +524,13 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU= -github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M= +github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= +github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= +github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= +github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= +github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -653,8 +658,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -828,7 +833,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pb/edge_cmd_pb/edge_cmd.pb.go b/pb/edge_cmd_pb/edge_cmd.pb.go index 45805e0ff..ad14ffd45 100644 --- a/pb/edge_cmd_pb/edge_cmd.pb.go +++ b/pb/edge_cmd_pb/edge_cmd.pb.go @@ -30,6 +30,7 @@ const ( CommandType_CreateEdgeRouterType CommandType = 1002 CommandType_CreateTransitRouterType CommandType = 1003 CommandType_CreateIdentityWithEnrollmentsType CommandType = 1004 + CommandType_UpdateServiceConfigsType CommandType = 1005 ) // Enum value maps for CommandType. @@ -41,6 +42,7 @@ var ( 1002: "CreateEdgeRouterType", 1003: "CreateTransitRouterType", 1004: "CreateIdentityWithEnrollmentsType", + 1005: "UpdateServiceConfigsType", } CommandType_value = map[string]int32{ "Zero": 0, @@ -49,6 +51,7 @@ var ( "CreateEdgeRouterType": 1002, "CreateTransitRouterType": 1003, "CreateIdentityWithEnrollmentsType": 1004, + "UpdateServiceConfigsType": 1005, } ) @@ -79,18 +82,74 @@ func (CommandType) EnumDescriptor() ([]byte, []int) { return file_edge_cmd_proto_rawDescGZIP(), []int{0} } +type ChangeContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Attributes map[string]string `protobuf:"bytes,1,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + RaftIndex uint64 `protobuf:"varint,2,opt,name=raftIndex,proto3" json:"raftIndex,omitempty"` +} + +func (x *ChangeContext) Reset() { + *x = ChangeContext{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_cmd_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChangeContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChangeContext) ProtoMessage() {} + +func (x *ChangeContext) ProtoReflect() protoreflect.Message { + mi := &file_edge_cmd_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChangeContext.ProtoReflect.Descriptor instead. +func (*ChangeContext) Descriptor() ([]byte, []int) { + return file_edge_cmd_proto_rawDescGZIP(), []int{0} +} + +func (x *ChangeContext) GetAttributes() map[string]string { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *ChangeContext) GetRaftIndex() uint64 { + if x != nil { + return x.RaftIndex + } + return 0 +} + type CreateEdgeTerminatorCommand struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TerminatorData []byte `protobuf:"bytes,1,opt,name=terminatorData,proto3" json:"terminatorData,omitempty"` + TerminatorData []byte `protobuf:"bytes,1,opt,name=terminatorData,proto3" json:"terminatorData,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,2,opt,name=ctx,proto3" json:"ctx,omitempty"` } func (x *CreateEdgeTerminatorCommand) Reset() { *x = CreateEdgeTerminatorCommand{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[0] + mi := &file_edge_cmd_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -103,7 +162,7 @@ func (x *CreateEdgeTerminatorCommand) String() string { func (*CreateEdgeTerminatorCommand) ProtoMessage() {} func (x *CreateEdgeTerminatorCommand) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[0] + mi := &file_edge_cmd_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -116,7 +175,7 @@ func (x *CreateEdgeTerminatorCommand) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateEdgeTerminatorCommand.ProtoReflect.Descriptor instead. func (*CreateEdgeTerminatorCommand) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{0} + return file_edge_cmd_proto_rawDescGZIP(), []int{1} } func (x *CreateEdgeTerminatorCommand) GetTerminatorData() []byte { @@ -126,6 +185,13 @@ func (x *CreateEdgeTerminatorCommand) GetTerminatorData() []byte { return nil } +func (x *CreateEdgeTerminatorCommand) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + type TagValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -142,7 +208,7 @@ type TagValue struct { func (x *TagValue) Reset() { *x = TagValue{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[1] + mi := &file_edge_cmd_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -155,7 +221,7 @@ func (x *TagValue) String() string { func (*TagValue) ProtoMessage() {} func (x *TagValue) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[1] + mi := &file_edge_cmd_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -168,7 +234,7 @@ func (x *TagValue) ProtoReflect() protoreflect.Message { // Deprecated: Use TagValue.ProtoReflect.Descriptor instead. func (*TagValue) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{1} + return file_edge_cmd_proto_rawDescGZIP(), []int{2} } func (m *TagValue) GetValue() isTagValue_Value { @@ -245,7 +311,7 @@ type JsonMap struct { func (x *JsonMap) Reset() { *x = JsonMap{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[2] + mi := &file_edge_cmd_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -258,7 +324,7 @@ func (x *JsonMap) String() string { func (*JsonMap) ProtoMessage() {} func (x *JsonMap) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[2] + mi := &file_edge_cmd_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -271,7 +337,7 @@ func (x *JsonMap) ProtoReflect() protoreflect.Message { // Deprecated: Use JsonMap.ProtoReflect.Descriptor instead. func (*JsonMap) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{2} + return file_edge_cmd_proto_rawDescGZIP(), []int{3} } func (x *JsonMap) GetValue() map[string]*JsonValue { @@ -292,7 +358,7 @@ type JsonList struct { func (x *JsonList) Reset() { *x = JsonList{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[3] + mi := &file_edge_cmd_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -305,7 +371,7 @@ func (x *JsonList) String() string { func (*JsonList) ProtoMessage() {} func (x *JsonList) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[3] + mi := &file_edge_cmd_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -318,7 +384,7 @@ func (x *JsonList) ProtoReflect() protoreflect.Message { // Deprecated: Use JsonList.ProtoReflect.Descriptor instead. func (*JsonList) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{3} + return file_edge_cmd_proto_rawDescGZIP(), []int{4} } func (x *JsonList) GetValue() []*JsonValue { @@ -347,7 +413,7 @@ type JsonValue struct { func (x *JsonValue) Reset() { *x = JsonValue{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[4] + mi := &file_edge_cmd_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -360,7 +426,7 @@ func (x *JsonValue) String() string { func (*JsonValue) ProtoMessage() {} func (x *JsonValue) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[4] + mi := &file_edge_cmd_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -373,7 +439,7 @@ func (x *JsonValue) ProtoReflect() protoreflect.Message { // Deprecated: Use JsonValue.ProtoReflect.Descriptor instead. func (*JsonValue) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{4} + return file_edge_cmd_proto_rawDescGZIP(), []int{5} } func (m *JsonValue) GetValue() isJsonValue_Value { @@ -496,7 +562,7 @@ type Authenticator struct { func (x *Authenticator) Reset() { *x = Authenticator{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[5] + mi := &file_edge_cmd_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -509,7 +575,7 @@ func (x *Authenticator) String() string { func (*Authenticator) ProtoMessage() {} func (x *Authenticator) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[5] + mi := &file_edge_cmd_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -522,7 +588,7 @@ func (x *Authenticator) ProtoReflect() protoreflect.Message { // Deprecated: Use Authenticator.ProtoReflect.Descriptor instead. func (*Authenticator) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{5} + return file_edge_cmd_proto_rawDescGZIP(), []int{6} } func (x *Authenticator) GetId() string { @@ -599,7 +665,7 @@ type AuthPolicy struct { func (x *AuthPolicy) Reset() { *x = AuthPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[6] + mi := &file_edge_cmd_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -612,7 +678,7 @@ func (x *AuthPolicy) String() string { func (*AuthPolicy) ProtoMessage() {} func (x *AuthPolicy) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[6] + mi := &file_edge_cmd_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -625,7 +691,7 @@ func (x *AuthPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy.ProtoReflect.Descriptor instead. func (*AuthPolicy) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6} + return file_edge_cmd_proto_rawDescGZIP(), []int{7} } func (x *AuthPolicy) GetId() string { @@ -687,7 +753,7 @@ type Ca struct { func (x *Ca) Reset() { *x = Ca{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[7] + mi := &file_edge_cmd_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -700,7 +766,7 @@ func (x *Ca) String() string { func (*Ca) ProtoMessage() {} func (x *Ca) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[7] + mi := &file_edge_cmd_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -713,7 +779,7 @@ func (x *Ca) ProtoReflect() protoreflect.Message { // Deprecated: Use Ca.ProtoReflect.Descriptor instead. func (*Ca) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{7} + return file_edge_cmd_proto_rawDescGZIP(), []int{8} } func (x *Ca) GetId() string { @@ -823,7 +889,7 @@ type Config struct { func (x *Config) Reset() { *x = Config{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[8] + mi := &file_edge_cmd_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -836,7 +902,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[8] + mi := &file_edge_cmd_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -849,7 +915,7 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{8} + return file_edge_cmd_proto_rawDescGZIP(), []int{9} } func (x *Config) GetId() string { @@ -902,7 +968,7 @@ type ConfigType struct { func (x *ConfigType) Reset() { *x = ConfigType{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[9] + mi := &file_edge_cmd_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -915,7 +981,7 @@ func (x *ConfigType) String() string { func (*ConfigType) ProtoMessage() {} func (x *ConfigType) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[9] + mi := &file_edge_cmd_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -928,7 +994,7 @@ func (x *ConfigType) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigType.ProtoReflect.Descriptor instead. func (*ConfigType) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{9} + return file_edge_cmd_proto_rawDescGZIP(), []int{10} } func (x *ConfigType) GetId() string { @@ -985,7 +1051,7 @@ type EdgeRouter struct { func (x *EdgeRouter) Reset() { *x = EdgeRouter{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[10] + mi := &file_edge_cmd_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -998,7 +1064,7 @@ func (x *EdgeRouter) String() string { func (*EdgeRouter) ProtoMessage() {} func (x *EdgeRouter) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[10] + mi := &file_edge_cmd_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1011,7 +1077,7 @@ func (x *EdgeRouter) ProtoReflect() protoreflect.Message { // Deprecated: Use EdgeRouter.ProtoReflect.Descriptor instead. func (*EdgeRouter) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{10} + return file_edge_cmd_proto_rawDescGZIP(), []int{11} } func (x *EdgeRouter) GetId() string { @@ -1124,14 +1190,15 @@ type CreateEdgeRouterCmd struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - EdgeRouter *EdgeRouter `protobuf:"bytes,1,opt,name=edgeRouter,proto3" json:"edgeRouter,omitempty"` - Enrollment *Enrollment `protobuf:"bytes,2,opt,name=enrollment,proto3" json:"enrollment,omitempty"` + EdgeRouter *EdgeRouter `protobuf:"bytes,1,opt,name=edgeRouter,proto3" json:"edgeRouter,omitempty"` + Enrollment *Enrollment `protobuf:"bytes,2,opt,name=enrollment,proto3" json:"enrollment,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,3,opt,name=ctx,proto3" json:"ctx,omitempty"` } func (x *CreateEdgeRouterCmd) Reset() { *x = CreateEdgeRouterCmd{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[11] + mi := &file_edge_cmd_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1144,7 +1211,7 @@ func (x *CreateEdgeRouterCmd) String() string { func (*CreateEdgeRouterCmd) ProtoMessage() {} func (x *CreateEdgeRouterCmd) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[11] + mi := &file_edge_cmd_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1157,7 +1224,7 @@ func (x *CreateEdgeRouterCmd) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateEdgeRouterCmd.ProtoReflect.Descriptor instead. func (*CreateEdgeRouterCmd) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{11} + return file_edge_cmd_proto_rawDescGZIP(), []int{12} } func (x *CreateEdgeRouterCmd) GetEdgeRouter() *EdgeRouter { @@ -1174,6 +1241,13 @@ func (x *CreateEdgeRouterCmd) GetEnrollment() *Enrollment { return nil } +func (x *CreateEdgeRouterCmd) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + // Edge Router Policies type EdgeRouterPolicy struct { state protoimpl.MessageState @@ -1191,7 +1265,7 @@ type EdgeRouterPolicy struct { func (x *EdgeRouterPolicy) Reset() { *x = EdgeRouterPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[12] + mi := &file_edge_cmd_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1204,7 +1278,7 @@ func (x *EdgeRouterPolicy) String() string { func (*EdgeRouterPolicy) ProtoMessage() {} func (x *EdgeRouterPolicy) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[12] + mi := &file_edge_cmd_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1217,7 +1291,7 @@ func (x *EdgeRouterPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use EdgeRouterPolicy.ProtoReflect.Descriptor instead. func (*EdgeRouterPolicy) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{12} + return file_edge_cmd_proto_rawDescGZIP(), []int{13} } func (x *EdgeRouterPolicy) GetId() string { @@ -1285,7 +1359,7 @@ type Enrollment struct { func (x *Enrollment) Reset() { *x = Enrollment{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[13] + mi := &file_edge_cmd_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1298,7 +1372,7 @@ func (x *Enrollment) String() string { func (*Enrollment) ProtoMessage() {} func (x *Enrollment) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[13] + mi := &file_edge_cmd_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1311,7 +1385,7 @@ func (x *Enrollment) ProtoReflect() protoreflect.Message { // Deprecated: Use Enrollment.ProtoReflect.Descriptor instead. func (*Enrollment) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{13} + return file_edge_cmd_proto_rawDescGZIP(), []int{14} } func (x *Enrollment) GetId() string { @@ -1405,12 +1479,13 @@ type ReplaceEnrollmentWithAuthenticatorCmd struct { EnrollmentId string `protobuf:"bytes,1,opt,name=enrollmentId,proto3" json:"enrollmentId,omitempty"` Authenticator *Authenticator `protobuf:"bytes,2,opt,name=authenticator,proto3" json:"authenticator,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,3,opt,name=ctx,proto3" json:"ctx,omitempty"` } func (x *ReplaceEnrollmentWithAuthenticatorCmd) Reset() { *x = ReplaceEnrollmentWithAuthenticatorCmd{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[14] + mi := &file_edge_cmd_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1423,7 +1498,7 @@ func (x *ReplaceEnrollmentWithAuthenticatorCmd) String() string { func (*ReplaceEnrollmentWithAuthenticatorCmd) ProtoMessage() {} func (x *ReplaceEnrollmentWithAuthenticatorCmd) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[14] + mi := &file_edge_cmd_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1436,7 +1511,7 @@ func (x *ReplaceEnrollmentWithAuthenticatorCmd) ProtoReflect() protoreflect.Mess // Deprecated: Use ReplaceEnrollmentWithAuthenticatorCmd.ProtoReflect.Descriptor instead. func (*ReplaceEnrollmentWithAuthenticatorCmd) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{14} + return file_edge_cmd_proto_rawDescGZIP(), []int{15} } func (x *ReplaceEnrollmentWithAuthenticatorCmd) GetEnrollmentId() string { @@ -1453,6 +1528,13 @@ func (x *ReplaceEnrollmentWithAuthenticatorCmd) GetAuthenticator() *Authenticato return nil } +func (x *ReplaceEnrollmentWithAuthenticatorCmd) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + // External JWT Signers type ExternalJwtSigner struct { state protoimpl.MessageState @@ -1480,7 +1562,7 @@ type ExternalJwtSigner struct { func (x *ExternalJwtSigner) Reset() { *x = ExternalJwtSigner{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[15] + mi := &file_edge_cmd_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1493,7 +1575,7 @@ func (x *ExternalJwtSigner) String() string { func (*ExternalJwtSigner) ProtoMessage() {} func (x *ExternalJwtSigner) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[15] + mi := &file_edge_cmd_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1506,7 +1588,7 @@ func (x *ExternalJwtSigner) ProtoReflect() protoreflect.Message { // Deprecated: Use ExternalJwtSigner.ProtoReflect.Descriptor instead. func (*ExternalJwtSigner) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{15} + return file_edge_cmd_proto_rawDescGZIP(), []int{16} } func (x *ExternalJwtSigner) GetId() string { @@ -1651,7 +1733,7 @@ type Identity struct { func (x *Identity) Reset() { *x = Identity{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[16] + mi := &file_edge_cmd_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1664,7 +1746,7 @@ func (x *Identity) String() string { func (*Identity) ProtoMessage() {} func (x *Identity) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[16] + mi := &file_edge_cmd_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1677,7 +1759,7 @@ func (x *Identity) ProtoReflect() protoreflect.Message { // Deprecated: Use Identity.ProtoReflect.Descriptor instead. func (*Identity) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{16} + return file_edge_cmd_proto_rawDescGZIP(), []int{17} } func (x *Identity) GetId() string { @@ -1818,14 +1900,15 @@ type CreateIdentityWithEnrollmentsCmd struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Identity *Identity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - Enrollments []*Enrollment `protobuf:"bytes,2,rep,name=enrollments,proto3" json:"enrollments,omitempty"` + Identity *Identity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + Enrollments []*Enrollment `protobuf:"bytes,2,rep,name=enrollments,proto3" json:"enrollments,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,3,opt,name=ctx,proto3" json:"ctx,omitempty"` } func (x *CreateIdentityWithEnrollmentsCmd) Reset() { *x = CreateIdentityWithEnrollmentsCmd{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[17] + mi := &file_edge_cmd_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1838,7 +1921,7 @@ func (x *CreateIdentityWithEnrollmentsCmd) String() string { func (*CreateIdentityWithEnrollmentsCmd) ProtoMessage() {} func (x *CreateIdentityWithEnrollmentsCmd) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[17] + mi := &file_edge_cmd_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1851,7 +1934,7 @@ func (x *CreateIdentityWithEnrollmentsCmd) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateIdentityWithEnrollmentsCmd.ProtoReflect.Descriptor instead. func (*CreateIdentityWithEnrollmentsCmd) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{17} + return file_edge_cmd_proto_rawDescGZIP(), []int{18} } func (x *CreateIdentityWithEnrollmentsCmd) GetIdentity() *Identity { @@ -1868,6 +1951,13 @@ func (x *CreateIdentityWithEnrollmentsCmd) GetEnrollments() []*Enrollment { return nil } +func (x *CreateIdentityWithEnrollmentsCmd) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + // MFA type Mfa struct { state protoimpl.MessageState @@ -1885,7 +1975,7 @@ type Mfa struct { func (x *Mfa) Reset() { *x = Mfa{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[18] + mi := &file_edge_cmd_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1898,7 +1988,7 @@ func (x *Mfa) String() string { func (*Mfa) ProtoMessage() {} func (x *Mfa) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[18] + mi := &file_edge_cmd_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1911,7 +2001,7 @@ func (x *Mfa) ProtoReflect() protoreflect.Message { // Deprecated: Use Mfa.ProtoReflect.Descriptor instead. func (*Mfa) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{18} + return file_edge_cmd_proto_rawDescGZIP(), []int{19} } func (x *Mfa) GetId() string { @@ -1981,7 +2071,7 @@ type PostureCheck struct { func (x *PostureCheck) Reset() { *x = PostureCheck{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[19] + mi := &file_edge_cmd_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1994,7 +2084,7 @@ func (x *PostureCheck) String() string { func (*PostureCheck) ProtoMessage() {} func (x *PostureCheck) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[19] + mi := &file_edge_cmd_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2007,7 +2097,7 @@ func (x *PostureCheck) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck.ProtoReflect.Descriptor instead. func (*PostureCheck) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19} + return file_edge_cmd_proto_rawDescGZIP(), []int{20} } func (x *PostureCheck) GetId() string { @@ -2159,7 +2249,7 @@ type Service struct { func (x *Service) Reset() { *x = Service{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[20] + mi := &file_edge_cmd_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2172,7 +2262,7 @@ func (x *Service) String() string { func (*Service) ProtoMessage() {} func (x *Service) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[20] + mi := &file_edge_cmd_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2185,7 +2275,7 @@ func (x *Service) ProtoReflect() protoreflect.Message { // Deprecated: Use Service.ProtoReflect.Descriptor instead. func (*Service) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{20} + return file_edge_cmd_proto_rawDescGZIP(), []int{21} } func (x *Service) GetId() string { @@ -2254,7 +2344,7 @@ type ServiceEdgeRouterPolicy struct { func (x *ServiceEdgeRouterPolicy) Reset() { *x = ServiceEdgeRouterPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[21] + mi := &file_edge_cmd_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2267,7 +2357,7 @@ func (x *ServiceEdgeRouterPolicy) String() string { func (*ServiceEdgeRouterPolicy) ProtoMessage() {} func (x *ServiceEdgeRouterPolicy) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[21] + mi := &file_edge_cmd_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2280,7 +2370,7 @@ func (x *ServiceEdgeRouterPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceEdgeRouterPolicy.ProtoReflect.Descriptor instead. func (*ServiceEdgeRouterPolicy) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{21} + return file_edge_cmd_proto_rawDescGZIP(), []int{22} } func (x *ServiceEdgeRouterPolicy) GetId() string { @@ -2344,7 +2434,7 @@ type ServicePolicy struct { func (x *ServicePolicy) Reset() { *x = ServicePolicy{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[22] + mi := &file_edge_cmd_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2357,7 +2447,7 @@ func (x *ServicePolicy) String() string { func (*ServicePolicy) ProtoMessage() {} func (x *ServicePolicy) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[22] + mi := &file_edge_cmd_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2370,7 +2460,7 @@ func (x *ServicePolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePolicy.ProtoReflect.Descriptor instead. func (*ServicePolicy) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{22} + return file_edge_cmd_proto_rawDescGZIP(), []int{23} } func (x *ServicePolicy) GetId() string { @@ -2450,7 +2540,7 @@ type TransitRouter struct { func (x *TransitRouter) Reset() { *x = TransitRouter{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[23] + mi := &file_edge_cmd_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2463,7 +2553,7 @@ func (x *TransitRouter) String() string { func (*TransitRouter) ProtoMessage() {} func (x *TransitRouter) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[23] + mi := &file_edge_cmd_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2476,7 +2566,7 @@ func (x *TransitRouter) ProtoReflect() protoreflect.Message { // Deprecated: Use TransitRouter.ProtoReflect.Descriptor instead. func (*TransitRouter) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{23} + return file_edge_cmd_proto_rawDescGZIP(), []int{24} } func (x *TransitRouter) GetId() string { @@ -2556,12 +2646,13 @@ type CreateTransitRouterCmd struct { Router *TransitRouter `protobuf:"bytes,1,opt,name=router,proto3" json:"router,omitempty"` Enrollment *Enrollment `protobuf:"bytes,2,opt,name=enrollment,proto3" json:"enrollment,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,3,opt,name=ctx,proto3" json:"ctx,omitempty"` } func (x *CreateTransitRouterCmd) Reset() { *x = CreateTransitRouterCmd{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[24] + mi := &file_edge_cmd_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2574,7 +2665,7 @@ func (x *CreateTransitRouterCmd) String() string { func (*CreateTransitRouterCmd) ProtoMessage() {} func (x *CreateTransitRouterCmd) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[24] + mi := &file_edge_cmd_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2587,7 +2678,7 @@ func (x *CreateTransitRouterCmd) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateTransitRouterCmd.ProtoReflect.Descriptor instead. func (*CreateTransitRouterCmd) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{24} + return file_edge_cmd_proto_rawDescGZIP(), []int{25} } func (x *CreateTransitRouterCmd) GetRouter() *TransitRouter { @@ -2604,6 +2695,84 @@ func (x *CreateTransitRouterCmd) GetEnrollment() *Enrollment { return nil } +func (x *CreateTransitRouterCmd) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + +type UpdateServiceConfigsCmd struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IdentityId string `protobuf:"bytes,1,opt,name=identityId,proto3" json:"identityId,omitempty"` + Add bool `protobuf:"varint,2,opt,name=add,proto3" json:"add,omitempty"` + ServiceConfigs []*UpdateServiceConfigsCmd_ServiceConfig `protobuf:"bytes,3,rep,name=serviceConfigs,proto3" json:"serviceConfigs,omitempty"` + Ctx *ChangeContext `protobuf:"bytes,4,opt,name=ctx,proto3" json:"ctx,omitempty"` +} + +func (x *UpdateServiceConfigsCmd) Reset() { + *x = UpdateServiceConfigsCmd{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_cmd_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateServiceConfigsCmd) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateServiceConfigsCmd) ProtoMessage() {} + +func (x *UpdateServiceConfigsCmd) ProtoReflect() protoreflect.Message { + mi := &file_edge_cmd_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateServiceConfigsCmd.ProtoReflect.Descriptor instead. +func (*UpdateServiceConfigsCmd) Descriptor() ([]byte, []int) { + return file_edge_cmd_proto_rawDescGZIP(), []int{26} +} + +func (x *UpdateServiceConfigsCmd) GetIdentityId() string { + if x != nil { + return x.IdentityId + } + return "" +} + +func (x *UpdateServiceConfigsCmd) GetAdd() bool { + if x != nil { + return x.Add + } + return false +} + +func (x *UpdateServiceConfigsCmd) GetServiceConfigs() []*UpdateServiceConfigsCmd_ServiceConfig { + if x != nil { + return x.ServiceConfigs + } + return nil +} + +func (x *UpdateServiceConfigsCmd) GetCtx() *ChangeContext { + if x != nil { + return x.Ctx + } + return nil +} + type Authenticator_Cert struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2618,7 +2787,7 @@ type Authenticator_Cert struct { func (x *Authenticator_Cert) Reset() { *x = Authenticator_Cert{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[26] + mi := &file_edge_cmd_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2631,7 +2800,7 @@ func (x *Authenticator_Cert) String() string { func (*Authenticator_Cert) ProtoMessage() {} func (x *Authenticator_Cert) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[26] + mi := &file_edge_cmd_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2644,7 +2813,7 @@ func (x *Authenticator_Cert) ProtoReflect() protoreflect.Message { // Deprecated: Use Authenticator_Cert.ProtoReflect.Descriptor instead. func (*Authenticator_Cert) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{5, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{6, 0} } func (x *Authenticator_Cert) GetFingerprint() string { @@ -2688,7 +2857,7 @@ type Authenticator_Updb struct { func (x *Authenticator_Updb) Reset() { *x = Authenticator_Updb{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[27] + mi := &file_edge_cmd_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2701,7 +2870,7 @@ func (x *Authenticator_Updb) String() string { func (*Authenticator_Updb) ProtoMessage() {} func (x *Authenticator_Updb) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[27] + mi := &file_edge_cmd_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2714,7 +2883,7 @@ func (x *Authenticator_Updb) ProtoReflect() protoreflect.Message { // Deprecated: Use Authenticator_Updb.ProtoReflect.Descriptor instead. func (*Authenticator_Updb) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{5, 1} + return file_edge_cmd_proto_rawDescGZIP(), []int{6, 1} } func (x *Authenticator_Updb) GetUsername() string { @@ -2751,7 +2920,7 @@ type AuthPolicy_Primary struct { func (x *AuthPolicy_Primary) Reset() { *x = AuthPolicy_Primary{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[29] + mi := &file_edge_cmd_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2764,7 +2933,7 @@ func (x *AuthPolicy_Primary) String() string { func (*AuthPolicy_Primary) ProtoMessage() {} func (x *AuthPolicy_Primary) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[29] + mi := &file_edge_cmd_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2777,7 +2946,7 @@ func (x *AuthPolicy_Primary) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy_Primary.ProtoReflect.Descriptor instead. func (*AuthPolicy_Primary) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{7, 0} } func (x *AuthPolicy_Primary) GetCert() *AuthPolicy_Primary_Cert { @@ -2813,7 +2982,7 @@ type AuthPolicy_Secondary struct { func (x *AuthPolicy_Secondary) Reset() { *x = AuthPolicy_Secondary{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[30] + mi := &file_edge_cmd_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2826,7 +2995,7 @@ func (x *AuthPolicy_Secondary) String() string { func (*AuthPolicy_Secondary) ProtoMessage() {} func (x *AuthPolicy_Secondary) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[30] + mi := &file_edge_cmd_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2839,7 +3008,7 @@ func (x *AuthPolicy_Secondary) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy_Secondary.ProtoReflect.Descriptor instead. func (*AuthPolicy_Secondary) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6, 1} + return file_edge_cmd_proto_rawDescGZIP(), []int{7, 1} } func (x *AuthPolicy_Secondary) GetRequireTotp() bool { @@ -2868,7 +3037,7 @@ type AuthPolicy_Primary_Cert struct { func (x *AuthPolicy_Primary_Cert) Reset() { *x = AuthPolicy_Primary_Cert{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[32] + mi := &file_edge_cmd_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2881,7 +3050,7 @@ func (x *AuthPolicy_Primary_Cert) String() string { func (*AuthPolicy_Primary_Cert) ProtoMessage() {} func (x *AuthPolicy_Primary_Cert) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[32] + mi := &file_edge_cmd_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2894,7 +3063,7 @@ func (x *AuthPolicy_Primary_Cert) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy_Primary_Cert.ProtoReflect.Descriptor instead. func (*AuthPolicy_Primary_Cert) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6, 0, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{7, 0, 0} } func (x *AuthPolicy_Primary_Cert) GetAllowed() bool { @@ -2928,7 +3097,7 @@ type AuthPolicy_Primary_Updb struct { func (x *AuthPolicy_Primary_Updb) Reset() { *x = AuthPolicy_Primary_Updb{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[33] + mi := &file_edge_cmd_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2941,7 +3110,7 @@ func (x *AuthPolicy_Primary_Updb) String() string { func (*AuthPolicy_Primary_Updb) ProtoMessage() {} func (x *AuthPolicy_Primary_Updb) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[33] + mi := &file_edge_cmd_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2954,7 +3123,7 @@ func (x *AuthPolicy_Primary_Updb) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy_Primary_Updb.ProtoReflect.Descriptor instead. func (*AuthPolicy_Primary_Updb) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6, 0, 1} + return file_edge_cmd_proto_rawDescGZIP(), []int{7, 0, 1} } func (x *AuthPolicy_Primary_Updb) GetAllowed() bool { @@ -3019,7 +3188,7 @@ type AuthPolicy_Primary_ExtJwt struct { func (x *AuthPolicy_Primary_ExtJwt) Reset() { *x = AuthPolicy_Primary_ExtJwt{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[34] + mi := &file_edge_cmd_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3032,7 +3201,7 @@ func (x *AuthPolicy_Primary_ExtJwt) String() string { func (*AuthPolicy_Primary_ExtJwt) ProtoMessage() {} func (x *AuthPolicy_Primary_ExtJwt) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[34] + mi := &file_edge_cmd_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3045,7 +3214,7 @@ func (x *AuthPolicy_Primary_ExtJwt) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicy_Primary_ExtJwt.ProtoReflect.Descriptor instead. func (*AuthPolicy_Primary_ExtJwt) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{6, 0, 2} + return file_edge_cmd_proto_rawDescGZIP(), []int{7, 0, 2} } func (x *AuthPolicy_Primary_ExtJwt) GetAllowed() bool { @@ -3085,7 +3254,7 @@ type Ca_ExternalIdClaim struct { func (x *Ca_ExternalIdClaim) Reset() { *x = Ca_ExternalIdClaim{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[35] + mi := &file_edge_cmd_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3098,7 +3267,7 @@ func (x *Ca_ExternalIdClaim) String() string { func (*Ca_ExternalIdClaim) ProtoMessage() {} func (x *Ca_ExternalIdClaim) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[35] + mi := &file_edge_cmd_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3111,7 +3280,7 @@ func (x *Ca_ExternalIdClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use Ca_ExternalIdClaim.ProtoReflect.Descriptor instead. func (*Ca_ExternalIdClaim) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{7, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{8, 0} } func (x *Ca_ExternalIdClaim) GetLocation() string { @@ -3170,7 +3339,7 @@ type Identity_EnvInfo struct { func (x *Identity_EnvInfo) Reset() { *x = Identity_EnvInfo{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[43] + mi := &file_edge_cmd_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3183,7 +3352,7 @@ func (x *Identity_EnvInfo) String() string { func (*Identity_EnvInfo) ProtoMessage() {} func (x *Identity_EnvInfo) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[43] + mi := &file_edge_cmd_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3196,7 +3365,7 @@ func (x *Identity_EnvInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use Identity_EnvInfo.ProtoReflect.Descriptor instead. func (*Identity_EnvInfo) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{16, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{17, 0} } func (x *Identity_EnvInfo) GetArch() string { @@ -3243,7 +3412,7 @@ type Identity_SdkInfo struct { func (x *Identity_SdkInfo) Reset() { *x = Identity_SdkInfo{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[44] + mi := &file_edge_cmd_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3256,7 +3425,7 @@ func (x *Identity_SdkInfo) String() string { func (*Identity_SdkInfo) ProtoMessage() {} func (x *Identity_SdkInfo) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[44] + mi := &file_edge_cmd_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3269,7 +3438,7 @@ func (x *Identity_SdkInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use Identity_SdkInfo.ProtoReflect.Descriptor instead. func (*Identity_SdkInfo) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{16, 1} + return file_edge_cmd_proto_rawDescGZIP(), []int{17, 1} } func (x *Identity_SdkInfo) GetAppId() string { @@ -3325,7 +3494,7 @@ type PostureCheck_Mac struct { func (x *PostureCheck_Mac) Reset() { *x = PostureCheck_Mac{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[49] + mi := &file_edge_cmd_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3338,7 +3507,7 @@ func (x *PostureCheck_Mac) String() string { func (*PostureCheck_Mac) ProtoMessage() {} func (x *PostureCheck_Mac) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[49] + mi := &file_edge_cmd_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3351,7 +3520,7 @@ func (x *PostureCheck_Mac) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_Mac.ProtoReflect.Descriptor instead. func (*PostureCheck_Mac) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 0} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 0} } func (x *PostureCheck_Mac) GetMacAddresses() []string { @@ -3375,7 +3544,7 @@ type PostureCheck_Mfa struct { func (x *PostureCheck_Mfa) Reset() { *x = PostureCheck_Mfa{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[50] + mi := &file_edge_cmd_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3388,7 +3557,7 @@ func (x *PostureCheck_Mfa) String() string { func (*PostureCheck_Mfa) ProtoMessage() {} func (x *PostureCheck_Mfa) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[50] + mi := &file_edge_cmd_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3401,7 +3570,7 @@ func (x *PostureCheck_Mfa) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_Mfa.ProtoReflect.Descriptor instead. func (*PostureCheck_Mfa) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 1} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 1} } func (x *PostureCheck_Mfa) GetTimeoutSeconds() int64 { @@ -3444,7 +3613,7 @@ type PostureCheck_Os struct { func (x *PostureCheck_Os) Reset() { *x = PostureCheck_Os{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[51] + mi := &file_edge_cmd_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3457,7 +3626,7 @@ func (x *PostureCheck_Os) String() string { func (*PostureCheck_Os) ProtoMessage() {} func (x *PostureCheck_Os) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[51] + mi := &file_edge_cmd_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3470,7 +3639,7 @@ func (x *PostureCheck_Os) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_Os.ProtoReflect.Descriptor instead. func (*PostureCheck_Os) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 2} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 2} } func (x *PostureCheck_Os) GetOsType() string { @@ -3498,7 +3667,7 @@ type PostureCheck_OsList struct { func (x *PostureCheck_OsList) Reset() { *x = PostureCheck_OsList{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[52] + mi := &file_edge_cmd_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3511,7 +3680,7 @@ func (x *PostureCheck_OsList) String() string { func (*PostureCheck_OsList) ProtoMessage() {} func (x *PostureCheck_OsList) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[52] + mi := &file_edge_cmd_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3524,7 +3693,7 @@ func (x *PostureCheck_OsList) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_OsList.ProtoReflect.Descriptor instead. func (*PostureCheck_OsList) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 3} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 3} } func (x *PostureCheck_OsList) GetOsList() []*PostureCheck_Os { @@ -3548,7 +3717,7 @@ type PostureCheck_Process struct { func (x *PostureCheck_Process) Reset() { *x = PostureCheck_Process{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[53] + mi := &file_edge_cmd_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3561,7 +3730,7 @@ func (x *PostureCheck_Process) String() string { func (*PostureCheck_Process) ProtoMessage() {} func (x *PostureCheck_Process) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[53] + mi := &file_edge_cmd_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3574,7 +3743,7 @@ func (x *PostureCheck_Process) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_Process.ProtoReflect.Descriptor instead. func (*PostureCheck_Process) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 4} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 4} } func (x *PostureCheck_Process) GetOsType() string { @@ -3617,7 +3786,7 @@ type PostureCheck_ProcessMulti struct { func (x *PostureCheck_ProcessMulti) Reset() { *x = PostureCheck_ProcessMulti{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[54] + mi := &file_edge_cmd_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3630,7 +3799,7 @@ func (x *PostureCheck_ProcessMulti) String() string { func (*PostureCheck_ProcessMulti) ProtoMessage() {} func (x *PostureCheck_ProcessMulti) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[54] + mi := &file_edge_cmd_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3643,7 +3812,7 @@ func (x *PostureCheck_ProcessMulti) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_ProcessMulti.ProtoReflect.Descriptor instead. func (*PostureCheck_ProcessMulti) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 5} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 5} } func (x *PostureCheck_ProcessMulti) GetSemantic() string { @@ -3671,7 +3840,7 @@ type PostureCheck_Domains struct { func (x *PostureCheck_Domains) Reset() { *x = PostureCheck_Domains{} if protoimpl.UnsafeEnabled { - mi := &file_edge_cmd_proto_msgTypes[55] + mi := &file_edge_cmd_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3684,7 +3853,7 @@ func (x *PostureCheck_Domains) String() string { func (*PostureCheck_Domains) ProtoMessage() {} func (x *PostureCheck_Domains) ProtoReflect() protoreflect.Message { - mi := &file_edge_cmd_proto_msgTypes[55] + mi := &file_edge_cmd_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3697,7 +3866,7 @@ func (x *PostureCheck_Domains) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureCheck_Domains.ProtoReflect.Descriptor instead. func (*PostureCheck_Domains) Descriptor() ([]byte, []int) { - return file_edge_cmd_proto_rawDescGZIP(), []int{19, 6} + return file_edge_cmd_proto_rawDescGZIP(), []int{20, 6} } func (x *PostureCheck_Domains) GetDomains() []string { @@ -3707,6 +3876,61 @@ func (x *PostureCheck_Domains) GetDomains() []string { return nil } +type UpdateServiceConfigsCmd_ServiceConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServiceId string `protobuf:"bytes,1,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + ConfigId string `protobuf:"bytes,2,opt,name=configId,proto3" json:"configId,omitempty"` +} + +func (x *UpdateServiceConfigsCmd_ServiceConfig) Reset() { + *x = UpdateServiceConfigsCmd_ServiceConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_cmd_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateServiceConfigsCmd_ServiceConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateServiceConfigsCmd_ServiceConfig) ProtoMessage() {} + +func (x *UpdateServiceConfigsCmd_ServiceConfig) ProtoReflect() protoreflect.Message { + mi := &file_edge_cmd_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateServiceConfigsCmd_ServiceConfig.ProtoReflect.Descriptor instead. +func (*UpdateServiceConfigsCmd_ServiceConfig) Descriptor() ([]byte, []int) { + return file_edge_cmd_proto_rawDescGZIP(), []int{26, 0} +} + +func (x *UpdateServiceConfigsCmd_ServiceConfig) GetServiceId() string { + if x != nil { + return x.ServiceId + } + return "" +} + +func (x *UpdateServiceConfigsCmd_ServiceConfig) GetConfigId() string { + if x != nil { + return x.ConfigId + } + return "" +} + var File_edge_cmd_proto protoreflect.FileDescriptor var file_edge_cmd_proto_rawDesc = []byte{ @@ -3714,752 +3938,801 @@ var file_edge_cmd_proto_rawDesc = []byte{ 0x12, 0x10, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x45, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, + 0x6f, 0x74, 0x6f, 0x22, 0xbd, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4f, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x61, 0x66, 0x74, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x61, 0x66, 0x74, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x78, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x61, 0x74, 0x61, 0x22, 0x91, 0x01, 0x0a, 0x08, 0x54, - 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, - 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x07, 0x66, - 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x07, - 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x08, 0x6e, 0x69, 0x6c, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x69, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9c, - 0x01, 0x0a, 0x07, 0x4a, 0x73, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, - 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, - 0x6e, 0x4d, 0x61, 0x70, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x55, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, - 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3d, 0x0a, - 0x08, 0x4a, 0x73, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x02, 0x0a, - 0x09, 0x4a, 0x73, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x09, 0x62, 0x6f, + 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0x91, 0x01, + 0x0a, 0x08, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x07, 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x48, - 0x00, 0x52, 0x07, 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0a, 0x69, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, - 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x08, - 0x6e, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x08, 0x6e, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x6d, 0x61, - 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x7a, + 0x00, 0x52, 0x07, 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x08, 0x6e, 0x69, + 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, + 0x6e, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x07, 0x4a, 0x73, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x12, 0x3a, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x4a, 0x73, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, - 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x4c, 0x69, - 0x73, 0x74, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, - 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc3, 0x04, 0x0a, 0x0d, 0x41, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x61, - 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x4a, 0x73, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x55, 0x0a, 0x0a, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x3d, 0x0a, 0x08, 0x4a, 0x73, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, + 0x73, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, + 0xa9, 0x02, 0x0a, 0x09, 0x4a, 0x73, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, + 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, + 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x1a, 0x0a, 0x07, 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x01, 0x48, 0x00, 0x52, 0x07, 0x66, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, + 0x0a, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x1c, 0x0a, 0x08, 0x6e, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x37, 0x0a, + 0x08, 0x6d, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, + 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4a, 0x73, 0x6f, + 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc3, 0x04, 0x0a, 0x0d, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3d, 0x0a, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x04, + 0x63, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, + 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x65, 0x72, 0x74, + 0x48, 0x00, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x75, 0x70, 0x64, 0x62, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x62, 0x48, 0x00, 0x52, 0x04, + 0x75, 0x70, 0x64, 0x62, 0x1a, 0x96, 0x01, 0x0a, 0x04, 0x43, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, + 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x70, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x65, + 0x6d, 0x12, 0x34, 0x0a, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, + 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x6e, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x65, 0x6d, 0x1a, 0x52, 0x0a, + 0x04, 0x55, 0x70, 0x64, 0x62, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x61, 0x6c, + 0x74, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, + 0x65, 0x22, 0x9f, 0x09, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x70, 0x72, 0x69, + 0x6d, 0x61, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, + 0x09, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x04, 0x63, 0x65, 0x72, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, - 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x48, 0x00, 0x52, - 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x75, 0x70, 0x64, 0x62, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x62, 0x48, 0x00, 0x52, 0x04, 0x75, 0x70, 0x64, - 0x62, 0x1a, 0x96, 0x01, 0x0a, 0x04, 0x43, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, - 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x70, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x65, 0x6d, 0x12, 0x34, - 0x0a, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x75, - 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x50, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x75, 0x6e, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x65, 0x6d, 0x1a, 0x52, 0x0a, 0x04, 0x55, 0x70, - 0x64, 0x62, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x61, - 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x1a, 0x53, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0xd4, 0x05, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, + 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x52, 0x04, 0x63, 0x65, 0x72, + 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x75, 0x70, 0x64, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, + 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x62, 0x52, 0x04, 0x75, 0x70, 0x64, 0x62, + 0x12, 0x43, 0x0a, 0x06, 0x65, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, + 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x52, 0x06, 0x65, + 0x78, 0x74, 0x4a, 0x77, 0x74, 0x1a, 0x4e, 0x0a, 0x04, 0x43, 0x65, 0x72, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, + 0x43, 0x65, 0x72, 0x74, 0x73, 0x1a, 0xb2, 0x02, 0x0a, 0x04, 0x55, 0x70, 0x64, 0x62, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x4d, 0x69, 0x6e, 0x50, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x53, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x69, + 0x61, 0x6c, 0x43, 0x68, 0x61, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x43, 0x68, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x43, 0x68, 0x61, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4d, + 0x69, 0x78, 0x65, 0x64, 0x43, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x43, 0x61, 0x73, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, + 0x74, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x16, 0x4c, 0x6f, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x80, 0x01, 0x0a, 0x06, 0x45, + 0x78, 0x74, 0x4a, 0x77, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, + 0x28, 0x0a, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, + 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x1a, 0x7f, 0x0a, + 0x09, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x54, 0x6f, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x54, 0x6f, 0x74, 0x70, 0x12, 0x37, 0x0a, 0x14, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x22, 0x9f, - 0x09, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, + 0x02, 0x38, 0x01, 0x22, 0xe4, 0x06, 0x0a, 0x02, 0x43, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32, + 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x7a, + 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, + 0x43, 0x61, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x12, 0x1e, + 0x0a, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x2c, + 0x0a, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x19, + 0x69, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, + 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x19, 0x69, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, + 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x18, 0x69, 0x73, + 0x4f, 0x74, 0x74, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x73, + 0x4f, 0x74, 0x74, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x41, 0x75, 0x74, 0x68, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, + 0x73, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, + 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, + 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x12, 0x53, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x48, 0x00, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, + 0x6c, 0x61, 0x69, 0x6d, 0x88, 0x01, 0x01, 0x1a, 0xc7, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x72, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, + 0x65, 0x72, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x43, 0x72, 0x69, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x22, 0xf1, 0x01, 0x0a, 0x06, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x36, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd9, + 0x01, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, - 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, - 0x79, 0x12, 0x44, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x09, 0x73, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, - 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x1a, 0xd4, 0x05, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, - 0x3d, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x3d, - 0x0a, 0x04, 0x75, 0x70, 0x64, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x61, - 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x62, 0x52, 0x04, 0x75, 0x70, 0x64, 0x62, 0x12, 0x43, 0x0a, - 0x06, 0x65, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x52, 0x06, 0x65, 0x78, 0x74, 0x4a, - 0x77, 0x74, 0x1a, 0x4e, 0x0a, 0x04, 0x43, 0x65, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x43, 0x65, 0x72, - 0x74, 0x73, 0x1a, 0xb2, 0x02, 0x0a, 0x04, 0x55, 0x70, 0x64, 0x62, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x53, 0x70, - 0x65, 0x63, 0x69, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x43, - 0x68, 0x61, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x43, 0x68, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, - 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x43, 0x68, 0x61, - 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4d, 0x69, 0x78, 0x65, - 0x64, 0x43, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x52, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x43, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, - 0x36, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x16, 0x4c, 0x6f, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x80, 0x01, 0x0a, 0x06, 0x45, 0x78, 0x74, 0x4a, - 0x77, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0f, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x6c, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x45, 0x78, 0x74, - 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x1a, 0x7f, 0x0a, 0x09, 0x53, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x54, 0x6f, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x54, 0x6f, 0x74, 0x70, 0x12, 0x37, 0x0a, 0x14, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x45, 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x88, - 0x01, 0x01, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, - 0x78, 0x74, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x1a, 0x53, 0x0a, 0x09, 0x54, - 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, - 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xe4, 0x06, 0x0a, 0x02, 0x43, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x7a, 0x69, 0x74, 0x69, - 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x2e, - 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, - 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x69, - 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x19, 0x69, 0x73, 0x41, - 0x75, 0x74, 0x6f, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x45, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x69, 0x73, - 0x41, 0x75, 0x74, 0x6f, 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x18, 0x69, 0x73, 0x4f, 0x74, 0x74, - 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x73, 0x4f, 0x74, 0x74, - 0x43, 0x61, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x41, 0x75, - 0x74, 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, - 0x2e, 0x0a, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x46, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, - 0x53, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, - 0x69, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x2e, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x48, 0x00, - 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, - 0x6d, 0x88, 0x01, 0x01, 0x1a, 0xc7, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x28, - 0x0a, 0x0f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, - 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x73, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, - 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, - 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x1a, 0x53, - 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x22, 0xf1, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x36, - 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd9, 0x01, 0x0a, 0x0a, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, - 0x70, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, - 0x67, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, - 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd1, 0x05, 0x0a, 0x0a, 0x45, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, - 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, - 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x25, - 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, - 0x6d, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, - 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x11, 0x69, 0x73, 0x54, 0x75, 0x6e, 0x6e, 0x65, - 0x6c, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x69, 0x73, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, - 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x15, - 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x11, 0x75, 0x6e, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x11, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x63, - 0x6f, 0x73, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x53, 0x0a, - 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, - 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, - 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x42, 0x0b, - 0x0a, 0x09, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x18, 0x0a, 0x16, 0x5f, - 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x13, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x43, 0x6d, 0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, - 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, 0x67, 0x65, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x12, 0x3c, 0x0a, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, - 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0xb9, 0x02, 0x0a, 0x10, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, - 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, - 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, - 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, - 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, - 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe0, 0x04, 0x0a, 0x0a, - 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, - 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, - 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, - 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0c, 0x65, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x36, 0x0a, 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x73, 0x41, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6a, 0x77, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x63, 0x61, 0x49, 0x64, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x04, 0x63, 0x61, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f, - 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x04, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x1a, - 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x49, 0x64, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x65, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x63, 0x61, 0x49, - 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x92, - 0x01, 0x0a, 0x25, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6d, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x0d, - 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x6f, 0x72, 0x22, 0xb5, 0x06, 0x0a, 0x11, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, 0x67, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, + 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd1, 0x05, 0x0a, 0x0a, 0x45, + 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, - 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x7a, 0x69, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, - 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, - 0x27, 0x0a, 0x0c, 0x6a, 0x77, 0x6b, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x6a, 0x77, 0x6b, 0x73, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x15, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, - 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x0f, 0x65, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x03, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, - 0x74, 0x68, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0d, 0x75, 0x73, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x2b, - 0x0a, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x69, - 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x06, 0x69, - 0x73, 0x73, 0x75, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x61, 0x75, 0x64, 0x69, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x08, 0x61, 0x75, - 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x66, 0x69, 0x6e, - 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07, - 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, - 0x12, 0x36, 0x0a, 0x08, 0x6e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, - 0x6e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x42, - 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, - 0x72, 0x65, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, - 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x65, 0x72, 0x74, - 0x50, 0x65, 0x6d, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x6a, 0x77, 0x6b, 0x73, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6b, 0x69, 0x64, 0x42, 0x12, 0x0a, 0x10, - 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, - 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x79, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x42, 0x0b, - 0x0a, 0x09, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, - 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x95, 0x0c, 0x0a, 0x08, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x04, - 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, - 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x26, - 0x0a, 0x0e, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x49, - 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, 0x69, 0x74, 0x69, - 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, - 0x07, 0x65, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x12, 0x41, 0x0a, 0x07, 0x73, - 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x48, 0x01, 0x52, 0x07, 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x12, 0x3a, - 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x77, 0x0a, 0x19, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, - 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x19, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x12, 0x65, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x33, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, - 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, - 0x70, 0x44, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x49, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0a, - 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, - 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x03, 0x52, 0x0a, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a, 0x0d, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x04, 0x52, - 0x0d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x88, 0x01, - 0x01, 0x1a, 0x69, 0x0a, 0x07, 0x45, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, - 0x41, 0x72, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, 0x63, 0x68, - 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x73, - 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x73, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x73, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xa1, 0x01, 0x0a, - 0x07, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x12, 0x1e, - 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x41, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, - 0x0a, 0x06, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x12, 0x25, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x65, 0x72, 0x74, + 0x50, 0x65, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x63, 0x65, 0x72, + 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x11, 0x69, 0x73, 0x54, 0x75, + 0x6e, 0x6e, 0x65, 0x6c, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x73, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x65, 0x72, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, + 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, + 0x12, 0x39, 0x0a, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, + 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x03, 0x52, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, + 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x11, 0x75, + 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x11, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, + 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x1e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x46, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, - 0x65, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x64, 0x6b, 0x49, - 0x6e, 0x66, 0x6f, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x49, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, - 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x6e, - 0x74, 0x69, 0x6c, 0x22, 0x9a, 0x01, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6d, 0x64, 0x12, 0x36, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, - 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x12, 0x3e, 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, - 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x9d, 0x02, 0x0a, 0x03, 0x4d, 0x66, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, - 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x66, 0x61, 0x2e, 0x54, 0x61, - 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1e, 0x0a, - 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, + 0x6d, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x18, + 0x0a, 0x16, 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, + 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x75, 0x6e, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x22, 0xc4, + 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x72, 0x43, 0x6d, 0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, + 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x64, + 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0xb9, 0x02, 0x0a, 0x10, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, + 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x7a, + 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, + 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x0f, + 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, + 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, + 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0xe0, 0x04, 0x0a, 0x0a, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, + 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x65, 0x64, 0x67, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, + 0x52, 0x0c, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x36, 0x0a, 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, + 0x64, 0x41, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x38, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, 0x74, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x63, + 0x61, 0x49, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x04, 0x63, 0x61, 0x49, + 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x88, 0x01, 0x01, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, + 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x42, 0x0f, 0x0a, + 0x0d, 0x5f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x42, 0x07, + 0x0a, 0x05, 0x5f, 0x63, 0x61, 0x49, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xc5, 0x01, 0x0a, 0x25, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6d, 0x64, 0x12, 0x22, + 0x0a, 0x0c, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x45, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, 0x78, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0xb5, 0x06, 0x0a, + 0x11, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, + 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x4a, 0x77, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x65, 0x72, + 0x74, 0x50, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x63, 0x65, + 0x72, 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x6a, 0x77, 0x6b, 0x73, + 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, + 0x52, 0x0c, 0x6a, 0x77, 0x6b, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x15, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, + 0x52, 0x03, 0x6b, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, + 0x74, 0x68, 0x55, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x0f, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x88, 0x01, + 0x01, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x45, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, + 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x04, 0x52, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x88, 0x01, + 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x88, + 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x08, 0x6e, 0x6f, 0x74, + 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x12, 0x38, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xa0, 0x0a, 0x0a, 0x0c, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x42, 0x0f, 0x0a, 0x0d, + 0x5f, 0x6a, 0x77, 0x6b, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x06, 0x0a, + 0x04, 0x5f, 0x6b, 0x69, 0x64, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x61, 0x75, 0x64, 0x69, + 0x65, 0x6e, 0x63, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x22, 0x95, 0x0c, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, - 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, - 0x03, 0x6d, 0x61, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, 0x69, 0x74, - 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, - 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4d, 0x61, 0x63, 0x48, 0x00, - 0x52, 0x03, 0x6d, 0x61, 0x63, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x66, 0x61, 0x18, 0x08, 0x20, 0x01, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, + 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, + 0x26, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x49, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x73, 0x44, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0e, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, + 0x18, 0x0a, 0x07, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x12, 0x41, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, - 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x2e, 0x4d, 0x66, 0x61, 0x48, 0x00, 0x52, 0x03, 0x6d, 0x66, 0x61, 0x12, 0x3f, 0x0a, - 0x06, 0x6f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4f, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x42, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, - 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, - 0x74, 0x69, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, - 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x42, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, - 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, - 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x48, 0x00, - 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x1a, 0x29, 0x0a, 0x03, 0x4d, 0x61, 0x63, - 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x1a, 0xaf, 0x01, 0x0a, 0x03, 0x4d, 0x66, 0x61, 0x12, 0x26, 0x0a, 0x0e, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, - 0x57, 0x61, 0x6b, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x50, 0x72, 0x6f, 0x6d, - 0x70, 0x74, 0x4f, 0x6e, 0x57, 0x61, 0x6b, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x6d, - 0x70, 0x74, 0x4f, 0x6e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x34, 0x0a, 0x15, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x15, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x3c, 0x0a, 0x02, 0x4f, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x43, 0x0a, 0x06, 0x4f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x39, - 0x0a, 0x06, 0x6f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, - 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4f, - 0x73, 0x52, 0x06, 0x6f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x71, 0x0a, 0x07, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x16, 0x0a, 0x06, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x06, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x46, 0x69, 0x6e, 0x67, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, - 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x0c, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x1a, 0x0a, 0x08, - 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x44, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, - 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, - 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x23, - 0x0a, 0x07, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, + 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x49, 0x6e, 0x66, + 0x6f, 0x88, 0x01, 0x01, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x01, 0x52, 0x07, 0x73, 0x64, 0x6b, + 0x49, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x12, 0x3a, 0x0a, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, + 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, + 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x73, 0x74, 0x12, 0x77, 0x0a, 0x19, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x19, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x65, 0x0a, 0x13, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x73, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x73, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, + 0x0c, 0x61, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, + 0x64, 0x12, 0x23, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x0a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, 0x74, + 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x48, 0x03, 0x52, 0x0a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, 0x74, + 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, + 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x04, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x1a, 0x69, 0x0a, 0x07, 0x45, 0x6e, + 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x73, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x73, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x73, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xa1, 0x01, 0x0a, 0x07, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x41, 0x70, 0x70, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, + 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, + 0x0a, 0x1e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, - 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, - 0x79, 0x70, 0x65, 0x22, 0xdd, 0x02, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, - 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x67, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x2e, 0x0a, 0x12, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, - 0x67, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x26, 0x0a, 0x0e, - 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x2e, - 0x0a, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x53, - 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, - 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xc5, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, - 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x33, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, - 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, - 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, - 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfb, 0x02, 0x0a, 0x0d, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x46, 0x0a, 0x18, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x65, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x0d, 0x0a, 0x0b, + 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0xcd, 0x01, 0x0a, + 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, + 0x69, 0x74, 0x68, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6d, + 0x64, 0x12, 0x36, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, + 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, + 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x65, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, + 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, 0x78, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0x9d, 0x02, 0x0a, + 0x03, 0x4d, 0x66, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, + 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x66, 0x61, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, + 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x0a, 0x0a, + 0x0c, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, - 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x24, 0x0a, 0x0d, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, - 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x75, 0x72, - 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, - 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x54, 0x79, 0x70, 0x65, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, - 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x04, 0x0a, 0x0d, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, + 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x61, 0x63, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, + 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4d, 0x61, 0x63, 0x48, 0x00, 0x52, 0x03, 0x6d, 0x61, + 0x63, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x66, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, + 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4d, + 0x66, 0x61, 0x48, 0x00, 0x52, 0x03, 0x6d, 0x66, 0x61, 0x12, 0x3f, 0x0a, 0x06, 0x6f, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, + 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4f, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x48, 0x00, 0x52, 0x06, 0x6f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x07, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, + 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x51, + 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, + 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x12, 0x42, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, + 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x07, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x1a, 0x29, 0x0a, 0x03, 0x4d, 0x61, 0x63, 0x12, 0x22, 0x0a, 0x0c, + 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x1a, 0xaf, 0x01, 0x0a, 0x03, 0x4d, 0x66, 0x61, 0x12, 0x26, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, + 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x57, 0x61, 0x6b, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, + 0x57, 0x61, 0x6b, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, + 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x50, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x34, 0x0a, 0x15, + 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x49, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x1a, 0x3c, 0x0a, 0x02, 0x4f, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x73, 0x54, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1e, 0x0a, 0x0a, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x1a, 0x43, 0x0a, 0x06, 0x4f, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x6f, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x7a, 0x69, 0x74, + 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, + 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x4f, 0x73, 0x52, 0x06, 0x6f, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x71, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x46, 0x69, 0x6e, 0x67, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, + 0x6e, 0x74, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, + 0x6e, 0x74, 0x69, 0x63, 0x12, 0x44, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, + 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x23, 0x0a, 0x07, 0x44, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x1a, + 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, + 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x22, + 0xdd, 0x02, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x3d, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x37, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, - 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x54, - 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x25, - 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, - 0x12, 0x31, 0x0a, 0x11, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, - 0x72, 0x74, 0x50, 0x65, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x11, 0x75, - 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, - 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, - 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, - 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x75, - 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x22, 0x8f, 0x01, 0x0a, 0x16, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x43, 0x6d, 0x64, 0x12, 0x37, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, - 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x3c, - 0x0a, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, - 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x2a, 0xc4, 0x01, 0x0a, - 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, - 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x45, 0x64, 0x67, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xe8, 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xe9, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0xea, 0x07, 0x12, 0x1c, 0x0a, - 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0xeb, 0x07, 0x12, 0x26, 0x0a, 0x21, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x69, 0x74, - 0x68, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xec, 0x07, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x2f, - 0x70, 0x62, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x5f, 0x70, 0x62, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x6f, 0x6c, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, + 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xc5, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x64, 0x67, 0x65, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x47, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, + 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, + 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, + 0x6e, 0x74, 0x69, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, + 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x22, + 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, + 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, + 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfb, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x22, + 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x6f, 0x6c, + 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x70, + 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x73, + 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, + 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, + 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x04, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, + 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x74, + 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0b, 0x66, 0x69, + 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x39, 0x0a, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, + 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x01, 0x52, 0x15, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, + 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x11, + 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, + 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x11, 0x75, 0x6e, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x88, 0x01, 0x01, 0x12, + 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, + 0x6f, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x54, 0x72, 0x61, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, + 0x70, 0x62, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, + 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, + 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x22, 0xc2, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6d, + 0x64, 0x12, 0x37, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, + 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x0a, 0x65, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, + 0x62, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x65, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, 0x78, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0xaa, 0x02, 0x0a, 0x17, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x43, 0x6d, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x64, 0x64, 0x12, 0x5f, 0x0a, 0x0e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x37, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, + 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x43, 0x6d, 0x64, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x03, 0x63, 0x74, + 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x03, 0x63, 0x74, 0x78, 0x1a, 0x49, 0x0a, + 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, + 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x2a, 0xe3, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x65, 0x72, 0x6f, + 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, + 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe8, + 0x07, 0x12, 0x2b, 0x0a, 0x26, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe9, 0x07, 0x12, 0x19, + 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0xea, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xeb, 0x07, 0x12, 0x26, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xec, 0x07, 0x12, + 0x1d, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xed, 0x07, 0x42, 0x29, + 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x2f, 0x70, 0x62, 0x2f, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -4475,148 +4748,160 @@ func file_edge_cmd_proto_rawDescGZIP() []byte { } var file_edge_cmd_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_edge_cmd_proto_msgTypes = make([]protoimpl.MessageInfo, 61) +var file_edge_cmd_proto_msgTypes = make([]protoimpl.MessageInfo, 65) var file_edge_cmd_proto_goTypes = []interface{}{ (CommandType)(0), // 0: ziti.edge_cmd.pb.CommandType - (*CreateEdgeTerminatorCommand)(nil), // 1: ziti.edge_cmd.pb.CreateEdgeTerminatorCommand - (*TagValue)(nil), // 2: ziti.edge_cmd.pb.TagValue - (*JsonMap)(nil), // 3: ziti.edge_cmd.pb.JsonMap - (*JsonList)(nil), // 4: ziti.edge_cmd.pb.JsonList - (*JsonValue)(nil), // 5: ziti.edge_cmd.pb.JsonValue - (*Authenticator)(nil), // 6: ziti.edge_cmd.pb.Authenticator - (*AuthPolicy)(nil), // 7: ziti.edge_cmd.pb.AuthPolicy - (*Ca)(nil), // 8: ziti.edge_cmd.pb.Ca - (*Config)(nil), // 9: ziti.edge_cmd.pb.Config - (*ConfigType)(nil), // 10: ziti.edge_cmd.pb.ConfigType - (*EdgeRouter)(nil), // 11: ziti.edge_cmd.pb.EdgeRouter - (*CreateEdgeRouterCmd)(nil), // 12: ziti.edge_cmd.pb.CreateEdgeRouterCmd - (*EdgeRouterPolicy)(nil), // 13: ziti.edge_cmd.pb.EdgeRouterPolicy - (*Enrollment)(nil), // 14: ziti.edge_cmd.pb.Enrollment - (*ReplaceEnrollmentWithAuthenticatorCmd)(nil), // 15: ziti.edge_cmd.pb.ReplaceEnrollmentWithAuthenticatorCmd - (*ExternalJwtSigner)(nil), // 16: ziti.edge_cmd.pb.ExternalJwtSigner - (*Identity)(nil), // 17: ziti.edge_cmd.pb.Identity - (*CreateIdentityWithEnrollmentsCmd)(nil), // 18: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd - (*Mfa)(nil), // 19: ziti.edge_cmd.pb.Mfa - (*PostureCheck)(nil), // 20: ziti.edge_cmd.pb.PostureCheck - (*Service)(nil), // 21: ziti.edge_cmd.pb.Service - (*ServiceEdgeRouterPolicy)(nil), // 22: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy - (*ServicePolicy)(nil), // 23: ziti.edge_cmd.pb.ServicePolicy - (*TransitRouter)(nil), // 24: ziti.edge_cmd.pb.TransitRouter - (*CreateTransitRouterCmd)(nil), // 25: ziti.edge_cmd.pb.CreateTransitRouterCmd - nil, // 26: ziti.edge_cmd.pb.JsonMap.ValueEntry - (*Authenticator_Cert)(nil), // 27: ziti.edge_cmd.pb.Authenticator.Cert - (*Authenticator_Updb)(nil), // 28: ziti.edge_cmd.pb.Authenticator.Updb - nil, // 29: ziti.edge_cmd.pb.Authenticator.TagsEntry - (*AuthPolicy_Primary)(nil), // 30: ziti.edge_cmd.pb.AuthPolicy.Primary - (*AuthPolicy_Secondary)(nil), // 31: ziti.edge_cmd.pb.AuthPolicy.Secondary - nil, // 32: ziti.edge_cmd.pb.AuthPolicy.TagsEntry - (*AuthPolicy_Primary_Cert)(nil), // 33: ziti.edge_cmd.pb.AuthPolicy.Primary.Cert - (*AuthPolicy_Primary_Updb)(nil), // 34: ziti.edge_cmd.pb.AuthPolicy.Primary.Updb - (*AuthPolicy_Primary_ExtJwt)(nil), // 35: ziti.edge_cmd.pb.AuthPolicy.Primary.ExtJwt - (*Ca_ExternalIdClaim)(nil), // 36: ziti.edge_cmd.pb.Ca.ExternalIdClaim - nil, // 37: ziti.edge_cmd.pb.Ca.TagsEntry - nil, // 38: ziti.edge_cmd.pb.Config.TagsEntry - nil, // 39: ziti.edge_cmd.pb.ConfigType.TagsEntry - nil, // 40: ziti.edge_cmd.pb.EdgeRouter.TagsEntry - nil, // 41: ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry - nil, // 42: ziti.edge_cmd.pb.Enrollment.TagsEntry - nil, // 43: ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry - (*Identity_EnvInfo)(nil), // 44: ziti.edge_cmd.pb.Identity.EnvInfo - (*Identity_SdkInfo)(nil), // 45: ziti.edge_cmd.pb.Identity.SdkInfo - nil, // 46: ziti.edge_cmd.pb.Identity.TagsEntry - nil, // 47: ziti.edge_cmd.pb.Identity.ServiceHostingPrecedencesEntry - nil, // 48: ziti.edge_cmd.pb.Identity.ServiceHostingCostsEntry - nil, // 49: ziti.edge_cmd.pb.Mfa.TagsEntry - (*PostureCheck_Mac)(nil), // 50: ziti.edge_cmd.pb.PostureCheck.Mac - (*PostureCheck_Mfa)(nil), // 51: ziti.edge_cmd.pb.PostureCheck.Mfa - (*PostureCheck_Os)(nil), // 52: ziti.edge_cmd.pb.PostureCheck.Os - (*PostureCheck_OsList)(nil), // 53: ziti.edge_cmd.pb.PostureCheck.OsList - (*PostureCheck_Process)(nil), // 54: ziti.edge_cmd.pb.PostureCheck.Process - (*PostureCheck_ProcessMulti)(nil), // 55: ziti.edge_cmd.pb.PostureCheck.ProcessMulti - (*PostureCheck_Domains)(nil), // 56: ziti.edge_cmd.pb.PostureCheck.Domains - nil, // 57: ziti.edge_cmd.pb.PostureCheck.TagsEntry - nil, // 58: ziti.edge_cmd.pb.Service.TagsEntry - nil, // 59: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry - nil, // 60: ziti.edge_cmd.pb.ServicePolicy.TagsEntry - nil, // 61: ziti.edge_cmd.pb.TransitRouter.TagsEntry - (*timestamppb.Timestamp)(nil), // 62: google.protobuf.Timestamp + (*ChangeContext)(nil), // 1: ziti.edge_cmd.pb.ChangeContext + (*CreateEdgeTerminatorCommand)(nil), // 2: ziti.edge_cmd.pb.CreateEdgeTerminatorCommand + (*TagValue)(nil), // 3: ziti.edge_cmd.pb.TagValue + (*JsonMap)(nil), // 4: ziti.edge_cmd.pb.JsonMap + (*JsonList)(nil), // 5: ziti.edge_cmd.pb.JsonList + (*JsonValue)(nil), // 6: ziti.edge_cmd.pb.JsonValue + (*Authenticator)(nil), // 7: ziti.edge_cmd.pb.Authenticator + (*AuthPolicy)(nil), // 8: ziti.edge_cmd.pb.AuthPolicy + (*Ca)(nil), // 9: ziti.edge_cmd.pb.Ca + (*Config)(nil), // 10: ziti.edge_cmd.pb.Config + (*ConfigType)(nil), // 11: ziti.edge_cmd.pb.ConfigType + (*EdgeRouter)(nil), // 12: ziti.edge_cmd.pb.EdgeRouter + (*CreateEdgeRouterCmd)(nil), // 13: ziti.edge_cmd.pb.CreateEdgeRouterCmd + (*EdgeRouterPolicy)(nil), // 14: ziti.edge_cmd.pb.EdgeRouterPolicy + (*Enrollment)(nil), // 15: ziti.edge_cmd.pb.Enrollment + (*ReplaceEnrollmentWithAuthenticatorCmd)(nil), // 16: ziti.edge_cmd.pb.ReplaceEnrollmentWithAuthenticatorCmd + (*ExternalJwtSigner)(nil), // 17: ziti.edge_cmd.pb.ExternalJwtSigner + (*Identity)(nil), // 18: ziti.edge_cmd.pb.Identity + (*CreateIdentityWithEnrollmentsCmd)(nil), // 19: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd + (*Mfa)(nil), // 20: ziti.edge_cmd.pb.Mfa + (*PostureCheck)(nil), // 21: ziti.edge_cmd.pb.PostureCheck + (*Service)(nil), // 22: ziti.edge_cmd.pb.Service + (*ServiceEdgeRouterPolicy)(nil), // 23: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy + (*ServicePolicy)(nil), // 24: ziti.edge_cmd.pb.ServicePolicy + (*TransitRouter)(nil), // 25: ziti.edge_cmd.pb.TransitRouter + (*CreateTransitRouterCmd)(nil), // 26: ziti.edge_cmd.pb.CreateTransitRouterCmd + (*UpdateServiceConfigsCmd)(nil), // 27: ziti.edge_cmd.pb.UpdateServiceConfigsCmd + nil, // 28: ziti.edge_cmd.pb.ChangeContext.AttributesEntry + nil, // 29: ziti.edge_cmd.pb.JsonMap.ValueEntry + (*Authenticator_Cert)(nil), // 30: ziti.edge_cmd.pb.Authenticator.Cert + (*Authenticator_Updb)(nil), // 31: ziti.edge_cmd.pb.Authenticator.Updb + nil, // 32: ziti.edge_cmd.pb.Authenticator.TagsEntry + (*AuthPolicy_Primary)(nil), // 33: ziti.edge_cmd.pb.AuthPolicy.Primary + (*AuthPolicy_Secondary)(nil), // 34: ziti.edge_cmd.pb.AuthPolicy.Secondary + nil, // 35: ziti.edge_cmd.pb.AuthPolicy.TagsEntry + (*AuthPolicy_Primary_Cert)(nil), // 36: ziti.edge_cmd.pb.AuthPolicy.Primary.Cert + (*AuthPolicy_Primary_Updb)(nil), // 37: ziti.edge_cmd.pb.AuthPolicy.Primary.Updb + (*AuthPolicy_Primary_ExtJwt)(nil), // 38: ziti.edge_cmd.pb.AuthPolicy.Primary.ExtJwt + (*Ca_ExternalIdClaim)(nil), // 39: ziti.edge_cmd.pb.Ca.ExternalIdClaim + nil, // 40: ziti.edge_cmd.pb.Ca.TagsEntry + nil, // 41: ziti.edge_cmd.pb.Config.TagsEntry + nil, // 42: ziti.edge_cmd.pb.ConfigType.TagsEntry + nil, // 43: ziti.edge_cmd.pb.EdgeRouter.TagsEntry + nil, // 44: ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry + nil, // 45: ziti.edge_cmd.pb.Enrollment.TagsEntry + nil, // 46: ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry + (*Identity_EnvInfo)(nil), // 47: ziti.edge_cmd.pb.Identity.EnvInfo + (*Identity_SdkInfo)(nil), // 48: ziti.edge_cmd.pb.Identity.SdkInfo + nil, // 49: ziti.edge_cmd.pb.Identity.TagsEntry + nil, // 50: ziti.edge_cmd.pb.Identity.ServiceHostingPrecedencesEntry + nil, // 51: ziti.edge_cmd.pb.Identity.ServiceHostingCostsEntry + nil, // 52: ziti.edge_cmd.pb.Mfa.TagsEntry + (*PostureCheck_Mac)(nil), // 53: ziti.edge_cmd.pb.PostureCheck.Mac + (*PostureCheck_Mfa)(nil), // 54: ziti.edge_cmd.pb.PostureCheck.Mfa + (*PostureCheck_Os)(nil), // 55: ziti.edge_cmd.pb.PostureCheck.Os + (*PostureCheck_OsList)(nil), // 56: ziti.edge_cmd.pb.PostureCheck.OsList + (*PostureCheck_Process)(nil), // 57: ziti.edge_cmd.pb.PostureCheck.Process + (*PostureCheck_ProcessMulti)(nil), // 58: ziti.edge_cmd.pb.PostureCheck.ProcessMulti + (*PostureCheck_Domains)(nil), // 59: ziti.edge_cmd.pb.PostureCheck.Domains + nil, // 60: ziti.edge_cmd.pb.PostureCheck.TagsEntry + nil, // 61: ziti.edge_cmd.pb.Service.TagsEntry + nil, // 62: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry + nil, // 63: ziti.edge_cmd.pb.ServicePolicy.TagsEntry + nil, // 64: ziti.edge_cmd.pb.TransitRouter.TagsEntry + (*UpdateServiceConfigsCmd_ServiceConfig)(nil), // 65: ziti.edge_cmd.pb.UpdateServiceConfigsCmd.ServiceConfig + (*timestamppb.Timestamp)(nil), // 66: google.protobuf.Timestamp } var file_edge_cmd_proto_depIdxs = []int32{ - 26, // 0: ziti.edge_cmd.pb.JsonMap.value:type_name -> ziti.edge_cmd.pb.JsonMap.ValueEntry - 5, // 1: ziti.edge_cmd.pb.JsonList.value:type_name -> ziti.edge_cmd.pb.JsonValue - 3, // 2: ziti.edge_cmd.pb.JsonValue.mapValue:type_name -> ziti.edge_cmd.pb.JsonMap - 4, // 3: ziti.edge_cmd.pb.JsonValue.listValue:type_name -> ziti.edge_cmd.pb.JsonList - 29, // 4: ziti.edge_cmd.pb.Authenticator.tags:type_name -> ziti.edge_cmd.pb.Authenticator.TagsEntry - 27, // 5: ziti.edge_cmd.pb.Authenticator.cert:type_name -> ziti.edge_cmd.pb.Authenticator.Cert - 28, // 6: ziti.edge_cmd.pb.Authenticator.updb:type_name -> ziti.edge_cmd.pb.Authenticator.Updb - 30, // 7: ziti.edge_cmd.pb.AuthPolicy.primary:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary - 31, // 8: ziti.edge_cmd.pb.AuthPolicy.secondary:type_name -> ziti.edge_cmd.pb.AuthPolicy.Secondary - 32, // 9: ziti.edge_cmd.pb.AuthPolicy.tags:type_name -> ziti.edge_cmd.pb.AuthPolicy.TagsEntry - 37, // 10: ziti.edge_cmd.pb.Ca.tags:type_name -> ziti.edge_cmd.pb.Ca.TagsEntry - 36, // 11: ziti.edge_cmd.pb.Ca.externalIdClaim:type_name -> ziti.edge_cmd.pb.Ca.ExternalIdClaim - 38, // 12: ziti.edge_cmd.pb.Config.tags:type_name -> ziti.edge_cmd.pb.Config.TagsEntry - 39, // 13: ziti.edge_cmd.pb.ConfigType.tags:type_name -> ziti.edge_cmd.pb.ConfigType.TagsEntry - 40, // 14: ziti.edge_cmd.pb.EdgeRouter.tags:type_name -> ziti.edge_cmd.pb.EdgeRouter.TagsEntry - 11, // 15: ziti.edge_cmd.pb.CreateEdgeRouterCmd.edgeRouter:type_name -> ziti.edge_cmd.pb.EdgeRouter - 14, // 16: ziti.edge_cmd.pb.CreateEdgeRouterCmd.enrollment:type_name -> ziti.edge_cmd.pb.Enrollment - 41, // 17: ziti.edge_cmd.pb.EdgeRouterPolicy.tags:type_name -> ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry - 42, // 18: ziti.edge_cmd.pb.Enrollment.tags:type_name -> ziti.edge_cmd.pb.Enrollment.TagsEntry - 62, // 19: ziti.edge_cmd.pb.Enrollment.issuedAt:type_name -> google.protobuf.Timestamp - 62, // 20: ziti.edge_cmd.pb.Enrollment.expiresAt:type_name -> google.protobuf.Timestamp - 6, // 21: ziti.edge_cmd.pb.ReplaceEnrollmentWithAuthenticatorCmd.authenticator:type_name -> ziti.edge_cmd.pb.Authenticator - 43, // 22: ziti.edge_cmd.pb.ExternalJwtSigner.tags:type_name -> ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry - 62, // 23: ziti.edge_cmd.pb.ExternalJwtSigner.notAfter:type_name -> google.protobuf.Timestamp - 62, // 24: ziti.edge_cmd.pb.ExternalJwtSigner.notBefore:type_name -> google.protobuf.Timestamp - 46, // 25: ziti.edge_cmd.pb.Identity.tags:type_name -> ziti.edge_cmd.pb.Identity.TagsEntry - 44, // 26: ziti.edge_cmd.pb.Identity.envInfo:type_name -> ziti.edge_cmd.pb.Identity.EnvInfo - 45, // 27: ziti.edge_cmd.pb.Identity.sdkInfo:type_name -> ziti.edge_cmd.pb.Identity.SdkInfo - 47, // 28: ziti.edge_cmd.pb.Identity.serviceHostingPrecedences:type_name -> ziti.edge_cmd.pb.Identity.ServiceHostingPrecedencesEntry - 48, // 29: ziti.edge_cmd.pb.Identity.serviceHostingCosts:type_name -> ziti.edge_cmd.pb.Identity.ServiceHostingCostsEntry - 62, // 30: ziti.edge_cmd.pb.Identity.disabledAt:type_name -> google.protobuf.Timestamp - 62, // 31: ziti.edge_cmd.pb.Identity.disabledUntil:type_name -> google.protobuf.Timestamp - 17, // 32: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd.identity:type_name -> ziti.edge_cmd.pb.Identity - 14, // 33: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd.enrollments:type_name -> ziti.edge_cmd.pb.Enrollment - 49, // 34: ziti.edge_cmd.pb.Mfa.tags:type_name -> ziti.edge_cmd.pb.Mfa.TagsEntry - 57, // 35: ziti.edge_cmd.pb.PostureCheck.tags:type_name -> ziti.edge_cmd.pb.PostureCheck.TagsEntry - 50, // 36: ziti.edge_cmd.pb.PostureCheck.mac:type_name -> ziti.edge_cmd.pb.PostureCheck.Mac - 51, // 37: ziti.edge_cmd.pb.PostureCheck.mfa:type_name -> ziti.edge_cmd.pb.PostureCheck.Mfa - 53, // 38: ziti.edge_cmd.pb.PostureCheck.osList:type_name -> ziti.edge_cmd.pb.PostureCheck.OsList - 54, // 39: ziti.edge_cmd.pb.PostureCheck.process:type_name -> ziti.edge_cmd.pb.PostureCheck.Process - 55, // 40: ziti.edge_cmd.pb.PostureCheck.processMulti:type_name -> ziti.edge_cmd.pb.PostureCheck.ProcessMulti - 56, // 41: ziti.edge_cmd.pb.PostureCheck.domains:type_name -> ziti.edge_cmd.pb.PostureCheck.Domains - 58, // 42: ziti.edge_cmd.pb.Service.tags:type_name -> ziti.edge_cmd.pb.Service.TagsEntry - 59, // 43: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.tags:type_name -> ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry - 60, // 44: ziti.edge_cmd.pb.ServicePolicy.tags:type_name -> ziti.edge_cmd.pb.ServicePolicy.TagsEntry - 61, // 45: ziti.edge_cmd.pb.TransitRouter.tags:type_name -> ziti.edge_cmd.pb.TransitRouter.TagsEntry - 24, // 46: ziti.edge_cmd.pb.CreateTransitRouterCmd.router:type_name -> ziti.edge_cmd.pb.TransitRouter - 14, // 47: ziti.edge_cmd.pb.CreateTransitRouterCmd.enrollment:type_name -> ziti.edge_cmd.pb.Enrollment - 5, // 48: ziti.edge_cmd.pb.JsonMap.ValueEntry.value:type_name -> ziti.edge_cmd.pb.JsonValue - 2, // 49: ziti.edge_cmd.pb.Authenticator.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 33, // 50: ziti.edge_cmd.pb.AuthPolicy.Primary.cert:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.Cert - 34, // 51: ziti.edge_cmd.pb.AuthPolicy.Primary.updb:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.Updb - 35, // 52: ziti.edge_cmd.pb.AuthPolicy.Primary.extJwt:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.ExtJwt - 2, // 53: ziti.edge_cmd.pb.AuthPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 54: ziti.edge_cmd.pb.Ca.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 55: ziti.edge_cmd.pb.Config.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 56: ziti.edge_cmd.pb.ConfigType.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 57: ziti.edge_cmd.pb.EdgeRouter.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 58: ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 59: ziti.edge_cmd.pb.Enrollment.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 60: ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 61: ziti.edge_cmd.pb.Identity.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 62: ziti.edge_cmd.pb.Mfa.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 52, // 63: ziti.edge_cmd.pb.PostureCheck.OsList.osList:type_name -> ziti.edge_cmd.pb.PostureCheck.Os - 54, // 64: ziti.edge_cmd.pb.PostureCheck.ProcessMulti.processes:type_name -> ziti.edge_cmd.pb.PostureCheck.Process - 2, // 65: ziti.edge_cmd.pb.PostureCheck.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 66: ziti.edge_cmd.pb.Service.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 67: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 68: ziti.edge_cmd.pb.ServicePolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 2, // 69: ziti.edge_cmd.pb.TransitRouter.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue - 70, // [70:70] is the sub-list for method output_type - 70, // [70:70] is the sub-list for method input_type - 70, // [70:70] is the sub-list for extension type_name - 70, // [70:70] is the sub-list for extension extendee - 0, // [0:70] is the sub-list for field type_name + 28, // 0: ziti.edge_cmd.pb.ChangeContext.attributes:type_name -> ziti.edge_cmd.pb.ChangeContext.AttributesEntry + 1, // 1: ziti.edge_cmd.pb.CreateEdgeTerminatorCommand.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 29, // 2: ziti.edge_cmd.pb.JsonMap.value:type_name -> ziti.edge_cmd.pb.JsonMap.ValueEntry + 6, // 3: ziti.edge_cmd.pb.JsonList.value:type_name -> ziti.edge_cmd.pb.JsonValue + 4, // 4: ziti.edge_cmd.pb.JsonValue.mapValue:type_name -> ziti.edge_cmd.pb.JsonMap + 5, // 5: ziti.edge_cmd.pb.JsonValue.listValue:type_name -> ziti.edge_cmd.pb.JsonList + 32, // 6: ziti.edge_cmd.pb.Authenticator.tags:type_name -> ziti.edge_cmd.pb.Authenticator.TagsEntry + 30, // 7: ziti.edge_cmd.pb.Authenticator.cert:type_name -> ziti.edge_cmd.pb.Authenticator.Cert + 31, // 8: ziti.edge_cmd.pb.Authenticator.updb:type_name -> ziti.edge_cmd.pb.Authenticator.Updb + 33, // 9: ziti.edge_cmd.pb.AuthPolicy.primary:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary + 34, // 10: ziti.edge_cmd.pb.AuthPolicy.secondary:type_name -> ziti.edge_cmd.pb.AuthPolicy.Secondary + 35, // 11: ziti.edge_cmd.pb.AuthPolicy.tags:type_name -> ziti.edge_cmd.pb.AuthPolicy.TagsEntry + 40, // 12: ziti.edge_cmd.pb.Ca.tags:type_name -> ziti.edge_cmd.pb.Ca.TagsEntry + 39, // 13: ziti.edge_cmd.pb.Ca.externalIdClaim:type_name -> ziti.edge_cmd.pb.Ca.ExternalIdClaim + 41, // 14: ziti.edge_cmd.pb.Config.tags:type_name -> ziti.edge_cmd.pb.Config.TagsEntry + 42, // 15: ziti.edge_cmd.pb.ConfigType.tags:type_name -> ziti.edge_cmd.pb.ConfigType.TagsEntry + 43, // 16: ziti.edge_cmd.pb.EdgeRouter.tags:type_name -> ziti.edge_cmd.pb.EdgeRouter.TagsEntry + 12, // 17: ziti.edge_cmd.pb.CreateEdgeRouterCmd.edgeRouter:type_name -> ziti.edge_cmd.pb.EdgeRouter + 15, // 18: ziti.edge_cmd.pb.CreateEdgeRouterCmd.enrollment:type_name -> ziti.edge_cmd.pb.Enrollment + 1, // 19: ziti.edge_cmd.pb.CreateEdgeRouterCmd.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 44, // 20: ziti.edge_cmd.pb.EdgeRouterPolicy.tags:type_name -> ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry + 45, // 21: ziti.edge_cmd.pb.Enrollment.tags:type_name -> ziti.edge_cmd.pb.Enrollment.TagsEntry + 66, // 22: ziti.edge_cmd.pb.Enrollment.issuedAt:type_name -> google.protobuf.Timestamp + 66, // 23: ziti.edge_cmd.pb.Enrollment.expiresAt:type_name -> google.protobuf.Timestamp + 7, // 24: ziti.edge_cmd.pb.ReplaceEnrollmentWithAuthenticatorCmd.authenticator:type_name -> ziti.edge_cmd.pb.Authenticator + 1, // 25: ziti.edge_cmd.pb.ReplaceEnrollmentWithAuthenticatorCmd.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 46, // 26: ziti.edge_cmd.pb.ExternalJwtSigner.tags:type_name -> ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry + 66, // 27: ziti.edge_cmd.pb.ExternalJwtSigner.notAfter:type_name -> google.protobuf.Timestamp + 66, // 28: ziti.edge_cmd.pb.ExternalJwtSigner.notBefore:type_name -> google.protobuf.Timestamp + 49, // 29: ziti.edge_cmd.pb.Identity.tags:type_name -> ziti.edge_cmd.pb.Identity.TagsEntry + 47, // 30: ziti.edge_cmd.pb.Identity.envInfo:type_name -> ziti.edge_cmd.pb.Identity.EnvInfo + 48, // 31: ziti.edge_cmd.pb.Identity.sdkInfo:type_name -> ziti.edge_cmd.pb.Identity.SdkInfo + 50, // 32: ziti.edge_cmd.pb.Identity.serviceHostingPrecedences:type_name -> ziti.edge_cmd.pb.Identity.ServiceHostingPrecedencesEntry + 51, // 33: ziti.edge_cmd.pb.Identity.serviceHostingCosts:type_name -> ziti.edge_cmd.pb.Identity.ServiceHostingCostsEntry + 66, // 34: ziti.edge_cmd.pb.Identity.disabledAt:type_name -> google.protobuf.Timestamp + 66, // 35: ziti.edge_cmd.pb.Identity.disabledUntil:type_name -> google.protobuf.Timestamp + 18, // 36: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd.identity:type_name -> ziti.edge_cmd.pb.Identity + 15, // 37: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd.enrollments:type_name -> ziti.edge_cmd.pb.Enrollment + 1, // 38: ziti.edge_cmd.pb.CreateIdentityWithEnrollmentsCmd.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 52, // 39: ziti.edge_cmd.pb.Mfa.tags:type_name -> ziti.edge_cmd.pb.Mfa.TagsEntry + 60, // 40: ziti.edge_cmd.pb.PostureCheck.tags:type_name -> ziti.edge_cmd.pb.PostureCheck.TagsEntry + 53, // 41: ziti.edge_cmd.pb.PostureCheck.mac:type_name -> ziti.edge_cmd.pb.PostureCheck.Mac + 54, // 42: ziti.edge_cmd.pb.PostureCheck.mfa:type_name -> ziti.edge_cmd.pb.PostureCheck.Mfa + 56, // 43: ziti.edge_cmd.pb.PostureCheck.osList:type_name -> ziti.edge_cmd.pb.PostureCheck.OsList + 57, // 44: ziti.edge_cmd.pb.PostureCheck.process:type_name -> ziti.edge_cmd.pb.PostureCheck.Process + 58, // 45: ziti.edge_cmd.pb.PostureCheck.processMulti:type_name -> ziti.edge_cmd.pb.PostureCheck.ProcessMulti + 59, // 46: ziti.edge_cmd.pb.PostureCheck.domains:type_name -> ziti.edge_cmd.pb.PostureCheck.Domains + 61, // 47: ziti.edge_cmd.pb.Service.tags:type_name -> ziti.edge_cmd.pb.Service.TagsEntry + 62, // 48: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.tags:type_name -> ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry + 63, // 49: ziti.edge_cmd.pb.ServicePolicy.tags:type_name -> ziti.edge_cmd.pb.ServicePolicy.TagsEntry + 64, // 50: ziti.edge_cmd.pb.TransitRouter.tags:type_name -> ziti.edge_cmd.pb.TransitRouter.TagsEntry + 25, // 51: ziti.edge_cmd.pb.CreateTransitRouterCmd.router:type_name -> ziti.edge_cmd.pb.TransitRouter + 15, // 52: ziti.edge_cmd.pb.CreateTransitRouterCmd.enrollment:type_name -> ziti.edge_cmd.pb.Enrollment + 1, // 53: ziti.edge_cmd.pb.CreateTransitRouterCmd.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 65, // 54: ziti.edge_cmd.pb.UpdateServiceConfigsCmd.serviceConfigs:type_name -> ziti.edge_cmd.pb.UpdateServiceConfigsCmd.ServiceConfig + 1, // 55: ziti.edge_cmd.pb.UpdateServiceConfigsCmd.ctx:type_name -> ziti.edge_cmd.pb.ChangeContext + 6, // 56: ziti.edge_cmd.pb.JsonMap.ValueEntry.value:type_name -> ziti.edge_cmd.pb.JsonValue + 3, // 57: ziti.edge_cmd.pb.Authenticator.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 36, // 58: ziti.edge_cmd.pb.AuthPolicy.Primary.cert:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.Cert + 37, // 59: ziti.edge_cmd.pb.AuthPolicy.Primary.updb:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.Updb + 38, // 60: ziti.edge_cmd.pb.AuthPolicy.Primary.extJwt:type_name -> ziti.edge_cmd.pb.AuthPolicy.Primary.ExtJwt + 3, // 61: ziti.edge_cmd.pb.AuthPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 62: ziti.edge_cmd.pb.Ca.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 63: ziti.edge_cmd.pb.Config.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 64: ziti.edge_cmd.pb.ConfigType.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 65: ziti.edge_cmd.pb.EdgeRouter.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 66: ziti.edge_cmd.pb.EdgeRouterPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 67: ziti.edge_cmd.pb.Enrollment.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 68: ziti.edge_cmd.pb.ExternalJwtSigner.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 69: ziti.edge_cmd.pb.Identity.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 70: ziti.edge_cmd.pb.Mfa.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 55, // 71: ziti.edge_cmd.pb.PostureCheck.OsList.osList:type_name -> ziti.edge_cmd.pb.PostureCheck.Os + 57, // 72: ziti.edge_cmd.pb.PostureCheck.ProcessMulti.processes:type_name -> ziti.edge_cmd.pb.PostureCheck.Process + 3, // 73: ziti.edge_cmd.pb.PostureCheck.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 74: ziti.edge_cmd.pb.Service.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 75: ziti.edge_cmd.pb.ServiceEdgeRouterPolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 76: ziti.edge_cmd.pb.ServicePolicy.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 3, // 77: ziti.edge_cmd.pb.TransitRouter.TagsEntry.value:type_name -> ziti.edge_cmd.pb.TagValue + 78, // [78:78] is the sub-list for method output_type + 78, // [78:78] is the sub-list for method input_type + 78, // [78:78] is the sub-list for extension type_name + 78, // [78:78] is the sub-list for extension extendee + 0, // [0:78] is the sub-list for field type_name } func init() { file_edge_cmd_proto_init() } @@ -4626,7 +4911,7 @@ func file_edge_cmd_proto_init() { } if !protoimpl.UnsafeEnabled { file_edge_cmd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateEdgeTerminatorCommand); i { + switch v := v.(*ChangeContext); i { case 0: return &v.state case 1: @@ -4638,7 +4923,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TagValue); i { + switch v := v.(*CreateEdgeTerminatorCommand); i { case 0: return &v.state case 1: @@ -4650,7 +4935,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JsonMap); i { + switch v := v.(*TagValue); i { case 0: return &v.state case 1: @@ -4662,7 +4947,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JsonList); i { + switch v := v.(*JsonMap); i { case 0: return &v.state case 1: @@ -4674,7 +4959,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JsonValue); i { + switch v := v.(*JsonList); i { case 0: return &v.state case 1: @@ -4686,7 +4971,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Authenticator); i { + switch v := v.(*JsonValue); i { case 0: return &v.state case 1: @@ -4698,7 +4983,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy); i { + switch v := v.(*Authenticator); i { case 0: return &v.state case 1: @@ -4710,7 +4995,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Ca); i { + switch v := v.(*AuthPolicy); i { case 0: return &v.state case 1: @@ -4722,7 +5007,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Config); i { + switch v := v.(*Ca); i { case 0: return &v.state case 1: @@ -4734,7 +5019,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigType); i { + switch v := v.(*Config); i { case 0: return &v.state case 1: @@ -4746,7 +5031,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EdgeRouter); i { + switch v := v.(*ConfigType); i { case 0: return &v.state case 1: @@ -4758,7 +5043,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateEdgeRouterCmd); i { + switch v := v.(*EdgeRouter); i { case 0: return &v.state case 1: @@ -4770,7 +5055,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EdgeRouterPolicy); i { + switch v := v.(*CreateEdgeRouterCmd); i { case 0: return &v.state case 1: @@ -4782,7 +5067,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Enrollment); i { + switch v := v.(*EdgeRouterPolicy); i { case 0: return &v.state case 1: @@ -4794,7 +5079,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplaceEnrollmentWithAuthenticatorCmd); i { + switch v := v.(*Enrollment); i { case 0: return &v.state case 1: @@ -4806,7 +5091,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExternalJwtSigner); i { + switch v := v.(*ReplaceEnrollmentWithAuthenticatorCmd); i { case 0: return &v.state case 1: @@ -4818,7 +5103,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Identity); i { + switch v := v.(*ExternalJwtSigner); i { case 0: return &v.state case 1: @@ -4830,7 +5115,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateIdentityWithEnrollmentsCmd); i { + switch v := v.(*Identity); i { case 0: return &v.state case 1: @@ -4842,7 +5127,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Mfa); i { + switch v := v.(*CreateIdentityWithEnrollmentsCmd); i { case 0: return &v.state case 1: @@ -4854,7 +5139,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureCheck); i { + switch v := v.(*Mfa); i { case 0: return &v.state case 1: @@ -4866,7 +5151,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Service); i { + switch v := v.(*PostureCheck); i { case 0: return &v.state case 1: @@ -4878,7 +5163,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceEdgeRouterPolicy); i { + switch v := v.(*Service); i { case 0: return &v.state case 1: @@ -4890,7 +5175,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicePolicy); i { + switch v := v.(*ServiceEdgeRouterPolicy); i { case 0: return &v.state case 1: @@ -4902,7 +5187,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransitRouter); i { + switch v := v.(*ServicePolicy); i { case 0: return &v.state case 1: @@ -4914,6 +5199,18 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransitRouter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_cmd_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateTransitRouterCmd); i { case 0: return &v.state @@ -4926,19 +5223,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Authenticator_Cert); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_edge_cmd_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Authenticator_Updb); i { + switch v := v.(*UpdateServiceConfigsCmd); i { case 0: return &v.state case 1: @@ -4950,7 +5235,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy_Primary); i { + switch v := v.(*Authenticator_Cert); i { case 0: return &v.state case 1: @@ -4962,7 +5247,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy_Secondary); i { + switch v := v.(*Authenticator_Updb); i { case 0: return &v.state case 1: @@ -4974,7 +5259,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy_Primary_Cert); i { + switch v := v.(*AuthPolicy_Primary); i { case 0: return &v.state case 1: @@ -4986,19 +5271,7 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy_Primary_Updb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_edge_cmd_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthPolicy_Primary_ExtJwt); i { + switch v := v.(*AuthPolicy_Secondary); i { case 0: return &v.state case 1: @@ -5010,6 +5283,42 @@ func file_edge_cmd_proto_init() { } } file_edge_cmd_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthPolicy_Primary_Cert); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_cmd_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthPolicy_Primary_Updb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_cmd_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthPolicy_Primary_ExtJwt); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_cmd_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Ca_ExternalIdClaim); i { case 0: return &v.state @@ -5021,7 +5330,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Identity_EnvInfo); i { case 0: return &v.state @@ -5033,7 +5342,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Identity_SdkInfo); i { case 0: return &v.state @@ -5045,7 +5354,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_Mac); i { case 0: return &v.state @@ -5057,7 +5366,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_Mfa); i { case 0: return &v.state @@ -5069,7 +5378,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_Os); i { case 0: return &v.state @@ -5081,7 +5390,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_OsList); i { case 0: return &v.state @@ -5093,7 +5402,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_Process); i { case 0: return &v.state @@ -5105,7 +5414,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_ProcessMulti); i { case 0: return &v.state @@ -5117,7 +5426,7 @@ func file_edge_cmd_proto_init() { return nil } } - file_edge_cmd_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + file_edge_cmd_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureCheck_Domains); i { case 0: return &v.state @@ -5129,14 +5438,26 @@ func file_edge_cmd_proto_init() { return nil } } + file_edge_cmd_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateServiceConfigsCmd_ServiceConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } - file_edge_cmd_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_edge_cmd_proto_msgTypes[2].OneofWrappers = []interface{}{ (*TagValue_BoolValue)(nil), (*TagValue_StringValue)(nil), (*TagValue_FpValue)(nil), (*TagValue_NilValue)(nil), } - file_edge_cmd_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_edge_cmd_proto_msgTypes[5].OneofWrappers = []interface{}{ (*JsonValue_BoolValue)(nil), (*JsonValue_StringValue)(nil), (*JsonValue_FpValue)(nil), @@ -5145,16 +5466,16 @@ func file_edge_cmd_proto_init() { (*JsonValue_MapValue)(nil), (*JsonValue_ListValue)(nil), } - file_edge_cmd_proto_msgTypes[5].OneofWrappers = []interface{}{ + file_edge_cmd_proto_msgTypes[6].OneofWrappers = []interface{}{ (*Authenticator_Cert_)(nil), (*Authenticator_Updb_)(nil), } - file_edge_cmd_proto_msgTypes[7].OneofWrappers = []interface{}{} - file_edge_cmd_proto_msgTypes[10].OneofWrappers = []interface{}{} - file_edge_cmd_proto_msgTypes[13].OneofWrappers = []interface{}{} - file_edge_cmd_proto_msgTypes[15].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[8].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[11].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[14].OneofWrappers = []interface{}{} file_edge_cmd_proto_msgTypes[16].OneofWrappers = []interface{}{} - file_edge_cmd_proto_msgTypes[19].OneofWrappers = []interface{}{ + file_edge_cmd_proto_msgTypes[17].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[20].OneofWrappers = []interface{}{ (*PostureCheck_Mac_)(nil), (*PostureCheck_Mfa_)(nil), (*PostureCheck_OsList_)(nil), @@ -5162,15 +5483,15 @@ func file_edge_cmd_proto_init() { (*PostureCheck_ProcessMulti_)(nil), (*PostureCheck_Domains_)(nil), } - file_edge_cmd_proto_msgTypes[23].OneofWrappers = []interface{}{} - file_edge_cmd_proto_msgTypes[30].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[24].OneofWrappers = []interface{}{} + file_edge_cmd_proto_msgTypes[33].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_edge_cmd_proto_rawDesc, NumEnums: 1, - NumMessages: 61, + NumMessages: 65, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/edge_cmd_pb/edge_cmd.proto b/pb/edge_cmd_pb/edge_cmd.proto index 7ffb818e7..c1c31cb98 100644 --- a/pb/edge_cmd_pb/edge_cmd.proto +++ b/pb/edge_cmd_pb/edge_cmd.proto @@ -12,10 +12,19 @@ enum CommandType { CreateEdgeRouterType = 1002; CreateTransitRouterType = 1003; CreateIdentityWithEnrollmentsType = 1004; + UpdateServiceConfigsType = 1005; } +message ChangeContext { + map attributes = 1; + uint64 raftIndex = 2; +} + + message CreateEdgeTerminatorCommand { bytes terminatorData = 1; + + ChangeContext ctx = 2; } message TagValue { @@ -177,6 +186,8 @@ message EdgeRouter { message CreateEdgeRouterCmd { EdgeRouter edgeRouter = 1; Enrollment enrollment = 2; + + ChangeContext ctx = 3; } // Edge Router Policies @@ -208,6 +219,8 @@ message Enrollment { message ReplaceEnrollmentWithAuthenticatorCmd { string enrollmentId = 1; Authenticator authenticator = 2; + + ChangeContext ctx = 3; } // External JWT Signers @@ -272,6 +285,8 @@ message Identity { message CreateIdentityWithEnrollmentsCmd { Identity identity = 1; repeated Enrollment enrollments = 2; + + ChangeContext ctx = 3; } // MFA @@ -391,5 +406,18 @@ message TransitRouter { message CreateTransitRouterCmd { TransitRouter router = 1; Enrollment enrollment = 2; + + ChangeContext ctx = 3; } +message UpdateServiceConfigsCmd { + message ServiceConfig { + string serviceId = 1; + string configId = 2; + } + + string identityId = 1; + bool add = 2; + repeated ServiceConfig serviceConfigs = 3; + ChangeContext ctx = 4; +} \ No newline at end of file diff --git a/pb/edge_cmd_pb/impl.go b/pb/edge_cmd_pb/impl.go index 433b6eeea..7c214f380 100644 --- a/pb/edge_cmd_pb/impl.go +++ b/pb/edge_cmd_pb/impl.go @@ -20,6 +20,10 @@ func (x *CreateIdentityWithEnrollmentsCmd) GetCommandType() int32 { return int32(CommandType_CreateIdentityWithEnrollmentsType) } +func (x *UpdateServiceConfigsCmd) GetCommandType() int32 { + return int32(CommandType_UpdateServiceConfigsType) +} + func EncodeTags(tags map[string]interface{}) (map[string]*TagValue, error) { if len(tags) == 0 { return nil, nil diff --git a/router/xgress_edge/factory_test.go b/router/xgress_edge/factory_test.go index a9b186e22..8d5bc4c8f 100644 --- a/router/xgress_edge/factory_test.go +++ b/router/xgress_edge/factory_test.go @@ -45,7 +45,7 @@ func Test_load(t *testing.T) { }) t.Run("has ConnectTimeout value set", func(t *testing.T) { - require.New(t).Equal(connectTimeout, options.channelOptions.ConnectTimeout) + require.New(t).Equal(connectTimeout*time.Millisecond, options.channelOptions.ConnectTimeout) }) }) @@ -108,7 +108,7 @@ func Test_load(t *testing.T) { const ( connectMaxQueuedConnections = 50 connectMaxOutstandingConnects = 100 - connectTimeout = 1000 * time.Millisecond + connectTimeout = 1000 ) func newTestConfigWithConnectOptions() xgress.OptionsData { @@ -119,7 +119,7 @@ func newTestConfigWithConnectOptions() xgress.OptionsData { "advertise": "127.0.0.1:3022", "maxQueuedConnects": connectMaxQueuedConnections, "maxOutstandingConnects": connectMaxOutstandingConnects, - "connectTimeout": connectTimeout.String(), + "connectTimeoutMs": connectTimeout, }, } } diff --git a/tests/auth_cert_test.go b/tests/auth_cert_test.go index 7495fed75..5591e1443 100644 --- a/tests/auth_cert_test.go +++ b/tests/auth_cert_test.go @@ -32,6 +32,7 @@ import ( "github.com/openziti/edge/controller/model" "github.com/openziti/edge/eid" "github.com/openziti/edge/internal/cert" + "github.com/openziti/fabric/controller/change" nfPem "github.com/openziti/foundation/v2/pem" "github.com/openziti/sdk-golang/ziti/constants" "github.com/stretchr/testify/require" @@ -96,7 +97,7 @@ func (test *authCertTests) testAuthenticateCertStoresAndFillsFullCert(t *testing certAuth.Pem = "" - err = test.ctx.EdgeController.AppEnv.Managers.Authenticator.Update(authenticator, false, nil) + err = test.ctx.EdgeController.AppEnv.Managers.Authenticator.Update(authenticator, false, nil, change.New().SetSource("test")) r.NoError(err) authenticator, err = test.ctx.EdgeController.AppEnv.Managers.Authenticator.ReadByFingerprint(test.certAuthenticator.Fingerprint()) diff --git a/tests/router_identities_test.go b/tests/router_identities_test.go index dd59879ff..d48453517 100644 --- a/tests/router_identities_test.go +++ b/tests/router_identities_test.go @@ -1,3 +1,4 @@ +//go:build apitests // +build apitests /* @@ -74,7 +75,7 @@ func TestEdgeRouterIdentities(t *testing.T) { resp = ctx.AdminManagementSession.deleteEntityOfType("edge-router-policies", edgeRouterPolicy1.id) ctx.Req.Equal(http.StatusBadRequest, resp.StatusCode()) - // deleting edge router should remove all three entitie + // deleting edge router should remove all three entities ctx.AdminManagementSession.requireDeleteEntity(edgeRouter1) ctx.RequireNotFoundError(ctx.AdminManagementSession.query("edge-routers/" + edgeRouter1.id)) ctx.RequireNotFoundError(ctx.AdminManagementSession.query("identities/" + identity1.Id)) diff --git a/tests/transit_router_test.go b/tests/transit_router_test.go index a57734a27..89cc0fd9b 100644 --- a/tests/transit_router_test.go +++ b/tests/transit_router_test.go @@ -20,6 +20,7 @@ package tests import ( + "github.com/openziti/fabric/controller/change" "github.com/openziti/fabric/controller/models" "github.com/openziti/fabric/controller/network" "testing" @@ -115,7 +116,7 @@ func Test_TransitRouters(t *testing.T) { Name: "uMvqq", Fingerprint: &fp, } - err := ctx.fabricController.GetNetwork().Routers.Create(fabTxRouter) + err := ctx.fabricController.GetNetwork().Routers.Create(fabTxRouter, change.New().SetSource("test")) ctx.Req.NoError(err, "could not create router at fabric level") body := ctx.AdminManagementSession.requireQuery("transit-routers")