diff --git a/cmd/wonderwall/main.go b/cmd/wonderwall/main.go index 0f2f5a6..aca194b 100644 --- a/cmd/wonderwall/main.go +++ b/cmd/wonderwall/main.go @@ -87,7 +87,9 @@ func run() error { return fmt.Errorf("initializing routing handler: %w", err) } - r := router.New(handler) + prefixes := config.ParseIngresses(cfg.Ingresses) + + r := router.New(handler, prefixes) return http.ListenAndServe(cfg.BindAddress, r) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 4ee5ca0..933b4d4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -19,6 +19,7 @@ type Config struct { LogFormat string `json:"log-format"` LogLevel string `json:"log-level"` Redis string `json:"redis"` + Ingresses []string `json:"ingresses"` } type IDPorten struct { @@ -41,6 +42,7 @@ const ( LogLevel = "log-level" EncryptionKey = "encryption-key" Redis = "redis" + Ingresses = "ingresses" IDPortenClientID = "idporten.client-id" IDPortenClientJWK = "idporten.client-jwk" IDPortenRedirectURI = "idporten.redirect-uri" @@ -74,6 +76,7 @@ func Initialize() *Config { flag.String(IDPortenPostLogoutRedirectURI, "https://nav.no", "URI for redirecting the user after successful logout at IDPorten.") flag.StringSlice(IDPortenScopes, []string{token.ScopeOpenID}, "List of scopes that should be used during the Auth Code flow.") flag.Duration(IDPortenSessionMaxLifetime, time.Hour, "Max lifetime for user sessions.") + flag.StringSlice(Ingresses, []string{""}, "Ingresses used to access the main application.") return &Config{} } diff --git a/pkg/config/ingress.go b/pkg/config/ingress.go new file mode 100644 index 0000000..a0767db --- /dev/null +++ b/pkg/config/ingress.go @@ -0,0 +1,28 @@ +package config + +import ( + "net/url" + "strings" +) + +func ParseIngresses(ingresses []string) []string { + prefixMap := make(map[string]interface{}) + + for _, ingress := range ingresses { + ingressURL, err := url.Parse(ingress) + if err != nil { + continue + } + path := ingressURL.Path + path = strings.TrimRight(path, "/") + + prefixMap[path] = new(interface{}) + } + + prefixes := make([]string, 0) + for prefix := range prefixMap { + prefixes = append(prefixes, prefix) + } + + return prefixes +} diff --git a/pkg/config/ingress_test.go b/pkg/config/ingress_test.go new file mode 100644 index 0000000..96ee012 --- /dev/null +++ b/pkg/config/ingress_test.go @@ -0,0 +1,26 @@ +package config_test + +import ( + "sort" + "testing" + + "github.com/nais/wonderwall/pkg/config" + "github.com/stretchr/testify/assert" +) + +func TestParseIngresses(t *testing.T) { + ingresses := []string{"https://tjenester.nav.no/sykepenger/", "https://sykepenger.nav.no/", "https://sykepenger-test.nav.no"} + expected := []string{"", "/sykepenger"} + + prefixes := config.ParseIngresses(ingresses) + sort.Strings(prefixes) + assert.Equal(t, expected, prefixes) +} + +func TestParseEmptyIngress(t *testing.T) { + ingresses := []string{""} + expected := []string{""} + + prefixes := config.ParseIngresses(ingresses) + assert.Equal(t, expected, prefixes) +} diff --git a/pkg/router/router.go b/pkg/router/router.go index d0bf9a7..9951925 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -377,15 +377,17 @@ func (h *Handler) FrontChannelLogout(w http.ResponseWriter, r *http.Request) { } } -func New(handler *Handler) chi.Router { +func New(handler *Handler, prefixes []string) chi.Router { r := chi.NewRouter() - r.Route("/oauth2", func(r chi.Router) { - r.With(middleware.NoCache) - r.Get("/login", handler.Login) - r.Get("/callback", handler.Callback) - r.Get("/logout", handler.Logout) - r.Get("/logout/frontchannel", handler.FrontChannelLogout) - }) + for _, prefix := range prefixes { + r.Route(prefix+"/oauth2", func(r chi.Router) { + r.With(middleware.NoCache) + r.Get("/login", handler.Login) + r.Get("/callback", handler.Callback) + r.Get("/logout", handler.Logout) + r.Get("/logout/frontchannel", handler.FrontChannelLogout) + }) + } r.HandleFunc("/*", handler.Default) return r } diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index a9b9130..528dbea 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -96,7 +96,8 @@ func TestHandler_Login(t *testing.T) { cfg := defaultConfig() h := handler(cfg) - r := router.New(h) + prefixes := config.ParseIngresses([]string{""}) + r := router.New(h, prefixes) server := httptest.NewServer(r) client := server.Client() @@ -150,7 +151,8 @@ func TestHandler_Callback_and_Logout(t *testing.T) { cfg.WellKnown.EndSessionEndpoint = idpserver.URL + "/endsession" h := handler(cfg) - r := router.New(h) + prefixes := config.ParseIngresses([]string{""}) + r := router.New(h, prefixes) server := httptest.NewServer(r) h.Config.RedirectURI = server.URL + "/oauth2/callback" @@ -243,7 +245,8 @@ func TestHandler_FrontChannelLogout(t *testing.T) { cfg.WellKnown.TokenEndpoint = idpserver.URL + "/token" h := handler(cfg) - r := router.New(h) + prefixes := config.ParseIngresses([]string{""}) + r := router.New(h, prefixes) server := httptest.NewServer(r) h.Config.RedirectURI = server.URL + "/oauth2/callback"