From 280b0fbd50888f97aff42281e0a83afd00560ec6 Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 11 Apr 2023 12:05:19 +0200 Subject: [PATCH] feat(controller,app): validate app manifests on app load --- internal/agent/controller/app/app_handler.go | 33 +--------- internal/agent/controller/app/auth_module.go | 65 ++++++++++++++++++++ internal/agent/controller/app/controller.go | 17 ++++- internal/agent/controller/app/manifest.go | 19 ++++++ 4 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 internal/agent/controller/app/auth_module.go create mode 100644 internal/agent/controller/app/manifest.go diff --git a/internal/agent/controller/app/app_handler.go b/internal/agent/controller/app/app_handler.go index 23c0140..61b8dc5 100644 --- a/internal/agent/controller/app/app_handler.go +++ b/internal/agent/controller/app/app_handler.go @@ -17,14 +17,12 @@ import ( edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http" "forge.cadoles.com/arcad/edge/pkg/module" appModule "forge.cadoles.com/arcad/edge/pkg/module/app" - "forge.cadoles.com/arcad/edge/pkg/module/auth" "forge.cadoles.com/arcad/edge/pkg/module/blob" "forge.cadoles.com/arcad/edge/pkg/module/cast" fetchModule "forge.cadoles.com/arcad/edge/pkg/module/fetch" netModule "forge.cadoles.com/arcad/edge/pkg/module/net" "forge.cadoles.com/arcad/edge/pkg/storage/sqlite" "github.com/Masterminds/sprig/v3" - "github.com/dop251/goja" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" @@ -49,12 +47,6 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs return nil, errors.Wrap(err, "could not retrieve auth key set") } - bundles := make([]string, 0, len(specs.Apps)) - for appKey, app := range specs.Apps { - path := c.getAppBundlePath(appKey, app.Format) - bundles = append(bundles, path) - } - bus := memory.NewBus() modules := c.getAppModules(bus, db, specs, keySet) @@ -252,30 +244,7 @@ func (c *Controller) getAppModules(bus bus.Bus, db *sql.DB, spec *appSpec.Spec, module.RPCModuleFactory(bus), module.StoreModuleFactory(ds), blob.ModuleFactory(bus, bs), - module.Extends( - auth.ModuleFactory( - auth.WithJWT(func() (jwk.Set, error) { - return keySet, nil - }), - ), - func(o *goja.Object) { - if err := o.Set("CLAIM_TENANT", "arcad_tenant"); err != nil { - panic(errors.New("could not set 'CLAIM_TENANT' property")) - } - - if err := o.Set("CLAIM_ENTRYPOINT", "arcad_entrypoint"); err != nil { - panic(errors.New("could not set 'CLAIM_ENTRYPOINT' property")) - } - - if err := o.Set("CLAIM_ROLE", "arcad_role"); err != nil { - panic(errors.New("could not set 'CLAIM_ROLE' property")) - } - - if err := o.Set("CLAIM_PREFERRED_USERNAME", "preferred_username"); err != nil { - panic(errors.New("could not set 'CLAIM_PREFERRED_USERNAME' property")) - } - }, - ), + authModule(keySet), appModule.ModuleFactory(c.appRepository), fetchModule.ModuleFactory(bus), } diff --git a/internal/agent/controller/app/auth_module.go b/internal/agent/controller/app/auth_module.go new file mode 100644 index 0000000..3891f98 --- /dev/null +++ b/internal/agent/controller/app/auth_module.go @@ -0,0 +1,65 @@ +package app + +import ( + "forge.cadoles.com/Cadoles/emissary/internal/jwk" + "forge.cadoles.com/arcad/edge/pkg/app" + "forge.cadoles.com/arcad/edge/pkg/module" + "forge.cadoles.com/arcad/edge/pkg/module/auth" + "github.com/dop251/goja" + "github.com/pkg/errors" +) + +const ( + RoleVisitor string = "visitor" + RoleUser string = "user" + RoleSuperuser string = "superuser" + RoleAdmin string = "admin" + RoleSuperadmin string = "superadmin" +) + +func authModule(keySet jwk.Set) app.ServerModuleFactory { + return module.Extends( + auth.ModuleFactory( + auth.WithJWT(func() (jwk.Set, error) { + return keySet, nil + }), + ), + func(o *goja.Object) { + if err := o.Set("CLAIM_TENANT", "arcad_tenant"); err != nil { + panic(errors.New("could not set 'CLAIM_TENANT' property")) + } + + if err := o.Set("CLAIM_ENTRYPOINT", "arcad_entrypoint"); err != nil { + panic(errors.New("could not set 'CLAIM_ENTRYPOINT' property")) + } + + if err := o.Set("CLAIM_ROLE", "arcad_role"); err != nil { + panic(errors.New("could not set 'CLAIM_ROLE' property")) + } + + if err := o.Set("CLAIM_PREFERRED_USERNAME", "preferred_username"); err != nil { + panic(errors.New("could not set 'CLAIM_PREFERRED_USERNAME' property")) + } + + if err := o.Set("ROLE_VISITOR", RoleVisitor); err != nil { + panic(errors.New("could not set 'ROLE_VISITOR' property")) + } + + if err := o.Set("ROLE_USER", RoleUser); err != nil { + panic(errors.New("could not set 'ROLE_USER' property")) + } + + if err := o.Set("ROLE_SUPERUSER", RoleSuperuser); err != nil { + panic(errors.New("could not set 'ROLE_SUPERUSER' property")) + } + + if err := o.Set("ROLE_ADMIN", RoleAdmin); err != nil { + panic(errors.New("could not set 'ROLE_ADMIN' property")) + } + + if err := o.Set("ROLE_SUPERADMIN", RoleSuperadmin); err != nil { + panic(errors.New("could not set 'ROLE_SUPERADMIN' property")) + } + }, + ) +} diff --git a/internal/agent/controller/app/controller.go b/internal/agent/controller/app/controller.go index 72e26db..9247327 100644 --- a/internal/agent/controller/app/controller.go +++ b/internal/agent/controller/app/controller.go @@ -9,6 +9,7 @@ import ( "forge.cadoles.com/Cadoles/emissary/internal/agent" "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" + "forge.cadoles.com/arcad/edge/pkg/app" "forge.cadoles.com/arcad/edge/pkg/bundle" "github.com/mitchellh/hashstructure/v2" "github.com/pkg/errors" @@ -276,7 +277,21 @@ func (c *Controller) ensureAppBundle(ctx context.Context, appID string, spec spe return nil, "", errors.WithStack(err) } - return bdle, "", nil + manifest, err := app.LoadManifest(bdle) + if err != nil { + return nil, "", errors.WithStack(err) + } + + valid, err := validateManifest(manifest) + if err != nil { + return nil, "", errors.WithStack(err) + } + + if !valid { + return nil, "", errors.New("bundle's manifest is invalid") + } + + return bdle, spec.SHA256Sum, nil } func (c *Controller) downloadFile(url string, sha256sum string, dest string) error { diff --git a/internal/agent/controller/app/manifest.go b/internal/agent/controller/app/manifest.go new file mode 100644 index 0000000..c5cae4b --- /dev/null +++ b/internal/agent/controller/app/manifest.go @@ -0,0 +1,19 @@ +package app + +import ( + "forge.cadoles.com/arcad/edge/pkg/app" + "forge.cadoles.com/arcad/edge/pkg/app/metadata" + "github.com/pkg/errors" +) + +func validateManifest(manifest *app.Manifest) (bool, error) { + valid, err := manifest.Validate( + metadata.WithMinimumRoleValidator(RoleVisitor, RoleUser, RoleSuperuser, RoleAdmin, RoleSuperadmin), + metadata.WithNamedPathsValidator(metadata.NamedPathAdmin, metadata.NamedPathIcon), + ) + if err != nil { + return false, errors.WithStack(err) + } + + return valid, nil +}