diff --git a/accounts/pkg/command/server.go b/accounts/pkg/command/server.go index a64c23080e4..0378c39cd93 100644 --- a/accounts/pkg/command/server.go +++ b/accounts/pkg/command/server.go @@ -35,6 +35,15 @@ func Server(cfg *config.Config) *cli.Command { if !cfg.Supervised { return ParseConfig(ctx, cfg) } + if origins := ctx.StringSlice("cors-allowed-origins"); len(origins) != 0 { + cfg.HTTP.CORS.AllowedOrigins = origins + } + if methods := ctx.StringSlice("cors-allowed-methods"); len(methods) != 0 { + cfg.HTTP.CORS.AllowedMethods = methods + } + if headers := ctx.StringSlice("cors-allowed-headers"); len(headers) != 0 { + cfg.HTTP.CORS.AllowedOrigins = headers + } logger.Debug().Str("service", "accounts").Msg("ignoring config file parsing when running supervised") return nil }, diff --git a/accounts/pkg/config/config.go b/accounts/pkg/config/config.go index 0afc8e094c3..a98554f0e2f 100644 --- a/accounts/pkg/config/config.go +++ b/accounts/pkg/config/config.go @@ -26,12 +26,21 @@ type LDAPSchema struct { Groups string } +// CORS defines the available cors configuration. +type CORS struct { + AllowedOrigins []string + AllowedMethods []string + AllowedHeaders []string + AllowCredentials bool +} + // HTTP defines the available http configuration. type HTTP struct { Addr string Namespace string Root string CacheTTL int + CORS CORS } // GRPC defines the available grpc configuration. diff --git a/accounts/pkg/flagset/flagset.go b/accounts/pkg/flagset/flagset.go index 4c6224a9758..fc29ca6d1cc 100644 --- a/accounts/pkg/flagset/flagset.go +++ b/accounts/pkg/flagset/flagset.go @@ -109,6 +109,30 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"ACCOUNTS_CACHE_TTL"}, Destination: &cfg.HTTP.CacheTTL, }, + &cli.StringSliceFlag{ + Name: "cors-allowed-origins", + Value: cli.NewStringSlice("*"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"ACCOUNTS_CORS_ALLOW_ORIGINS", "OCIS_CORS_ALLOW_ORIGINS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-methods", + Value: cli.NewStringSlice("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"ACCOUNTS_CORS_ALLOW_METHODS", "OCIS_CORS_ALLOW_METHODS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-headers", + Value: cli.NewStringSlice("Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"ACCOUNTS_CORS_ALLOW_HEADERS", "OCIS_CORS_ALLOW_HEADERS"}, + }, + &cli.BoolFlag{ + Name: "cors-allow-credentials", + Value: flags.OverrideDefaultBool(cfg.HTTP.CORS.AllowCredentials, true), + Usage: "Allow credentials for CORS", + EnvVars: []string{"ACCOUNTS_CORS_ALLOW_CREDENTIALS", "OCIS_CORS_ALLOW_CREDENTIALS"}, + }, &cli.StringFlag{ Name: "grpc-namespace", Value: flags.OverrideDefaultString(cfg.GRPC.Namespace, "com.owncloud.api"), diff --git a/accounts/pkg/server/http/server.go b/accounts/pkg/server/http/server.go index dc2f5e8cf1a..21487a2d61d 100644 --- a/accounts/pkg/server/http/server.go +++ b/accounts/pkg/server/http/server.go @@ -6,6 +6,7 @@ import ( "github.com/owncloud/ocis/accounts/pkg/assets" "github.com/owncloud/ocis/accounts/pkg/proto/v0" "github.com/owncloud/ocis/ocis-pkg/account" + "github.com/owncloud/ocis/ocis-pkg/cors" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/owncloud/ocis/ocis-pkg/service/http" "github.com/owncloud/ocis/ocis-pkg/version" @@ -33,7 +34,13 @@ func Server(opts ...Option) http.Service { mux.Use(chimiddleware.RequestID) mux.Use(middleware.TraceContext) mux.Use(middleware.NoCache) - mux.Use(middleware.Cors) + mux.Use(middleware.Cors( + cors.Logger(options.Logger), + cors.AllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + cors.AllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + cors.AllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + cors.AllowCredentials(options.Config.HTTP.CORS.AllowCredentials), + )) mux.Use(middleware.Secure) mux.Use(middleware.ExtractAccountUUID( account.Logger(options.Logger), diff --git a/changelog/unreleased/http-header.md b/changelog/unreleased/http-header.md new file mode 100644 index 00000000000..83fb60debed --- /dev/null +++ b/changelog/unreleased/http-header.md @@ -0,0 +1,6 @@ +Enhancement: Review and correct http header + +Reviewed and corrected the necessary http headers. +Made CORS configurable. + +https://github.com/owncloud/ocis/pull/2666 diff --git a/go.mod b/go.mod index 010383f3cbf..6688a5d3d8e 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/disintegration/imaging v1.6.2 github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733 github.com/go-chi/chi/v5 v5.0.4 + github.com/go-chi/cors v1.2.0 github.com/go-chi/render v1.0.1 github.com/go-logr/logr v0.4.0 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 @@ -84,7 +85,6 @@ require ( github.com/RoaringBitmap/roaring v0.9.4 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/asim/go-micro/v3 v3.7.0 // indirect github.com/aws/aws-sdk-go v1.41.6 // indirect github.com/beevik/etree v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 2371db35da9..bec946fae0e 100644 --- a/go.sum +++ b/go.sum @@ -164,9 +164,8 @@ github.com/asim/go-micro/plugins/wrapper/monitoring/prometheus/v3 v3.0.0-2021101 github.com/asim/go-micro/plugins/wrapper/trace/opencensus/v3 v3.0.0-20211012122208-f63e46a7d1e9 h1:EAewDo27l8kidfQQo3yTrJ64pFy8sCOaJ6I5ZRHKFOg= github.com/asim/go-micro/plugins/wrapper/trace/opencensus/v3 v3.0.0-20211012122208-f63e46a7d1e9/go.mod h1:5mB3LtO4EUAWFz5PZaRxnC48OCSI005ySscXtRu37+M= github.com/asim/go-micro/v3 v3.5.1/go.mod h1:OJ5DnUQmoEVQTNbKRstR7/krtYJI+QaBe/XeN5MZkqE= +github.com/asim/go-micro/v3 v3.5.2-0.20210629124054-4929a7c16ecc h1:ikUleoYb/ZJDhh0sckGHxSplZfJILvfBzGM9KnGxp6o= github.com/asim/go-micro/v3 v3.5.2-0.20210629124054-4929a7c16ecc/go.mod h1:cNGIIYQcp0qy+taNYmrBdaIHeqMWHV5ZH/FfQzfOyE8= -github.com/asim/go-micro/v3 v3.7.0 h1:iPpKAkcftVyg8zcXWV4dTyrDkpJ5wst6g3ad7gEczqQ= -github.com/asim/go-micro/v3 v3.7.0/go.mod h1:GP48EHjG/7dw16ZL+lflu2S2SXSPKEVE2mPc45URs1E= github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= @@ -393,6 +392,8 @@ github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAU github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo= github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= +github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -816,6 +817,7 @@ github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 h1:Z/i1e+gTZrmcGeZy github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103/go.mod h1:o9YPB5aGP8ob35Vy6+vyq3P3bWe7NQWzf+JLiXCiMaE= github.com/mennanov/fieldmask-utils v0.5.0 h1:8em4akN0NM3hmmrg8VbvOPfdS4SSBdbFd53m9VtfOg0= github.com/mennanov/fieldmask-utils v0.5.0/go.mod h1:lah2lHczE2ff+7SqnNKpB+YzaO7M3h5iNO4LgPTJheM= +github.com/micro/cli/v2 v2.1.2 h1:43J1lChg/rZCC1rvdqZNFSQDrGT7qfMrtp6/ztpIkEM= github.com/micro/cli/v2 v2.1.2/go.mod h1:EguNh6DAoWKm9nmk+k/Rg0H3lQnDxqzu5x5srOtGtYg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= diff --git a/graph-explorer/pkg/server/http/server.go b/graph-explorer/pkg/server/http/server.go index f8025d93a82..33c85458e1d 100644 --- a/graph-explorer/pkg/server/http/server.go +++ b/graph-explorer/pkg/server/http/server.go @@ -30,7 +30,6 @@ func Server(opts ...Option) (http.Service, error) { chimiddleware.RealIP, chimiddleware.RequestID, middleware.NoCache, - middleware.Cors, middleware.Secure, middleware.Version( "graph-explorer", diff --git a/idp/pkg/server/http/server.go b/idp/pkg/server/http/server.go index dae7b49be17..cab4554b3da 100644 --- a/idp/pkg/server/http/server.go +++ b/idp/pkg/server/http/server.go @@ -57,7 +57,6 @@ func Server(opts ...Option) (http.Service, error) { chimiddleware.RequestID, middleware.TraceContext, middleware.NoCache, - middleware.Cors, middleware.Secure, middleware.Version( options.Config.Service.Name, diff --git a/ocis-pkg/cors/option.go b/ocis-pkg/cors/option.go new file mode 100644 index 00000000000..e53454191dd --- /dev/null +++ b/ocis-pkg/cors/option.go @@ -0,0 +1,68 @@ +package cors + +import ( + "github.com/owncloud/ocis/ocis-pkg/log" +) + +// Option defines a single option function. +type Option func(o *Options) + +// Options defines the available options for this package. +type Options struct { + // Logger to use for logging, must be set + Logger log.Logger + // AllowedOrigins represents the allowed CORS origins + AllowedOrigins []string + // AllowedMethods represents the allowed CORS methods + AllowedMethods []string + // AllowedHeaders represents the allowed CORS headers + AllowedHeaders []string + // AllowCredentials represents the AllowCredentials CORS option + AllowCredentials bool +} + +// newAccountOptions initializes the available default options. +func NewOptions(opts ...Option) Options { + opt := Options{} + + for _, o := range opts { + o(&opt) + } + + return opt +} + +// Logger provides a function to set the logger option. +func Logger(l log.Logger) Option { + return func(o *Options) { + o.Logger = l + } +} + +// AllowedOrigins provides a function to set the AllowedOrigins option. +func AllowedOrigins(origins []string) Option { + return func(o *Options) { + o.AllowedOrigins = origins + } +} + +// AllowedMethods provides a function to set the AllowedMethods option. +func AllowedMethods(methods []string) Option { + return func(o *Options) { + o.AllowedMethods = methods + } +} + +// AllowedHeaders provides a function to set the AllowedHeaders option. +func AllowedHeaders(headers []string) Option { + return func(o *Options) { + o.AllowedHeaders = headers + } +} + +// AlloweCredentials provides a function to set the AllowCredentials option. +func AllowCredentials(allow bool) Option { + return func(o *Options) { + o.AllowCredentials = allow + } +} diff --git a/ocis-pkg/middleware/header.go b/ocis-pkg/middleware/header.go index a9a33dac985..9c94e6a2e0a 100644 --- a/ocis-pkg/middleware/header.go +++ b/ocis-pkg/middleware/header.go @@ -2,7 +2,12 @@ package middleware import ( "net/http" + "strings" "time" + + "github.com/owncloud/ocis/ocis-pkg/cors" + + chicors "github.com/go-chi/cors" ) // NoCache writes required cache headers to all requests. @@ -17,18 +22,20 @@ func NoCache(next http.Handler) http.Handler { } // Cors writes required cors headers to all requests. -func Cors(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != "OPTIONS" { - next.ServeHTTP(w, r) - } else { - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "authorization, origin, content-type, accept, x-requested-with") - w.Header().Set("Allow", "HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS") - - w.WriteHeader(http.StatusOK) - } +func Cors(opts ...cors.Option) func(http.Handler) http.Handler { + options := cors.NewOptions(opts...) + logger := options.Logger + logger.Debug(). + Str("allowed_origins", strings.Join(options.AllowedOrigins, ", ")). + Str("allowed_methods", strings.Join(options.AllowedMethods, ", ")). + Str("allowed_headers", strings.Join(options.AllowedHeaders, ", ")). + Bool("allow_credentials", options.AllowCredentials). + Msg("setup cors middleware") + return chicors.Handler(chicors.Options{ + AllowedOrigins: options.AllowedOrigins, + AllowedMethods: options.AllowedMethods, + AllowedHeaders: options.AllowedHeaders, + AllowCredentials: options.AllowCredentials, }) } diff --git a/ocis-pkg/service/debug/option.go b/ocis-pkg/service/debug/option.go index 700df6f58fe..ef39d9ce42a 100644 --- a/ocis-pkg/service/debug/option.go +++ b/ocis-pkg/service/debug/option.go @@ -11,15 +11,19 @@ type Option func(o *Options) // Options defines the available options for this package. type Options struct { - Logger log.Logger - Name string - Version string - Address string - Token string - Pprof bool - Zpages bool - Health func(http.ResponseWriter, *http.Request) - Ready func(http.ResponseWriter, *http.Request) + Logger log.Logger + Name string + Version string + Address string + Token string + Pprof bool + Zpages bool + Health func(http.ResponseWriter, *http.Request) + Ready func(http.ResponseWriter, *http.Request) + CorsAllowedOrigins []string + CorsAllowedMethods []string + CorsAllowedHeaders []string + CorsAllowCredentials bool } // newOptions initializes the available default options. @@ -95,3 +99,31 @@ func Ready(r func(http.ResponseWriter, *http.Request)) Option { o.Ready = r } } + +// CorsAllowedOrigins provides a function to set the CorsAllowedOrigin option. +func CorsAllowedOrigins(origins []string) Option { + return func(o *Options) { + o.CorsAllowedOrigins = origins + } +} + +// CorsAllowedMethods provides a function to set the CorsAllowedMethods option. +func CorsAllowedMethods(methods []string) Option { + return func(o *Options) { + o.CorsAllowedMethods = methods + } +} + +// CorsAllowedHeaders provides a function to set the CorsAllowedHeaders option. +func CorsAllowedHeaders(headers []string) Option { + return func(o *Options) { + o.CorsAllowedHeaders = headers + } +} + +// CorsAllowCredentials provides a function to set the CorsAllowAllowCredential option. +func CorsAllowCredentials(allow bool) Option { + return func(o *Options) { + o.CorsAllowCredentials = allow + } +} diff --git a/ocis-pkg/service/debug/service.go b/ocis-pkg/service/debug/service.go index f4fabc7a083..a89ea0c53cc 100644 --- a/ocis-pkg/service/debug/service.go +++ b/ocis-pkg/service/debug/service.go @@ -6,6 +6,7 @@ import ( chimiddleware "github.com/go-chi/chi/v5/middleware" "github.com/justinas/alice" + "github.com/owncloud/ocis/ocis-pkg/cors" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/prometheus/client_golang/prometheus/promhttp" "go.opencensus.io/zpages" @@ -51,7 +52,12 @@ func NewService(opts ...Option) *http.Server { chimiddleware.RealIP, chimiddleware.RequestID, middleware.NoCache, - middleware.Cors, + middleware.Cors( + cors.AllowedOrigins(dopts.CorsAllowedOrigins), + cors.AllowedMethods(dopts.CorsAllowedMethods), + cors.AllowedHeaders(dopts.CorsAllowedHeaders), + cors.AllowCredentials(dopts.CorsAllowCredentials), + ), middleware.Secure, middleware.Version( dopts.Name, diff --git a/ocs/pkg/command/server.go b/ocs/pkg/command/server.go index 344acf49ec2..0e66aa9aa41 100644 --- a/ocs/pkg/command/server.go +++ b/ocs/pkg/command/server.go @@ -32,6 +32,15 @@ func Server(cfg *config.Config) *cli.Command { if !cfg.Supervised { return ParseConfig(ctx, cfg) } + if origins := ctx.StringSlice("cors-allowed-origins"); len(origins) != 0 { + cfg.HTTP.CORS.AllowedOrigins = origins + } + if methods := ctx.StringSlice("cors-allowed-methods"); len(methods) != 0 { + cfg.HTTP.CORS.AllowedMethods = methods + } + if headers := ctx.StringSlice("cors-allowed-headers"); len(headers) != 0 { + cfg.HTTP.CORS.AllowedOrigins = headers + } logger.Debug().Str("service", "ocs").Msg("ignoring config file parsing when running supervised") return nil }, diff --git a/ocs/pkg/config/config.go b/ocs/pkg/config/config.go index bb270ad5f94..6ee0377a44d 100644 --- a/ocs/pkg/config/config.go +++ b/ocs/pkg/config/config.go @@ -18,10 +18,19 @@ type Debug struct { Zpages bool } +// CORS defines the available cors configuration. +type CORS struct { + AllowedOrigins []string + AllowedMethods []string + AllowedHeaders []string + AllowCredentials bool +} + // HTTP defines the available http configuration. type HTTP struct { Addr string Root string + CORS CORS } // Service defines the available service configuration. diff --git a/ocs/pkg/flagset/flagset.go b/ocs/pkg/flagset/flagset.go index 9420df3161c..378d07eafc3 100644 --- a/ocs/pkg/flagset/flagset.go +++ b/ocs/pkg/flagset/flagset.go @@ -128,6 +128,30 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"OCS_NAMESPACE"}, Destination: &cfg.Service.Namespace, }, + &cli.StringSliceFlag{ + Name: "cors-allowed-origins", + Value: cli.NewStringSlice("*"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"OCS_CORS_ALLOW_ORIGINS", "OCIS_CORS_ALLOW_ORIGINS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-methods", + Value: cli.NewStringSlice("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"OCS_CORS_ALLOW_METHODS", "OCIS_CORS_ALLOW_METHODS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-headers", + Value: cli.NewStringSlice("Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"OCS_CORS_ALLOW_HEADERS", "OCIS_CORS_ALLOW_HEADERS"}, + }, + &cli.BoolFlag{ + Name: "cors-allow-credentials", + Value: flags.OverrideDefaultBool(cfg.HTTP.CORS.AllowCredentials, true), + Usage: "Allow credentials for CORS", + EnvVars: []string{"OCS_CORS_ALLOW_CREDENTIALS", "OCIS_CORS_ALLOW_CREDENTIALS"}, + }, &cli.StringFlag{ Name: "name", Value: flags.OverrideDefaultString(cfg.Service.Name, "ocs"), diff --git a/ocs/pkg/server/debug/server.go b/ocs/pkg/server/debug/server.go index bd1edb68c31..7c704840e0b 100644 --- a/ocs/pkg/server/debug/server.go +++ b/ocs/pkg/server/debug/server.go @@ -22,6 +22,10 @@ func Server(opts ...Option) (*http.Server, error) { debug.Zpages(options.Config.Debug.Zpages), debug.Health(health(options.Config)), debug.Ready(ready(options.Config)), + debug.CorsAllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + debug.CorsAllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + debug.CorsAllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + debug.CorsAllowCredentials(options.Config.HTTP.CORS.AllowCredentials), ), nil } diff --git a/ocs/pkg/server/http/server.go b/ocs/pkg/server/http/server.go index 34eea8674b9..4df5fbbddb4 100644 --- a/ocs/pkg/server/http/server.go +++ b/ocs/pkg/server/http/server.go @@ -2,6 +2,7 @@ package http import ( chimiddleware "github.com/go-chi/chi/v5/middleware" + "github.com/owncloud/ocis/ocis-pkg/cors" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/owncloud/ocis/ocis-pkg/service/http" ocsmw "github.com/owncloud/ocis/ocs/pkg/middleware" @@ -30,7 +31,13 @@ func Server(opts ...Option) (http.Service, error) { chimiddleware.RealIP, chimiddleware.RequestID, middleware.NoCache, - middleware.Cors, + middleware.Cors( + cors.Logger(options.Logger), + cors.AllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + cors.AllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + cors.AllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + cors.AllowCredentials(options.Config.HTTP.CORS.AllowCredentials), + ), middleware.Secure, middleware.Version(options.Config.Service.Name, options.Config.Service.Version), middleware.Logger(options.Logger), diff --git a/settings/pkg/command/server.go b/settings/pkg/command/server.go index 3609762b3eb..630930a8575 100644 --- a/settings/pkg/command/server.go +++ b/settings/pkg/command/server.go @@ -33,6 +33,15 @@ func Server(cfg *config.Config) *cli.Command { if !cfg.Supervised { return ParseConfig(ctx, cfg) } + if origins := ctx.StringSlice("cors-allowed-origins"); len(origins) != 0 { + cfg.HTTP.CORS.AllowedOrigins = origins + } + if methods := ctx.StringSlice("cors-allowed-methods"); len(methods) != 0 { + cfg.HTTP.CORS.AllowedMethods = methods + } + if headers := ctx.StringSlice("cors-allowed-headers"); len(headers) != 0 { + cfg.HTTP.CORS.AllowedOrigins = headers + } logger.Debug().Str("service", "settings").Msg("ignoring config file parsing when running supervised") return nil }, diff --git a/settings/pkg/config/config.go b/settings/pkg/config/config.go index f137a9ac471..71053c421f5 100644 --- a/settings/pkg/config/config.go +++ b/settings/pkg/config/config.go @@ -18,12 +18,21 @@ type Debug struct { Zpages bool } +// CORS defines the available cors configuration. +type CORS struct { + AllowedOrigins []string + AllowedMethods []string + AllowedHeaders []string + AllowCredentials bool +} + // HTTP defines the available http configuration. type HTTP struct { Addr string Namespace string Root string CacheTTL int + CORS CORS } // GRPC defines the available grpc configuration. diff --git a/settings/pkg/flagset/flagset.go b/settings/pkg/flagset/flagset.go index f4c7c4cff9a..585cfcecfa0 100644 --- a/settings/pkg/flagset/flagset.go +++ b/settings/pkg/flagset/flagset.go @@ -144,6 +144,30 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"SETTINGS_CACHE_TTL"}, Destination: &cfg.HTTP.CacheTTL, }, + &cli.StringSliceFlag{ + Name: "cors-allowed-origins", + Value: cli.NewStringSlice("*"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"SETTINGS_CORS_ALLOW_ORIGINS", "OCIS_CORS_ALLOW_ORIGINS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-methods", + Value: cli.NewStringSlice("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"SETTINGS_CORS_ALLOW_METHODS", "OCIS_CORS_ALLOW_METHODS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-headers", + Value: cli.NewStringSlice("Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"SETTINGS_CORS_ALLOW_HEADERS", "OCIS_CORS_ALLOW_HEADERS"}, + }, + &cli.BoolFlag{ + Name: "cors-allow-credentials", + Value: flags.OverrideDefaultBool(cfg.HTTP.CORS.AllowCredentials, true), + Usage: "Allow credentials for CORS", + EnvVars: []string{"SETTINGS_CORS_ALLOW_CREDENTIALS", "OCIS_CORS_ALLOW_CREDENTIALS"}, + }, &cli.StringFlag{ Name: "grpc-addr", Value: flags.OverrideDefaultString(cfg.GRPC.Addr, "127.0.0.1:9191"), diff --git a/settings/pkg/server/debug/server.go b/settings/pkg/server/debug/server.go index e2c16d67b71..36bf1411eaa 100644 --- a/settings/pkg/server/debug/server.go +++ b/settings/pkg/server/debug/server.go @@ -23,6 +23,10 @@ func Server(opts ...Option) (*http.Server, error) { debug.Zpages(options.Config.Debug.Zpages), debug.Health(health(options.Config)), debug.Ready(ready(options.Config)), + debug.CorsAllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + debug.CorsAllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + debug.CorsAllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + debug.CorsAllowCredentials(options.Config.HTTP.CORS.AllowCredentials), ), nil } diff --git a/settings/pkg/server/http/server.go b/settings/pkg/server/http/server.go index 238d3a2c7f4..cb63ac5ec63 100644 --- a/settings/pkg/server/http/server.go +++ b/settings/pkg/server/http/server.go @@ -4,6 +4,7 @@ import ( "github.com/go-chi/chi/v5" chimiddleware "github.com/go-chi/chi/v5/middleware" "github.com/owncloud/ocis/ocis-pkg/account" + "github.com/owncloud/ocis/ocis-pkg/cors" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/owncloud/ocis/ocis-pkg/service/http" "github.com/owncloud/ocis/ocis-pkg/version" @@ -40,7 +41,13 @@ func Server(opts ...Option) http.Service { mux.Use(chimiddleware.RealIP) mux.Use(chimiddleware.RequestID) mux.Use(middleware.NoCache) - mux.Use(middleware.Cors) + mux.Use(middleware.Cors( + cors.Logger(options.Logger), + cors.AllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + cors.AllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + cors.AllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + cors.AllowCredentials(options.Config.HTTP.CORS.AllowCredentials), + )) mux.Use(middleware.Secure) mux.Use(middleware.ExtractAccountUUID( account.Logger(options.Logger), diff --git a/web/pkg/server/http/server.go b/web/pkg/server/http/server.go index 25a9e5db72e..b33019e83d3 100644 --- a/web/pkg/server/http/server.go +++ b/web/pkg/server/http/server.go @@ -31,7 +31,6 @@ func Server(opts ...Option) (http.Service, error) { chimiddleware.RealIP, chimiddleware.RequestID, middleware.NoCache, - middleware.Cors, middleware.Secure, webmid.SilentRefresh, middleware.Version( diff --git a/webdav/pkg/command/server.go b/webdav/pkg/command/server.go index 3541ad4a53b..47a50909934 100644 --- a/webdav/pkg/command/server.go +++ b/webdav/pkg/command/server.go @@ -30,6 +30,15 @@ func Server(cfg *config.Config) *cli.Command { if !cfg.Supervised { return ParseConfig(ctx, cfg) } + if origins := ctx.StringSlice("cors-allowed-origins"); len(origins) != 0 { + cfg.HTTP.CORS.AllowedOrigins = origins + } + if methods := ctx.StringSlice("cors-allowed-methods"); len(methods) != 0 { + cfg.HTTP.CORS.AllowedMethods = methods + } + if headers := ctx.StringSlice("cors-allowed-headers"); len(headers) != 0 { + cfg.HTTP.CORS.AllowedOrigins = headers + } logger.Debug().Str("service", "webdav").Msg("ignoring config file parsing when running supervised") return nil }, diff --git a/webdav/pkg/config/config.go b/webdav/pkg/config/config.go index 16fc4618b83..dfd4f46c6f0 100644 --- a/webdav/pkg/config/config.go +++ b/webdav/pkg/config/config.go @@ -18,10 +18,19 @@ type Debug struct { Zpages bool } +// CORS defines the available cors configuration. +type CORS struct { + AllowedOrigins []string + AllowedMethods []string + AllowedHeaders []string + AllowCredentials bool +} + // HTTP defines the available http configuration. type HTTP struct { Addr string Root string + CORS CORS } // Service defines the available service configuration. @@ -42,13 +51,13 @@ type Tracing struct { // Config combines all available configuration parts. type Config struct { - File string - Log Log - Debug Debug - HTTP HTTP - Tracing Tracing - Service Service - OcisPublicURL string + File string + Log Log + Debug Debug + HTTP HTTP + Tracing Tracing + Service Service + OcisPublicURL string WebdavNamespace string Context context.Context diff --git a/webdav/pkg/flagset/flagset.go b/webdav/pkg/flagset/flagset.go index 2441d57bd3c..7df00873cd1 100644 --- a/webdav/pkg/flagset/flagset.go +++ b/webdav/pkg/flagset/flagset.go @@ -127,6 +127,30 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"WEBDAV_HTTP_NAMESPACE"}, Destination: &cfg.Service.Namespace, }, + &cli.StringSliceFlag{ + Name: "cors-allowed-origins", + Value: cli.NewStringSlice("*"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"WEBDAV_CORS_ALLOW_ORIGINS", "OCIS_CORS_ALLOW_ORIGINS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-methods", + Value: cli.NewStringSlice("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"WEBDAV_CORS_ALLOW_METHODS", "OCIS_CORS_ALLOW_METHODS"}, + }, + &cli.StringSliceFlag{ + Name: "cors-allowed-headers", + Value: cli.NewStringSlice("Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"), + Usage: "Set the allowed CORS origins", + EnvVars: []string{"WEBDAV_CORS_ALLOW_HEADERS", "OCIS_CORS_ALLOW_HEADERS"}, + }, + &cli.BoolFlag{ + Name: "cors-allow-credentials", + Value: flags.OverrideDefaultBool(cfg.HTTP.CORS.AllowCredentials, true), + Usage: "Allow credentials for CORS", + EnvVars: []string{"WEBDAV_CORS_ALLOW_CREDENTIALS", "OCIS_CORS_ALLOW_CREDENTIALS"}, + }, &cli.StringFlag{ Name: "service-name", Value: flags.OverrideDefaultString(cfg.Service.Name, "webdav"), diff --git a/webdav/pkg/server/debug/server.go b/webdav/pkg/server/debug/server.go index bd1eca5812d..f79a0538f81 100644 --- a/webdav/pkg/server/debug/server.go +++ b/webdav/pkg/server/debug/server.go @@ -22,6 +22,10 @@ func Server(opts ...Option) (*http.Server, error) { debug.Zpages(options.Config.Debug.Zpages), debug.Health(health(options.Config)), debug.Ready(ready(options.Config)), + debug.CorsAllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + debug.CorsAllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + debug.CorsAllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + debug.CorsAllowCredentials(options.Config.HTTP.CORS.AllowCredentials), ), nil } diff --git a/webdav/pkg/server/http/server.go b/webdav/pkg/server/http/server.go index 11eeeeae367..1b183af5ed0 100644 --- a/webdav/pkg/server/http/server.go +++ b/webdav/pkg/server/http/server.go @@ -2,6 +2,7 @@ package http import ( chimiddleware "github.com/go-chi/chi/v5/middleware" + "github.com/owncloud/ocis/ocis-pkg/cors" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/owncloud/ocis/ocis-pkg/service/http" svc "github.com/owncloud/ocis/webdav/pkg/service/v0" @@ -29,7 +30,13 @@ func Server(opts ...Option) (http.Service, error) { chimiddleware.RealIP, chimiddleware.RequestID, middleware.NoCache, - middleware.Cors, + middleware.Cors( + cors.Logger(options.Logger), + cors.AllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins), + cors.AllowedMethods(options.Config.HTTP.CORS.AllowedMethods), + cors.AllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders), + cors.AllowCredentials(options.Config.HTTP.CORS.AllowCredentials), + ), middleware.Secure, middleware.Version( options.Config.Service.Name,