mirror of https://github.com/grafana/grafana.git
Team LBAC: Add permission check for Update datasource (#77709)
* add permission check for updating the LBAC Rules * permission scoped for id in the updating datasource * fixed test to cover for permissions * fix proper check for permissions and empty teamHTTPHeader requests * check for jsondata * check nil for jsondata inside the getEncodedString
This commit is contained in:
parent
a39242890e
commit
c13fd62b16
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
|
|
@ -409,6 +410,11 @@ func validateLBACHeader(headervalue string) bool {
|
|||
return err == nil
|
||||
}
|
||||
|
||||
func evaluateTeamHTTPHeaderPermissions(hs *HTTPServer, c *contextmodel.ReqContext, scope string) (bool, error) {
|
||||
ev := ac.EvalPermission(datasources.ActionPermissionsWrite, ac.Scope(scope))
|
||||
return hs.AccessControl.Evaluate(c.Req.Context(), c.SignedInUser, ev)
|
||||
}
|
||||
|
||||
// swagger:route POST /datasources datasources addDataSource
|
||||
//
|
||||
// Create a data source.
|
||||
|
|
@ -446,6 +452,7 @@ func (hs *HTTPServer) AddDataSource(c *contextmodel.ReqContext) response.Respons
|
|||
return resp
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg, hs.Features); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "Failed to add datasource", err)
|
||||
}
|
||||
|
|
@ -514,7 +521,6 @@ func (hs *HTTPServer) UpdateDataSourceByID(c *contextmodel.ReqContext) response.
|
|||
if err := validateJSONData(c.Req.Context(), cmd.JsonData, hs.Cfg, hs.Features); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
ds, err := hs.getRawDataSourceById(c.Req.Context(), cmd.ID, cmd.OrgID)
|
||||
if err != nil {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
|
|
@ -522,6 +528,13 @@ func (hs *HTTPServer) UpdateDataSourceByID(c *contextmodel.ReqContext) response.
|
|||
}
|
||||
return response.Error(500, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
// check if LBAC rules have been modified
|
||||
hasAccess, errAccess := checkTeamHTTPHeaderPermissions(hs, c, ds, cmd)
|
||||
if !hasAccess {
|
||||
return response.Error(http.StatusForbidden, fmt.Sprintf("You'll need additional permissions to perform this action. Permissions needed: %s", datasources.ActionPermissionsWrite), errAccess)
|
||||
}
|
||||
|
||||
return hs.updateDataSourceByID(c, ds, cmd)
|
||||
}
|
||||
|
||||
|
|
@ -563,9 +576,37 @@ func (hs *HTTPServer) UpdateDataSourceByUID(c *contextmodel.ReqContext) response
|
|||
return response.Error(http.StatusInternalServerError, "Failed to update datasource", err)
|
||||
}
|
||||
cmd.ID = ds.ID
|
||||
|
||||
// check if LBAC rules have been modified
|
||||
hasAccess, errAccess := checkTeamHTTPHeaderPermissions(hs, c, ds, cmd)
|
||||
if !hasAccess {
|
||||
return response.Error(http.StatusForbidden, fmt.Sprintf("You'll need additional permissions to perform this action. Permissions needed: %s", datasources.ActionPermissionsWrite), errAccess)
|
||||
}
|
||||
|
||||
return hs.updateDataSourceByID(c, ds, cmd)
|
||||
}
|
||||
|
||||
func getEncodedString(jsonData *simplejson.Json, key string) string {
|
||||
if jsonData == nil {
|
||||
return ""
|
||||
}
|
||||
jsonValues, exists := jsonData.CheckGet(key)
|
||||
if !exists {
|
||||
return ""
|
||||
}
|
||||
val, _ := jsonValues.Encode()
|
||||
return string(val)
|
||||
}
|
||||
|
||||
func checkTeamHTTPHeaderPermissions(hs *HTTPServer, c *contextmodel.ReqContext, ds *datasources.DataSource, cmd datasources.UpdateDataSourceCommand) (bool, error) {
|
||||
currentTeamHTTPHeaders := getEncodedString(ds.JsonData, "teamHttpHeaders")
|
||||
newTeamHTTPHeaders := getEncodedString(cmd.JsonData, "teamHttpHeaders")
|
||||
if (currentTeamHTTPHeaders != "" || newTeamHTTPHeaders != "") && currentTeamHTTPHeaders != newTeamHTTPHeaders {
|
||||
return evaluateTeamHTTPHeaderPermissions(hs, c, datasources.ScopePrefix+ds.UID)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) updateDataSourceByID(c *contextmodel.ReqContext, ds *datasources.DataSource, cmd datasources.UpdateDataSourceCommand) response.Response {
|
||||
if ds.ReadOnly {
|
||||
return response.Error(403, "Cannot update read-only data source", nil)
|
||||
|
|
|
|||
|
|
@ -286,6 +286,10 @@ func TestUpdateDataSourceTeamHTTPHeaders_InvalidJSONData(t *testing.T) {
|
|||
Cfg: setting.NewCfg(),
|
||||
Features: featuremgmt.WithFeatures(featuremgmt.FlagTeamHttpHeaders),
|
||||
accesscontrolService: actest.FakeService{},
|
||||
AccessControl: actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
ExpectedErr: nil,
|
||||
},
|
||||
}
|
||||
sc := setupScenarioContext(t, fmt.Sprintf("/api/datasources/%s", tenantID))
|
||||
hs.Cfg.AuthProxyEnabled = true
|
||||
|
|
@ -300,7 +304,9 @@ func TestUpdateDataSourceTeamHTTPHeaders_InvalidJSONData(t *testing.T) {
|
|||
Type: "test",
|
||||
JsonData: jsonData,
|
||||
})
|
||||
c.SignedInUser = authedUserWithPermissions(1, 1, []ac.Permission{})
|
||||
c.SignedInUser = authedUserWithPermissions(1, 1, []ac.Permission{
|
||||
{Action: datasources.ActionPermissionsWrite, Scope: datasources.ScopeAll},
|
||||
})
|
||||
return hs.AddDataSource(c)
|
||||
}))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue