mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Team LBAC: Refactor to use only the teamHeader json part (#76756)
* refactor: to check for feature toggle and for checking for jsonData field * fix tests * whitelisting of X-Prom-Label-Policy Header
This commit is contained in:
@@ -18,9 +18,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -334,7 +334,7 @@ func validateURL(cmdType string, url string) response.Response {
|
||||
// validateJSONData prevents the user from adding a custom header with name that matches the auth proxy header name.
|
||||
// This is done to prevent data source proxy from being used to circumvent auth proxy.
|
||||
// For more context take a look at CVE-2022-35957
|
||||
func validateJSONData(ctx context.Context, jsonData *simplejson.Json, cfg *setting.Cfg) error {
|
||||
func validateJSONData(ctx context.Context, jsonData *simplejson.Json, cfg *setting.Cfg, features *featuremgmt.FeatureManager) error {
|
||||
if jsonData == nil || !cfg.AuthProxyEnabled {
|
||||
return nil
|
||||
}
|
||||
@@ -350,25 +350,19 @@ func validateJSONData(ctx context.Context, jsonData *simplejson.Json, cfg *setti
|
||||
}
|
||||
|
||||
// Prevent adding a data source team header with a name that matches the auth proxy header name
|
||||
list := contexthandler.AuthHTTPHeaderListFromContext(ctx)
|
||||
if list == nil {
|
||||
return nil
|
||||
}
|
||||
teamHTTPHeadersJSON := datasources.TeamHTTPHeadersJSONData{}
|
||||
if jsonData != nil {
|
||||
jsonData, err := jsonData.MarshalJSON()
|
||||
if features.IsEnabled(featuremgmt.FlagTeamHttpHeaders) {
|
||||
teamHTTPHeadersJSON, err := datasources.GetTeamHTTPHeaders(jsonData)
|
||||
if err != nil {
|
||||
return err
|
||||
datasourcesLogger.Error("Unable to marshal TeamHTTPHeaders")
|
||||
return errors.New("validation error, invalid format of TeamHTTPHeaders")
|
||||
}
|
||||
err = json.Unmarshal(jsonData, &teamHTTPHeadersJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, headers := range teamHTTPHeadersJSON.TeamHTTPHeaders {
|
||||
// whitelisting X-Prom-Label-Policy
|
||||
for _, headers := range teamHTTPHeadersJSON {
|
||||
for _, header := range headers {
|
||||
for _, name := range list.Items {
|
||||
if http.CanonicalHeaderKey(header.Header) == http.CanonicalHeaderKey(name) {
|
||||
datasourcesLogger.Error("Cannot add a data source team header with a used by our proxy header", "headerName", header.Header)
|
||||
// TODO: currently we only allow for X-Prom-Label-Policy header to be used by our proxy
|
||||
for _, name := range []string{"X-Prom-Label-Policy"} {
|
||||
if http.CanonicalHeaderKey(header.Header) != http.CanonicalHeaderKey(name) {
|
||||
datasourcesLogger.Error("Cannot add a data source team header that is different than", "headerName", name)
|
||||
return errors.New("validation error, invalid header name specified")
|
||||
}
|
||||
}
|
||||
@@ -416,7 +410,7 @@ func (hs *HTTPServer) AddDataSource(c *contextmodel.ReqContext) response.Respons
|
||||
return resp
|
||||
}
|
||||
}
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg); err != nil {
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg, hs.Features); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "Failed to add datasource", err)
|
||||
}
|
||||
|
||||
@@ -481,7 +475,7 @@ func (hs *HTTPServer) UpdateDataSourceByID(c *contextmodel.ReqContext) response.
|
||||
if resp := validateURL(cmd.Type, cmd.URL); resp != nil {
|
||||
return resp
|
||||
}
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg); err != nil {
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg, hs.Features); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
@@ -521,7 +515,7 @@ func (hs *HTTPServer) UpdateDataSourceByUID(c *contextmodel.ReqContext) response
|
||||
if resp := validateURL(cmd.Type, cmd.URL); resp != nil {
|
||||
return resp
|
||||
}
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg); err != nil {
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg, hs.Features); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/datasources/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -226,6 +227,7 @@ func TestUpdateDataSourceTeamHTTPHeaders_InvalidJSONData(t *testing.T) {
|
||||
hs := &HTTPServer{
|
||||
DataSourcesService: &dataSourcesServiceMock{},
|
||||
Cfg: setting.NewCfg(),
|
||||
Features: featuremgmt.WithFeatures(featuremgmt.FlagTeamHttpHeaders),
|
||||
}
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
@@ -243,7 +245,7 @@ func TestUpdateDataSourceTeamHTTPHeaders_InvalidJSONData(t *testing.T) {
|
||||
|
||||
hs.Cfg.AuthProxyEnabled = true
|
||||
jsonData := simplejson.New()
|
||||
jsonData.Set("teamHTTPHeaders", data)
|
||||
jsonData.Set("teamHttpHeaders", data)
|
||||
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *contextmodel.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(datasources.AddDataSourceCommand{
|
||||
|
||||
Reference in New Issue
Block a user