mirror of
https://github.com/openziti/ziti.git
synced 2026-09-23 19:06:38 +00:00
fixes #129, errors w/ tx enrollment
- addresses issues w/ tests not covering the error - adds tests that run transit routers post enrollment - adds test that list mixed transit routers (enrolled, not, fabric)
This commit is contained in:
@@ -119,7 +119,7 @@ func MapTransitRouterToApiEntity(appEnv *env.AppEnv, context *response.RequestCo
|
||||
enrollment := enrollments[0]
|
||||
|
||||
ret.EnrollmentExpiresAt = enrollment.ExpiresAt
|
||||
ret.EnrollmentCreatedAt = &enrollment.CreatedAt
|
||||
ret.EnrollmentCreatedAt = enrollment.IssuedAt
|
||||
ret.EnrollmentJwt = &enrollment.Jwt
|
||||
ret.EnrollmentToken = &enrollment.Token
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ func (ir *TransitRouterRouter) Delete(ae *env.AppEnv, rc *response.RequestContex
|
||||
func (ir *TransitRouterRouter) Update(ae *env.AppEnv, rc *response.RequestContext) {
|
||||
transitRouterUpdate := &TransitRouterApi{}
|
||||
Update(rc, ae.Schemes.TransitRouter.Put, ir.IdType, transitRouterUpdate, func(id string) error {
|
||||
return ae.Handlers.TransitRouter.Update(transitRouterUpdate.ToModel(id))
|
||||
return ae.Handlers.TransitRouter.Update(transitRouterUpdate.ToModel(id), false)
|
||||
})
|
||||
}
|
||||
|
||||
func (ir *TransitRouterRouter) Patch(ae *env.AppEnv, rc *response.RequestContext) {
|
||||
transitRouterUpdate := &TransitRouterApi{}
|
||||
Patch(rc, ae.Schemes.TransitRouter.Patch, ir.IdType, transitRouterUpdate, func(id string, fields JsonFields) error {
|
||||
return ae.Handlers.TransitRouter.Patch(transitRouterUpdate.ToModel(id), fields.ConcatNestedNames().FilterMaps("tags"))
|
||||
return ae.Handlers.TransitRouter.Patch(transitRouterUpdate.ToModel(id), fields.ConcatNestedNames().FilterMaps("tags"), false)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/netfoundry/ziti-edge/controller/validation"
|
||||
"github.com/netfoundry/ziti-edge/internal/cert"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -152,9 +153,9 @@ func (module *EnrollModuleRouterOtt) Process(context EnrollmentContext) (*Enroll
|
||||
cltFp := module.fingerprintGenerator.FromPem(cltPem)
|
||||
|
||||
txRouter.IsVerified = true
|
||||
txRouter.Fingerprint = cltFp
|
||||
txRouter.Fingerprint = strings.ToLower(strings.Replace(cltFp, ":", "", -1))
|
||||
|
||||
if err := module.env.GetHandlers().TransitRouter.Update(txRouter); err != nil {
|
||||
if err := module.env.GetHandlers().TransitRouter.Update(txRouter, true); err != nil {
|
||||
return nil, fmt.Errorf("could not update edge router: %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ import (
|
||||
func NewTransitRouterHandler(env Env) *TransitRouterHandler {
|
||||
handler := &TransitRouterHandler{
|
||||
baseHandler: newBaseHandler(env, env.GetStores().TransitRouter),
|
||||
allowedFields: boltz.MapFieldChecker{
|
||||
persistence.FieldName: struct{}{},
|
||||
boltz.FieldTags: struct{}{},
|
||||
},
|
||||
}
|
||||
handler.impl = handler
|
||||
return handler
|
||||
@@ -35,6 +39,7 @@ func NewTransitRouterHandler(env Env) *TransitRouterHandler {
|
||||
|
||||
type TransitRouterHandler struct {
|
||||
baseHandler
|
||||
allowedFields boltz.FieldChecker
|
||||
}
|
||||
|
||||
func (handler *TransitRouterHandler) Delete(id string) error {
|
||||
@@ -97,12 +102,21 @@ func (handler *TransitRouterHandler) CreateWithEnrollment(txRouter *TransitRoute
|
||||
return txRouter.Id, enrollmentId, nil
|
||||
}
|
||||
|
||||
func (handler *TransitRouterHandler) Update(entity *TransitRouter) error {
|
||||
return handler.updateEntity(entity, nil)
|
||||
func (handler *TransitRouterHandler) Update(entity *TransitRouter, allowAllFields bool) error {
|
||||
if allowAllFields {
|
||||
return handler.updateEntity(entity, nil)
|
||||
}
|
||||
|
||||
return handler.updateEntity(entity, handler.allowedFields)
|
||||
|
||||
}
|
||||
|
||||
func (handler *TransitRouterHandler) Patch(entity *TransitRouter, checker boltz.FieldChecker) error {
|
||||
return handler.patchEntity(entity, checker)
|
||||
func (handler *TransitRouterHandler) Patch(entity *TransitRouter, checker boltz.FieldChecker, allowAllFields bool) error {
|
||||
if allowAllFields {
|
||||
return handler.patchEntity(entity, checker)
|
||||
}
|
||||
combinedChecker := &AndFieldChecker{first: handler.allowedFields, second: checker}
|
||||
return handler.patchEntity(entity, combinedChecker)
|
||||
}
|
||||
|
||||
func (handler *TransitRouterHandler) ReadOneByQuery(query string) (*TransitRouter, error) {
|
||||
|
||||
@@ -51,8 +51,10 @@ func (entity *TransitRouter) toBoltEntityForUpdate(tx *bbolt.Tx, handler Handler
|
||||
ret := &persistence.TransitRouter{
|
||||
Router: db.Router{
|
||||
BaseExtEntity: *boltz.NewExtEntity(entity.Id, entity.Tags),
|
||||
Fingerprint: entity.Fingerprint,
|
||||
},
|
||||
Name: entity.Name,
|
||||
Name: entity.Name,
|
||||
IsVerified: entity.IsVerified,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
@@ -78,7 +78,11 @@ func (entity *TransitRouter) LoadValues(store boltz.CrudStore, bucket *boltz.Typ
|
||||
func (entity *TransitRouter) SetValues(ctx *boltz.PersistContext) {
|
||||
entity.Router.SetValues(ctx.GetParentContext())
|
||||
entity.SetBaseValues(ctx)
|
||||
ctx.SetString(FieldName, entity.Name)
|
||||
if ctx.Bucket != nil {
|
||||
ctx.SetString(FieldName, entity.Name)
|
||||
ctx.SetBool(FieldTransitRouterIsVerified, entity.IsVerified)
|
||||
ctx.SetStringList(FieldTransitRouterEnrollments, entity.Enrollments)
|
||||
}
|
||||
}
|
||||
|
||||
func (entity *TransitRouter) GetEntityType() string {
|
||||
|
||||
@@ -267,6 +267,19 @@ func (ctx *TestContext) createAndEnrollTransitRouter() *transitRouter {
|
||||
return ctx.transitRouterEntity
|
||||
}
|
||||
|
||||
func (ctx *TestContext) createEnrollAndStartTransitRouter() {
|
||||
ctx.createAndEnrollTransitRouter()
|
||||
ctx.startTransitRouter()
|
||||
}
|
||||
|
||||
func (ctx *TestContext) startTransitRouter() {
|
||||
config, err := router.LoadConfig(TransitRouterConfFile)
|
||||
ctx.req.NoError(err)
|
||||
ctx.router = router.Create(config)
|
||||
|
||||
ctx.req.NoError(ctx.router.Start())
|
||||
}
|
||||
|
||||
func (ctx *TestContext) createEnrollAndStartEdgeRouter(roleAttributes ...string) {
|
||||
ctx.createAndEnrollEdgeRouter(roleAttributes...)
|
||||
|
||||
@@ -518,3 +531,58 @@ func (ctx *TestContext) idsJson(ids ...string) *gabs.Container {
|
||||
ctx.setJsonValue(entityData, ids, "ids")
|
||||
return entityData
|
||||
}
|
||||
|
||||
func (ctx *TestContext) requireEntityNotEnrolled(name string, entity *gabs.Container) {
|
||||
fingerprint, ok := entity.Path("fingerprint").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to not have a fingerprint, could not cast")
|
||||
ctx.req.Empty(fingerprint, "expected "+name+" with isVerified=false to have an empty fingerprint")
|
||||
|
||||
token, ok := entity.Path("enrollmentToken").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to have an enrollment token, could not cast")
|
||||
ctx.req.NotEmpty(token, "expected "+name+" with isVerified=false to have an enrollment token, was empty")
|
||||
|
||||
jwt, ok := entity.Path("enrollmentJwt").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to have an enrollment jwt, could not cast")
|
||||
ctx.req.NotEmpty(jwt, "expected "+name+" with isVerified=false to have an enrollment jwt, was empty")
|
||||
|
||||
createdAtStr, ok := entity.Path("enrollmentCreatedAt").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to have an enrollment created at date, could not cast")
|
||||
ctx.req.NotEmpty(createdAtStr, "expected "+name+" with isVerified=false to have an enrollment created at date string, was empty")
|
||||
|
||||
createdAt, err := time.Parse(time.RFC3339, createdAtStr)
|
||||
ctx.req.NoError(err, "expected "+name+" with isVerified=false to have a parsable created at date time string")
|
||||
ctx.req.NotEmpty(createdAt, "expected "+name+" with isVerified=false to have an enrollment created at date, was empty")
|
||||
|
||||
expiresAtStr, ok := entity.Path("enrollmentExpiresAt").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to have an enrollment expires at date, could not cast")
|
||||
ctx.req.NotEmpty(expiresAtStr, "expected "+name+" with isVerified=false to have an enrollment expires at date string, was empty")
|
||||
|
||||
expiresAt, err := time.Parse(time.RFC3339, expiresAtStr)
|
||||
ctx.req.NoError(err, "expected "+name+" with isVerified=false to have a parsable expires at date time string")
|
||||
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=false to have an enrollment expires at date, could not cast")
|
||||
ctx.req.NotEmpty(expiresAt, "expected "+name+" with isVerified=false to have an enrollment expires at date, was empty")
|
||||
|
||||
ctx.req.True(expiresAt.After(createdAt), "expected "+name+" with isVerified=false to have an enrollment expires at date after the created at date")
|
||||
}
|
||||
|
||||
func (ctx *TestContext) requireEntityEnrolled(name string, entity *gabs.Container) {
|
||||
fingerprint, ok := entity.Path("fingerprint").Data().(string)
|
||||
ctx.req.True(ok, "expected "+name+" with isVerified=true to have a fingerprint, could not cast")
|
||||
ctx.req.NotEmpty(fingerprint, "expected "+name+" with isVerified=true to have a fingerprint, was empty")
|
||||
ctx.req.False(strings.Contains(fingerprint, ":"), "fingerprint should not contain colons")
|
||||
ctx.req.False(strings.ToLower(fingerprint) != fingerprint, "fingerprint should not contain uppercase characters")
|
||||
|
||||
token := entity.Path("enrollmentToken").Data()
|
||||
ctx.req.Nil(token, "expected "+name+" with isVerified=true to have an nil enrollment token")
|
||||
|
||||
jwt := entity.Path("enrollmentJwt").Data()
|
||||
ctx.req.Nil(jwt, "expected "+name+" with isVerified=true to have an nil enrollment jwt")
|
||||
|
||||
createdAt := entity.Path("enrollmentCreatedAt").Data()
|
||||
ctx.req.Nil(createdAt, "expected "+name+" with isVerified=true to have an nil enrollment created at date")
|
||||
|
||||
expiresAt := entity.Path("enrollmentExpiresAt").Data()
|
||||
ctx.req.Nil(expiresAt, "expected "+name+" with isVerified=true to have an nil enrollment expires at date")
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/netfoundry/ziti-fabric/controller/models"
|
||||
"github.com/netfoundry/ziti-fabric/controller/network"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_TransitRouters(t *testing.T) {
|
||||
@@ -33,6 +36,56 @@ func Test_TransitRouters(t *testing.T) {
|
||||
ctx.createAndEnrollTransitRouter()
|
||||
})
|
||||
|
||||
t.Run("transit routers can be created, enrolled, and started", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
ctx.createEnrollAndStartTransitRouter()
|
||||
})
|
||||
|
||||
t.Run("transit routers can be created, enrolled, and listed", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
ctx.AdminSession.requireQuery("transit-routers")
|
||||
})
|
||||
|
||||
t.Run("transit routers can be listed with enrolled and un-enrolled states", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
ctx.createAndEnrollTransitRouter()
|
||||
_ = ctx.AdminSession.requireNewTransitRouter()
|
||||
|
||||
body := ctx.AdminSession.requireQuery("transit-routers")
|
||||
ctx.logJson(body.Bytes())
|
||||
|
||||
t.Run("enrolled router is verified and has a fingerprint, un-enrolled router does not", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
|
||||
routers := body.Path("data")
|
||||
|
||||
children, err := routers.Children()
|
||||
ctx.req.NoError(err)
|
||||
|
||||
ctx.req.Len(children, 2, "two routers should have been returned")
|
||||
|
||||
router0IsVerified, ok := children[0].Path("isVerified").Data().(bool)
|
||||
ctx.req.True(ok, "issue getting transit router 0 isVerified state")
|
||||
|
||||
router1IsVerified, ok := children[1].Path("isVerified").Data().(bool)
|
||||
ctx.req.True(ok, "issue getting transit router 1 isVerified state")
|
||||
|
||||
ctx.req.True(router0IsVerified != router1IsVerified, "expected 1 enrolled transit router and 1 un-enrolled transit router")
|
||||
|
||||
if router0IsVerified {
|
||||
ctx.requireEntityEnrolled("transit router 0", children[0])
|
||||
} else {
|
||||
ctx.requireEntityNotEnrolled("transit router 0", children[0])
|
||||
}
|
||||
|
||||
if router1IsVerified {
|
||||
ctx.requireEntityEnrolled("transit router 1", children[1])
|
||||
} else {
|
||||
ctx.requireEntityNotEnrolled("transit router 1", children[1])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("create transit router, then delete", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
router := ctx.AdminSession.requireNewTransitRouter()
|
||||
@@ -44,4 +97,24 @@ func Test_TransitRouters(t *testing.T) {
|
||||
router := ctx.createAndEnrollTransitRouter()
|
||||
ctx.AdminSession.requireDeleteEntity(router)
|
||||
})
|
||||
|
||||
t.Run("can list transit routers created in fabric", func(t *testing.T) {
|
||||
ctx.testContextChanged(t)
|
||||
|
||||
fabTxRouter := &network.Router{
|
||||
BaseEntity: models.BaseEntity{
|
||||
Id: "uMvqq",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Tags: nil,
|
||||
},
|
||||
Fingerprint: "f6fc1c03175f674f1f0b505a9ff930e5",
|
||||
AdvertisedListener: "tls:127.0.0.1",
|
||||
}
|
||||
err := ctx.fabricController.GetNetwork().Routers.Create(fabTxRouter)
|
||||
ctx.req.NoError(err, "could not create router at fabric level")
|
||||
|
||||
body := ctx.AdminSession.requireQuery("transit-routers")
|
||||
ctx.logJson(body.Bytes())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user