grafana/pkg/middleware/middleware.go

79 lines
2.1 KiB
Go
Raw Normal View History

2014-10-05 09:50:04 -05:00
package middleware
import (
"fmt"
"strings"
2014-10-05 09:50:04 -05:00
Auth: Allow expiration of API keys (#17678) * Modify backend to allow expiration of API Keys * Add middleware test for expired api keys * Modify frontend to enable expiration of API Keys * Fix frontend tests * Fix migration and add index for `expires` field * Add api key tests for database access * Substitude time.Now() by a mock for test usage * Front-end modifications * Change input label to `Time to live` * Change input behavior to comply with the other similar * Add tooltip * Modify AddApiKey api call response Expiration should be *time.Time instead of string * Present expiration date in the selected timezone * Use kbn for transforming intervals to seconds * Use `assert` library for tests * Frontend fixes Add checks for empty/undefined/null values * Change expires column from datetime to integer * Restrict api key duration input It should be interval not number * AddApiKey must complain if SecondsToLive is negative * Declare ErrInvalidApiKeyExpiration * Move configuration to auth section * Update docs * Eliminate alias for models in modified files * Omit expiration from api response if empty * Eliminate Goconvey from test file * Fix test Do not sleep, use mocked timeNow() instead * Remove index for expires from api_key table The index should be anyway on both org_id and expires fields. However this commit eliminates completely the index for now since not many rows are expected to be in this table. * Use getTimeZone function * Minor change in api key listing The frontend should display a message instead of empty string if the key does not expire.
2019-06-26 01:47:03 -05:00
"github.com/grafana/grafana/pkg/models"
2015-02-05 03:37:13 -06:00
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
)
var (
ReqGrafanaAdmin = Auth(&AuthOptions{
ReqSignedIn: true,
ReqGrafanaAdmin: true,
})
ReqSignedIn = Auth(&AuthOptions{ReqSignedIn: true})
ReqSignedInNoAnonymous = Auth(&AuthOptions{ReqSignedIn: true, ReqNoAnonynmous: true})
ReqEditorRole = RoleAuth(models.ROLE_EDITOR, models.ROLE_ADMIN)
ReqOrgAdmin = RoleAuth(models.ROLE_ADMIN)
)
func HandleNoCacheHeader(ctx *models.ReqContext) {
ctx.SkipCache = ctx.Req.Header.Get("X-Grafana-NoCache") == "true"
}
func AddDefaultResponseHeaders(cfg *setting.Cfg) web.Handler {
return func(c *web.Context) {
c.Resp.Before(func(w web.ResponseWriter) {
// if response has already been written, skip.
if w.Written() {
return
}
if !strings.HasPrefix(c.Req.URL.Path, "/api/datasources/proxy/") {
addNoCacheHeaders(c.Resp)
}
if !cfg.AllowEmbedding {
addXFrameOptionsDenyHeader(w)
}
addSecurityHeaders(w, cfg)
})
}
}
// addSecurityHeaders adds HTTP(S) response headers that enable various security protections in the client's browser.
func addSecurityHeaders(w web.ResponseWriter, cfg *setting.Cfg) {
if cfg.StrictTransportSecurity {
strictHeaderValues := []string{fmt.Sprintf("max-age=%v", cfg.StrictTransportSecurityMaxAge)}
if cfg.StrictTransportSecurityPreload {
strictHeaderValues = append(strictHeaderValues, "preload")
}
if cfg.StrictTransportSecuritySubDomains {
strictHeaderValues = append(strictHeaderValues, "includeSubDomains")
}
w.Header().Set("Strict-Transport-Security", strings.Join(strictHeaderValues, "; "))
}
if cfg.ContentTypeProtectionHeader {
w.Header().Set("X-Content-Type-Options", "nosniff")
}
if cfg.XSSProtectionHeader {
w.Header().Set("X-XSS-Protection", "1; mode=block")
}
}
func addNoCacheHeaders(w web.ResponseWriter) {
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "-1")
}
func addXFrameOptionsDenyHeader(w web.ResponseWriter) {
w.Header().Set("X-Frame-Options", "deny")
}