Skip to content

Commit

Permalink
*: Allow to disable automatically setting CORS headers
Browse files Browse the repository at this point in the history
Signed-off-by: Frederic Branczyk <fbranczyk@gmail.com>
  • Loading branch information
brancz committed Mar 11, 2021
1 parent cb7cf1e commit 71cb188
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ We use _breaking :warning:_ to mark changes that are not backward compatible (re

### Added
- [#3903](https://github.com/thanos-io/thanos/pull/3903) Store: Returning custom grpc code when reaching series/chunk limits.
- [3919](https://github.com/thanos-io/thanos/pull/3919) Allow to disable automatically setting CORS headers using `--web.disable-cors` flag in each component that exposes an API.

### Fixed
- [#3204](https://github.com/thanos-io/thanos/pull/3204) Mixin: Use sidecar's metric timestamp for healthcheck.
Expand Down
2 changes: 1 addition & 1 deletion cmd/thanos/compact.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ func runCompact(
"/loaded",
component,
)
api := blocksAPI.NewBlocksAPI(logger, conf.label, flagsMap)
api := blocksAPI.NewBlocksAPI(logger, conf.webConf.disableCORS, conf.label, flagsMap)
noCompactMarkerFilter := compact.NewGatherNoCompactionMarkFilter(logger, bkt)
var sy *compact.Syncer
{
Expand Down
2 changes: 2 additions & 0 deletions cmd/thanos/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func (sc *shipperConfig) registerFlag(cmd extkingpin.FlagClause) *shipperConfig
type webConfig struct {
externalPrefix string
prefixHeaderName string
disableCORS bool
}

func (wc *webConfig) registerFlag(cmd extkingpin.FlagClause) *webConfig {
Expand All @@ -157,5 +158,6 @@ func (wc *webConfig) registerFlag(cmd extkingpin.FlagClause) *webConfig {
Default("").StringVar(&wc.externalPrefix)
cmd.Flag("web.prefix-header", "Name of HTTP request header used for dynamic prefixing of UI links and redirects. This option is ignored if web.external-prefix argument is set. Security risk: enable this option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path.").
Default("").StringVar(&wc.prefixHeaderName)
cmd.Flag("web.disable-cors", "Whether to disable CORS headers to be set by Thanos. By default Thanos sets CORS headers to be allowed by all.").Default("false").BoolVar(&wc.disableCORS)
return wc
}
4 changes: 4 additions & 0 deletions cmd/thanos/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func registerQuery(app *extkingpin.App) {
webRoutePrefix := cmd.Flag("web.route-prefix", "Prefix for API and UI endpoints. This allows thanos UI to be served on a sub-path. Defaults to the value of --web.external-prefix. This option is analogous to --web.route-prefix of Prometheus.").Default("").String()
webExternalPrefix := cmd.Flag("web.external-prefix", "Static prefix for all HTML links and redirect URLs in the UI query web interface. Actual endpoints are still served on / or the web.route-prefix. This allows thanos UI to be served behind a reverse proxy that strips a URL sub-path.").Default("").String()
webPrefixHeaderName := cmd.Flag("web.prefix-header", "Name of HTTP request header used for dynamic prefixing of UI links and redirects. This option is ignored if web.external-prefix argument is set. Security risk: enable this option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path.").Default("").String()
webDisableCORS := cmd.Flag("web.disable-cors", "Whether to disable CORS headers to be set by Thanos. By default Thanos sets CORS headers to be allowed by all.").Default("false").Bool()

reqLogDecision := cmd.Flag("log.request.decision", "Deprecation Warning - This flag would be soon deprecated, and replaced with `request.logging-config`. Request Logging for logging the start and end of requests. By default this flag is disabled. LogFinishCall: Logs the finish call of the requests. LogStartAndFinishCall: Logs the start and finish call of the requests. NoLogCall: Disable request logging.").Default("").Enum("NoLogCall", "LogFinishCall", "LogStartAndFinishCall", "")

Expand Down Expand Up @@ -233,6 +234,7 @@ func registerQuery(app *extkingpin.App) {
time.Duration(*instantDefaultMaxSourceResolution),
*defaultMetadataTimeRange,
*strictStores,
*webDisableCORS,
component.Query,
)
})
Expand Down Expand Up @@ -288,6 +290,7 @@ func runQuery(
instantDefaultMaxSourceResolution time.Duration,
defaultMetadataTimeRange time.Duration,
strictStores []string,
disableCORS bool,
comp component.Component,
) error {
// TODO(bplotka in PR #513 review): Move arguments into struct.
Expand Down Expand Up @@ -511,6 +514,7 @@ func runQuery(
defaultRangeQueryStep,
instantDefaultMaxSourceResolution,
defaultMetadataTimeRange,
disableCORS,
gate.New(
extprom.WrapRegistererWithPrefix("thanos_query_concurrent_", reg),
maxConcurrentQueries,
Expand Down
5 changes: 4 additions & 1 deletion cmd/thanos/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func registerRule(app *extkingpin.App) {
webRoutePrefix := cmd.Flag("web.route-prefix", "Prefix for API and UI endpoints. This allows thanos UI to be served on a sub-path. This option is analogous to --web.route-prefix of Prometheus.").Default("").String()
webExternalPrefix := cmd.Flag("web.external-prefix", "Static prefix for all HTML links and redirect URLs in the UI query web interface. Actual endpoints are still served on / or the web.route-prefix. This allows thanos UI to be served behind a reverse proxy that strips a URL sub-path.").Default("").String()
webPrefixHeaderName := cmd.Flag("web.prefix-header", "Name of HTTP request header used for dynamic prefixing of UI links and redirects. This option is ignored if web.external-prefix argument is set. Security risk: enable this option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path.").Default("").String()
webDisableCORS := cmd.Flag("web.disable-cors", "Whether to disable CORS headers to be set by Thanos. By default Thanos sets CORS headers to be allowed by all.").Default("false").Bool()

reqLogDecision := cmd.Flag("log.request.decision", "Deprecation Warning - This flag would be soon deprecated, and replaced with `request.logging-config`. Request Logging for logging the start and end of requests. By default this flag is disabled. LogFinishCall: Logs the finish call of the requests. LogStartAndFinishCall: Logs the start and finish call of the requests. NoLogCall: Disable request logging.").Default("").Enum("NoLogCall", "LogFinishCall", "LogStartAndFinishCall", "")

Expand Down Expand Up @@ -217,6 +218,7 @@ func registerRule(app *extkingpin.App) {
*webRoutePrefix,
*webExternalPrefix,
*webPrefixHeaderName,
*webDisableCORS,
time.Duration(*resendDelay),
time.Duration(*evalInterval),
*dataDir,
Expand Down Expand Up @@ -310,6 +312,7 @@ func runRule(
webRoutePrefix string,
webExternalPrefix string,
webPrefixHeaderName string,
disableCORS bool,
resendDelay time.Duration,
evalInterval time.Duration,
dataDir string,
Expand Down Expand Up @@ -626,7 +629,7 @@ func runRule(
// TODO(bplotka in PR #513 review): pass all flags, not only the flags needed by prefix rewriting.
ui.NewRuleUI(logger, reg, ruleMgr, alertQueryURL.String(), webExternalPrefix, webPrefixHeaderName).Register(router, ins)

api := v1.NewRuleAPI(logger, reg, thanosrules.NewGRPCClient(ruleMgr), ruleMgr, flagsMap)
api := v1.NewRuleAPI(logger, reg, thanosrules.NewGRPCClient(ruleMgr), ruleMgr, disableCORS, flagsMap)
api.Register(router.WithPrefix("/api/v1"), tracer, logger, ins, logMiddleware)

srv := httpserver.New(logger, reg, comp, httpProbe,
Expand Down
5 changes: 4 additions & 1 deletion cmd/thanos/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func registerStore(app *extkingpin.App) {

webExternalPrefix := cmd.Flag("web.external-prefix", "Static prefix for all HTML links and redirect URLs in the bucket web UI interface. Actual endpoints are still served on / or the web.route-prefix. This allows thanos bucket web UI to be served behind a reverse proxy that strips a URL sub-path.").Default("").String()
webPrefixHeaderName := cmd.Flag("web.prefix-header", "Name of HTTP request header used for dynamic prefixing of UI links and redirects. This option is ignored if web.external-prefix argument is set. Security risk: enable this option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path.").Default("").String()
webDisableCORS := cmd.Flag("web.disable-cors", "Whether to disable CORS headers to be set by Thanos. By default Thanos sets CORS headers to be allowed by all.").Default("false").Bool()
reqLogConfig := extkingpin.RegisterRequestLoggingFlags(cmd)

cmd.Setup(func(g *run.Group, logger log.Logger, reg *prometheus.Registry, tracer opentracing.Tracer, _ <-chan struct{}, debugLogging bool) error {
Expand Down Expand Up @@ -173,6 +174,7 @@ func registerStore(app *extkingpin.App) {
time.Duration(*ignoreDeletionMarksDelay),
*webExternalPrefix,
*webPrefixHeaderName,
*webDisableCORS,
*postingOffsetsInMemSampling,
cachingBucketConfig,
getFlagsMap(cmd.Flags()),
Expand Down Expand Up @@ -211,6 +213,7 @@ func runStore(
consistencyDelay time.Duration,
ignoreDeletionMarksDelay time.Duration,
externalPrefix, prefixHeader string,
disableCORS bool,
postingOffsetsInMemSampling int,
cachingBucketConfig *extflag.PathOrContent,
flagsMap map[string]string,
Expand Down Expand Up @@ -411,7 +414,7 @@ func runStore(

// Configure Request Logging for HTTP calls.
logMiddleware := logging.NewHTTPServerMiddleware(logger, httpLogOpts...)
api := blocksAPI.NewBlocksAPI(logger, "", flagsMap)
api := blocksAPI.NewBlocksAPI(logger, disableCORS, "", flagsMap)
api.Register(r.WithPrefix("/api/v1"), tracer, logger, ins, logMiddleware)

metaFetcher.UpdateOnChange(func(blocks []metadata.Meta, err error) {
Expand Down
3 changes: 2 additions & 1 deletion cmd/thanos/tools_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ func registerBucketWeb(app extkingpin.AppClause, objStoreConfig *extflag.PathOrC
httpBindAddr, httpGracePeriod := extkingpin.RegisterHTTPFlags(cmd)
webExternalPrefix := cmd.Flag("web.external-prefix", "Static prefix for all HTML links and redirect URLs in the bucket web UI interface. Actual endpoints are still served on / or the web.route-prefix. This allows thanos bucket web UI to be served behind a reverse proxy that strips a URL sub-path.").Default("").String()
webPrefixHeaderName := cmd.Flag("web.prefix-header", "Name of HTTP request header used for dynamic prefixing of UI links and redirects. This option is ignored if web.external-prefix argument is set. Security risk: enable this option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path.").Default("").String()
webDisableCORS := cmd.Flag("web.disable-cors", "Whether to disable CORS headers to be set by Thanos. By default Thanos sets CORS headers to be allowed by all.").Default("false").Bool()
interval := cmd.Flag("refresh", "Refresh interval to download metadata from remote storage").Default("30m").Duration()
timeout := cmd.Flag("timeout", "Timeout to download metadata from remote storage").Default("5m").Duration()
label := cmd.Flag("label", "Prometheus label to use as timeline title").String()
Expand All @@ -348,7 +349,7 @@ func registerBucketWeb(app extkingpin.AppClause, objStoreConfig *extflag.PathOrC

flagsMap := getFlagsMap(cmd.Flags())

api := v1.NewBlocksAPI(logger, *label, flagsMap)
api := v1.NewBlocksAPI(logger, *webDisableCORS, *label, flagsMap)

// Configure Request Logging for HTTP calls.
opts := []logging.Option{logging.WithDecider(func(_ string, _ error) logging.Decision {
Expand Down
11 changes: 8 additions & 3 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,23 +129,25 @@ type BaseAPI struct {
runtimeInfo RuntimeInfoFn
buildInfo *ThanosVersion
Now func() time.Time
disableCORS bool
}

// NewBaseAPI returns a new initialized BaseAPI type.
func NewBaseAPI(logger log.Logger, flagsMap map[string]string) *BaseAPI {
func NewBaseAPI(logger log.Logger, disableCORS bool, flagsMap map[string]string) *BaseAPI {

return &BaseAPI{
logger: logger,
flagsMap: flagsMap,
runtimeInfo: GetRuntimeInfoFunc(logger),
buildInfo: BuildInfo,
disableCORS: disableCORS,
Now: time.Now,
}
}

// Register registers the common API endpoints.
func (api *BaseAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) {
instr := GetInstr(tracer, logger, ins, logMiddleware)
instr := GetInstr(tracer, logger, ins, logMiddleware, api.disableCORS)

r.Options("/*path", instr("options", api.options))

Expand Down Expand Up @@ -199,10 +201,13 @@ func GetInstr(
logger log.Logger,
ins extpromhttp.InstrumentationMiddleware,
logMiddleware *logging.HTTPServerMiddleware,
disableCORS bool,
) InstrFunc {
instr := func(name string, f ApiFunc) http.HandlerFunc {
hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
SetCORS(w)
if !disableCORS {
SetCORS(w)
}
if data, warnings, err := f(r); err != nil {
RespondError(w, err, data)
} else if data != nil {
Expand Down
8 changes: 5 additions & 3 deletions pkg/api/blocks/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type BlocksAPI struct {
logger log.Logger
globalBlocksInfo *BlocksInfo
loadedBlocksInfo *BlocksInfo
disableCORS bool
}

type BlocksInfo struct {
Expand All @@ -32,9 +33,9 @@ type BlocksInfo struct {
}

// NewBlocksAPI creates a simple API to be used by Thanos Block Viewer.
func NewBlocksAPI(logger log.Logger, label string, flagsMap map[string]string) *BlocksAPI {
func NewBlocksAPI(logger log.Logger, disableCORS bool, label string, flagsMap map[string]string) *BlocksAPI {
return &BlocksAPI{
baseAPI: api.NewBaseAPI(logger, flagsMap),
baseAPI: api.NewBaseAPI(logger, disableCORS, flagsMap),
logger: logger,
globalBlocksInfo: &BlocksInfo{
Blocks: []metadata.Meta{},
Expand All @@ -44,13 +45,14 @@ func NewBlocksAPI(logger log.Logger, label string, flagsMap map[string]string) *
Blocks: []metadata.Meta{},
Label: label,
},
disableCORS: disableCORS,
}
}

func (bapi *BlocksAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) {
bapi.baseAPI.Register(r, tracer, logger, ins, logMiddleware)

instr := api.GetInstr(tracer, logger, ins, logMiddleware)
instr := api.GetInstr(tracer, logger, ins, logMiddleware, bapi.disableCORS)

r.Get("/blocks", instr("blocks", bapi.blocks))
}
Expand Down
7 changes: 5 additions & 2 deletions pkg/api/query/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type QueryAPI struct {
enableQueryPartialResponse bool
enableRulePartialResponse bool
enableMetricMetadataPartialResponse bool
disableCORS bool

replicaLabels []string
storeSet *query.StoreSet
Expand All @@ -104,10 +105,11 @@ func NewQueryAPI(
defaultRangeQueryStep time.Duration,
defaultInstantQueryMaxSourceResolution time.Duration,
defaultMetadataTimeRange time.Duration,
disableCORS bool,
gate gate.Gate,
) *QueryAPI {
return &QueryAPI{
baseAPI: api.NewBaseAPI(logger, flagsMap),
baseAPI: api.NewBaseAPI(logger, disableCORS, flagsMap),
logger: logger,
queryEngine: qe,
queryableCreate: c,
Expand All @@ -124,14 +126,15 @@ func NewQueryAPI(
defaultRangeQueryStep: defaultRangeQueryStep,
defaultInstantQueryMaxSourceResolution: defaultInstantQueryMaxSourceResolution,
defaultMetadataTimeRange: defaultMetadataTimeRange,
disableCORS: disableCORS,
}
}

// Register the API's endpoints in the given router.
func (qapi *QueryAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) {
qapi.baseAPI.Register(r, tracer, logger, ins, logMiddleware)

instr := api.GetInstr(tracer, logger, ins, logMiddleware)
instr := api.GetInstr(tracer, logger, ins, logMiddleware, qapi.disableCORS)

r.Get("/query", instr("query", qapi.query))
r.Post("/query", instr("query", qapi.query))
Expand Down
25 changes: 14 additions & 11 deletions pkg/api/rule/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (

// RuleAPI is a very simple API used by Thanos Ruler.
type RuleAPI struct {
baseAPI *api.BaseAPI
logger log.Logger
ruleGroups rules.UnaryClient
alerts alertsRetriever
reg prometheus.Registerer
baseAPI *api.BaseAPI
logger log.Logger
ruleGroups rules.UnaryClient
alerts alertsRetriever
reg prometheus.Registerer
disableCORS bool
}

type alertsRetriever interface {
Expand All @@ -37,21 +38,23 @@ func NewRuleAPI(
reg prometheus.Registerer,
ruleGroups rules.UnaryClient,
activeAlerts alertsRetriever,
disableCORS bool,
flagsMap map[string]string,
) *RuleAPI {
return &RuleAPI{
baseAPI: api.NewBaseAPI(logger, flagsMap),
logger: logger,
ruleGroups: ruleGroups,
alerts: activeAlerts,
reg: reg,
baseAPI: api.NewBaseAPI(logger, disableCORS, flagsMap),
logger: logger,
ruleGroups: ruleGroups,
alerts: activeAlerts,
reg: reg,
disableCORS: disableCORS,
}
}

func (rapi *RuleAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) {
rapi.baseAPI.Register(r, tracer, logger, ins, logMiddleware)

instr := api.GetInstr(tracer, logger, ins, logMiddleware)
instr := api.GetInstr(tracer, logger, ins, logMiddleware, rapi.disableCORS)

r.Get("/alerts", instr("alerts", func(r *http.Request) (interface{}, []error, *api.ApiError) {
return struct{ Alerts []*rulespb.AlertInstance }{Alerts: rapi.alerts.Active()}, nil, nil
Expand Down

0 comments on commit 71cb188

Please sign in to comment.