diff --git a/internal/agent/controller/app/app_handler.go b/internal/agent/controller/app/app_handler.go index 61b8dc5..7b656a9 100644 --- a/internal/agent/controller/app/app_handler.go +++ b/internal/agent/controller/app/app_handler.go @@ -23,6 +23,7 @@ import ( netModule "forge.cadoles.com/arcad/edge/pkg/module/net" "forge.cadoles.com/arcad/edge/pkg/storage/sqlite" "github.com/Masterminds/sprig/v3" + "github.com/go-chi/chi/v5" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" @@ -47,12 +48,26 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs return nil, errors.Wrap(err, "could not retrieve auth key set") } + mounts := make([]func(r chi.Router), 0) + + authMount, err := getAuthMount(specs.Config.Auth, keySet) + if err != nil { + return nil, errors.WithStack(err) + } + + if authMount != nil { + mounts = append(mounts, authMount) + } + + mounts = append(mounts, appModule.Mount(c.appRepository)) + bus := memory.NewBus() modules := c.getAppModules(bus, db, specs, keySet) options := []edgeHTTP.HandlerOptionFunc{ edgeHTTP.WithBus(bus), edgeHTTP.WithServerModules(modules...), + edgeHTTP.WithHTTPMounts(mounts...), } return options, nil @@ -244,7 +259,7 @@ func (c *Controller) getAppModules(bus bus.Bus, db *sql.DB, spec *appSpec.Spec, module.RPCModuleFactory(bus), module.StoreModuleFactory(ds), blob.ModuleFactory(bus, bs), - authModule(keySet), + authModuleFactory(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 index 3891f98..855bebf 100644 --- a/internal/agent/controller/app/auth_module.go +++ b/internal/agent/controller/app/auth_module.go @@ -1,11 +1,17 @@ package app import ( + "time" + + "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" "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" + authModule "forge.cadoles.com/arcad/edge/pkg/module/auth" + authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http" "github.com/dop251/goja" + "github.com/lestrrat-go/jwx/v2/jwa" "github.com/pkg/errors" ) @@ -17,30 +23,14 @@ const ( RoleSuperadmin string = "superadmin" ) -func authModule(keySet jwk.Set) app.ServerModuleFactory { +func authModuleFactory(keySet jwk.Set) app.ServerModuleFactory { return module.Extends( - auth.ModuleFactory( - auth.WithJWT(func() (jwk.Set, error) { + authModule.ModuleFactory( + authModule.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")) } @@ -63,3 +53,41 @@ func authModule(keySet jwk.Set) app.ServerModuleFactory { }, ) } + +func getAuthMount(auth *spec.Auth, keySet jwk.Set) (auth.MountFunc, error) { + switch { + case auth.Local != nil: + var rawKey any = auth.Local.Key + if strKey, ok := rawKey.(string); ok { + rawKey = []byte(strKey) + } + + key, err := jwk.FromRaw(rawKey) + if err != nil { + return nil, errors.WithStack(err) + } + + cookieDuration := defaultCookieDuration + if auth.Local.CookieDuration != "" { + cookieDuration, err = time.ParseDuration(auth.Local.CookieDuration) + if err != nil { + return nil, errors.WithStack(err) + } + } + + return authModule.Mount( + authHTTP.NewLocalHandler( + jwa.HS256, key, + authHTTP.WithRoutePrefix("/auth"), + authHTTP.WithAccounts(auth.Local.Accounts...), + authHTTP.WithCookieOptions(getCookieDomain, cookieDuration), + ), + authModule.WithJWT(func() (jwk.Set, error) { + return keySet, nil + }), + ), nil + + default: + return nil, nil + } +} diff --git a/internal/agent/controller/app/server.go b/internal/agent/controller/app/server.go index c9f0492..44c9aa7 100644 --- a/internal/agent/controller/app/server.go +++ b/internal/agent/controller/app/server.go @@ -12,14 +12,11 @@ import ( appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" "forge.cadoles.com/Cadoles/emissary/internal/proxy/wildcard" edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http" - authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http" "gitlab.com/wpetit/goweb/logger" "forge.cadoles.com/arcad/edge/pkg/bundle" "github.com/go-chi/chi/middleware" "github.com/go-chi/chi/v5" - "github.com/lestrrat-go/jwx/v2/jwa" - "github.com/lestrrat-go/jwx/v2/jwk" "github.com/pkg/errors" _ "forge.cadoles.com/Cadoles/emissary/internal/imports/passwd" @@ -62,12 +59,6 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) { s.config.UnexpectedHostRedirect.AcceptedHostPatterns..., )) } - - if s.config.Auth != nil { - if err := s.configureAuth(router, s.config.Auth); err != nil { - return errors.WithStack(err) - } - } } router.Handle("/*", handler) @@ -136,38 +127,6 @@ func (s *Server) Stop() error { return nil } -func (s *Server) configureAuth(router chi.Router, auth *spec.Auth) error { - switch { - case auth.Local != nil: - var rawKey any = auth.Local.Key - if strKey, ok := rawKey.(string); ok { - rawKey = []byte(strKey) - } - - key, err := jwk.FromRaw(rawKey) - if err != nil { - return errors.WithStack(err) - } - - cookieDuration := defaultCookieDuration - if auth.Local.CookieDuration != "" { - cookieDuration, err = time.ParseDuration(auth.Local.CookieDuration) - if err != nil { - return errors.WithStack(err) - } - } - - router.Handle("/auth/*", authHTTP.NewLocalHandler( - jwa.HS256, key, - authHTTP.WithRoutePrefix("/auth"), - authHTTP.WithAccounts(auth.Local.Accounts...), - authHTTP.WithCookieOptions(getCookieDomain, cookieDuration), - )) - } - - return nil -} - func NewServer(bundle bundle.Bundle, config *spec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server { return &Server{ bundle: bundle, diff --git a/misc/spec-samples/app.emissary.cadoles.com.json b/misc/spec-samples/app.emissary.cadoles.com.json index dab1234..05d6ca5 100644 --- a/misc/spec-samples/app.emissary.cadoles.com.json +++ b/misc/spec-samples/app.emissary.cadoles.com.json @@ -1,28 +1,16 @@ { "apps": { - "edge.portal": { - "url": "https://emissary.cadol.es/files/apps/edge.portal_v2023.4.9-41c100d.zip", - "sha256sum": "b73a6741654f3e24281e354b3b506b109dac6ada8a9698452f52b03a53299a7d", - "address": ":8082", - "format": "zip" - }, "app.arcad.edge.hextris": { - "url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.11-81fb4c4.zip", - "sha256sum": "6d70f65971b3dd288da32d8d004ab8fbca030398b5c12e3c052ef98c53a6b81a", + "url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.20-2bbbe94.zip", + "sha256sum": "67942ef4b623c46308c3f640b534bd4cb6b1d6021a422e40b62ab97658ba4586", "address": ":8083", "format": "zip" }, "edge.sdk.client.test": { - "url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_v2023.4.11-f5283b8.zip", - "sha256sum": "785d9f8d427900e1bb27ab85a33e8b1cbd1b6a1f8b2eab6366dc215a69655ade", + "url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_v2023.4.20-20c4189.zip", + "sha256sum": "1edeb4aa75c1675db49cf27367b1537234a04526848ea6657931ca63f26e5dae", "address": ":8084", "format": "zip" - }, - "arcad.diffusion": { - "url": "https://emissary.cadol.es/files/apps/arcad.diffusion_v2023.4.9-81046a2.zip", - "sha256sum": "b8770adfaaf60e6d3e7776e0a090e6e7a0b31f3f9425b91168b42144d0346513", - "address": ":8085", - "format": "zip" } }, "config": { @@ -48,11 +36,44 @@ "algo": "plain", "password": "admin", "claims": { - "arcad_role": "admin", - "arcad_tenant": "x86", + "edge_role": "admin", + "edge_tenant": "emissary-dev", "preferred_username": "Admin", "sub": "admin" } + }, + { + "username": "superadmin", + "algo": "plain", + "password": "superadmin", + "claims": { + "edge_role": "superadmin", + "edge_tenant": "emissary-dev", + "preferred_username": "SuperAdmin", + "sub": "superadmin" + } + }, + { + "username": "user", + "algo": "plain", + "password": "user", + "claims": { + "edge_role": "user", + "edge_tenant": "emissary-dev", + "preferred_username": "User", + "sub": "user" + } + }, + { + "username": "superuser", + "algo": "plain", + "password": "superuser", + "claims": { + "edge_role": "superuser", + "edge_tenant": "emissary-dev", + "preferred_username": "SuperUser", + "sub": "superuser" + } } ] }