From 4ea6f99c3e9c081807883a142077865c2edcd8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 15 Apr 2022 14:26:52 +0200 Subject: [PATCH] Manager: dynamically generate allowed CORS origins Remove the hard-coded list of allowed CORS origins, and build it dynamically from the list of "own URLs", i.e. the URLs at which the Manager expects to be available. This list of "own URLs" is constructed from the available network interfaces. --- cmd/flamenco-manager/main.go | 45 +++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/cmd/flamenco-manager/main.go b/cmd/flamenco-manager/main.go index 1cb02098..618441a9 100644 --- a/cmd/flamenco-manager/main.go +++ b/cmd/flamenco-manager/main.go @@ -6,11 +6,14 @@ import ( "context" "errors" "flag" + "fmt" "net" "net/http" + "net/url" "os" "os/signal" "runtime" + "strings" "sync" "syscall" "time" @@ -43,6 +46,8 @@ var cliArgs struct { writeConfig bool } +const developmentWebInterfacePort = 8081 + func main() { output := zerolog.ConsoleWriter{Out: colorable.NewColorableStdout(), TimeFormat: time.RFC3339} log.Logger = log.Output(output) @@ -83,7 +88,12 @@ func main() { _, port, _ := net.SplitHostPort(listen) log.Info().Str("port", port).Msg("listening") - ssdp := makeAutoDiscoverable("http", listen) + urls, err := own_url.AvailableURLs("http", listen) + if err != nil { + log.Fatal().Err(err).Msg("unable to figure out my own URL") + } + + ssdp := makeAutoDiscoverable(urls) // Construct the services. persist := openDB(*configService) @@ -96,7 +106,7 @@ func main() { webUpdater := webupdates.New() flamenco := buildFlamencoAPI(configService, persist, webUpdater) - e := buildWebService(flamenco, persist, ssdp, webUpdater) + e := buildWebService(flamenco, persist, ssdp, webUpdater, urls) installSignalHandler(mainCtxCancel) @@ -150,6 +160,7 @@ func buildWebService( persist api_impl.PersistenceService, ssdp *upnp_ssdp.Server, webUpdater *webupdates.BiDirComms, + ownURLs []url.URL, ) *echo.Echo { e := echo.New() e.HideBanner = true @@ -175,8 +186,7 @@ func buildWebService( // e.Use(middleware.Gzip()) e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - // Just some hard-coded URLs for now, just to get some tests going. - AllowOrigins: []string{"http://localhost:8080", "http://localhost:8081", "http://10.161.30.150:8081"}, + AllowOrigins: corsOrigins(ownURLs), // List taken from https://www.bacancytechnology.com/blog/real-time-chat-application-using-socketio-golang-vuejs/ AllowHeaders: []string{ @@ -346,13 +356,7 @@ func installSignalHandler(cancelFunc context.CancelFunc) { }() } -func makeAutoDiscoverable(scheme, listen string) *upnp_ssdp.Server { - urls, err := own_url.AvailableURLs("http", listen) - if err != nil { - log.Error().Err(err).Msg("unable to figure out my own URL") - return nil - } - +func makeAutoDiscoverable(urls []url.URL) *upnp_ssdp.Server { ssdp, err := upnp_ssdp.NewServer(log.Logger) if err != nil { log.Error().Err(err).Msg("error creating UPnP/SSDP server") @@ -362,3 +366,22 @@ func makeAutoDiscoverable(scheme, listen string) *upnp_ssdp.Server { ssdp.AddAdvertisementURLs(urls) return ssdp } + +// corsOrigins strips everything from the URL that follows the hostname:port, so +// that it's suitable for checking Origin headers of CORS OPTIONS requests. +func corsOrigins(urls []url.URL) []string { + origins := make([]string, len(urls)) + + // TODO: find a way to allow CORS requests during development, but not when + // running in production. + + for i, url := range urls { + // Allow the `yarn run dev` webserver do cross-origin requests to this Manager. + url.Path = "" + url.Fragment = "" + url.Host = fmt.Sprintf("%s:%d", url.Hostname(), developmentWebInterfacePort) + origins[i] = url.String() + } + log.Debug().Str("origins", strings.Join(origins, " ")).Msg("accepted CORS origins") + return origins +}