mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AccessControl: Grant data source reader to all users when running oss (#49514)
* grant data source reader to all users when running oss or enterprise without license * fix asserts in alerting tests * add oss licensing service for test setup * fix tests to pass in enterprise * lint * fix tests * set setting.IsEnterprise flag for tests Co-authored-by: Yuriy Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
parent
8d313f54e2
commit
1796a1d277
@ -94,6 +94,11 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
||||
Grants: []string{string(models.ROLE_ADMIN)},
|
||||
}
|
||||
|
||||
// when running oss or enterprise without a license all users should be able to query data sources
|
||||
if !hs.License.FeatureEnabled("accesscontrol.enforcement") {
|
||||
datasourcesReaderRole.Grants = []string{string(models.ROLE_VIEWER)}
|
||||
}
|
||||
|
||||
datasourcesWriterRole := ac.RoleRegistration{
|
||||
Role: ac.RoleDTO{
|
||||
Version: 3,
|
||||
@ -135,21 +140,6 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
||||
Grants: []string{string(models.ROLE_VIEWER)},
|
||||
}
|
||||
|
||||
datasourcesCompatibilityReaderRole := ac.RoleRegistration{
|
||||
Role: ac.RoleDTO{
|
||||
Version: 3,
|
||||
Name: "fixed:datasources:compatibility:querier",
|
||||
DisplayName: "Data source compatibility querier",
|
||||
Description: "Only used for open source compatibility. Query data sources.",
|
||||
Group: "Infrequently used",
|
||||
Permissions: []ac.Permission{
|
||||
{Action: datasources.ActionQuery},
|
||||
{Action: datasources.ActionRead},
|
||||
},
|
||||
},
|
||||
Grants: []string{string(models.ROLE_VIEWER)},
|
||||
}
|
||||
|
||||
apikeyReaderRole := ac.RoleRegistration{
|
||||
Role: ac.RoleDTO{
|
||||
Version: 1,
|
||||
@ -419,8 +409,8 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
||||
}
|
||||
|
||||
return hs.AccessControl.DeclareFixedRoles(
|
||||
provisioningWriterRole, datasourcesReaderRole, datasourcesWriterRole, datasourcesIdReaderRole,
|
||||
datasourcesCompatibilityReaderRole, orgReaderRole, orgWriterRole,
|
||||
provisioningWriterRole, datasourcesReaderRole, datasourcesWriterRole,
|
||||
datasourcesIdReaderRole, orgReaderRole, orgWriterRole,
|
||||
orgMaintainerRole, teamsCreatorRole, teamsWriterRole, datasourcesExplorerRole,
|
||||
annotationsReaderRole, dashboardAnnotationsWriterRole, annotationsWriterRole,
|
||||
dashboardsCreatorRole, dashboardsReaderRole, dashboardsWriterRole,
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/ldap"
|
||||
"github.com/grafana/grafana/pkg/services/licensing"
|
||||
"github.com/grafana/grafana/pkg/services/login/loginservice"
|
||||
"github.com/grafana/grafana/pkg/services/login/logintest"
|
||||
"github.com/grafana/grafana/pkg/services/preference/preftest"
|
||||
@ -373,6 +374,7 @@ func setupHTTPServerWithCfgDb(t *testing.T, useFakeAccessControl, enableAccessCo
|
||||
QuotaService: "a.QuotaService{Cfg: cfg},
|
||||
RouteRegister: routeRegister,
|
||||
SQLStore: store,
|
||||
License: &licensing.OSSLicensingService{},
|
||||
searchUsersService: searchusers.ProvideUsersService(db, filters.ProvideOSSSearchUserFilter()),
|
||||
dashboardService: dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardsStore, nil, features,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||
)
|
||||
|
||||
@ -2279,9 +2280,9 @@ func TestEval(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
payload string
|
||||
expectedStatusCode int
|
||||
expectedResponse string
|
||||
expectedMessage string
|
||||
expectedStatusCode func() int
|
||||
expectedResponse func() string
|
||||
expectedMessage func() string
|
||||
}{
|
||||
{
|
||||
desc: "alerting condition",
|
||||
@ -2307,8 +2308,10 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedResponse: `{
|
||||
expectedMessage: func() string { return "" },
|
||||
expectedStatusCode: func() int { return http.StatusOK },
|
||||
expectedResponse: func() string {
|
||||
return `{
|
||||
"instances": [
|
||||
{
|
||||
"schema": {
|
||||
@ -2342,7 +2345,8 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
}`
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "normal condition",
|
||||
@ -2368,8 +2372,10 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedResponse: `{
|
||||
expectedMessage: func() string { return "" },
|
||||
expectedStatusCode: func() int { return http.StatusOK },
|
||||
expectedResponse: func() string {
|
||||
return `{
|
||||
"instances": [
|
||||
{
|
||||
"schema": {
|
||||
@ -2403,7 +2409,8 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
}`
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "condition not found in any query or expression",
|
||||
@ -2429,8 +2436,11 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusBadRequest,
|
||||
expectedMessage: "invalid condition: condition B not found in any query or expression: it should be one of: [A]",
|
||||
expectedStatusCode: func() int { return http.StatusBadRequest },
|
||||
expectedMessage: func() string {
|
||||
return "invalid condition: condition B not found in any query or expression: it should be one of: [A]"
|
||||
},
|
||||
expectedResponse: func() string { return "" },
|
||||
},
|
||||
{
|
||||
desc: "unknown query datasource",
|
||||
@ -2454,8 +2464,19 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusUnauthorized,
|
||||
expectedMessage: "user is not authorized to query one or many data sources used by the rule",
|
||||
expectedStatusCode: func() int {
|
||||
if setting.IsEnterprise {
|
||||
return http.StatusUnauthorized
|
||||
}
|
||||
return http.StatusBadRequest
|
||||
},
|
||||
expectedMessage: func() string {
|
||||
if setting.IsEnterprise {
|
||||
return "user is not authorized to query one or many data sources used by the rule"
|
||||
}
|
||||
return "invalid condition: invalid query A: data source not found: unknown"
|
||||
},
|
||||
expectedResponse: func() string { return "" },
|
||||
},
|
||||
}
|
||||
|
||||
@ -2476,12 +2497,12 @@ func TestEval(t *testing.T) {
|
||||
err = json.Unmarshal(b, &res)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
|
||||
if tc.expectedResponse != "" {
|
||||
require.JSONEq(t, tc.expectedResponse, string(b))
|
||||
assert.Equal(t, tc.expectedStatusCode(), resp.StatusCode)
|
||||
if tc.expectedResponse() != "" {
|
||||
require.JSONEq(t, tc.expectedResponse(), string(b))
|
||||
}
|
||||
if tc.expectedMessage != "" {
|
||||
assert.Equal(t, tc.expectedMessage, res.Message)
|
||||
if tc.expectedMessage() != "" {
|
||||
assert.Equal(t, tc.expectedMessage(), res.Message)
|
||||
assert.NotEmpty(t, res.TraceID)
|
||||
}
|
||||
})
|
||||
@ -2491,9 +2512,9 @@ func TestEval(t *testing.T) {
|
||||
testCases = []struct {
|
||||
desc string
|
||||
payload string
|
||||
expectedStatusCode int
|
||||
expectedResponse string
|
||||
expectedMessage string
|
||||
expectedStatusCode func() int
|
||||
expectedResponse func() string
|
||||
expectedMessage func() string
|
||||
}{
|
||||
{
|
||||
desc: "alerting condition",
|
||||
@ -2516,8 +2537,10 @@ func TestEval(t *testing.T) {
|
||||
"now": "2021-04-11T14:38:14Z"
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedResponse: `{
|
||||
expectedMessage: func() string { return "" },
|
||||
expectedStatusCode: func() int { return http.StatusOK },
|
||||
expectedResponse: func() string {
|
||||
return `{
|
||||
"results": {
|
||||
"A": {
|
||||
"frames": [
|
||||
@ -2546,7 +2569,8 @@ func TestEval(t *testing.T) {
|
||||
]
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}`
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "normal condition",
|
||||
@ -2569,8 +2593,10 @@ func TestEval(t *testing.T) {
|
||||
"now": "2021-04-11T14:38:14Z"
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedResponse: `{
|
||||
expectedMessage: func() string { return "" },
|
||||
expectedStatusCode: func() int { return http.StatusOK },
|
||||
expectedResponse: func() string {
|
||||
return `{
|
||||
"results": {
|
||||
"A": {
|
||||
"frames": [
|
||||
@ -2599,7 +2625,8 @@ func TestEval(t *testing.T) {
|
||||
]
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}`
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "unknown query datasource",
|
||||
@ -2620,8 +2647,19 @@ func TestEval(t *testing.T) {
|
||||
"now": "2021-04-11T14:38:14Z"
|
||||
}
|
||||
`,
|
||||
expectedStatusCode: http.StatusUnauthorized,
|
||||
expectedMessage: "user is not authorized to query one or many data sources used by the rule",
|
||||
expectedResponse: func() string { return "" },
|
||||
expectedStatusCode: func() int {
|
||||
if setting.IsEnterprise {
|
||||
return http.StatusUnauthorized
|
||||
}
|
||||
return http.StatusBadRequest
|
||||
},
|
||||
expectedMessage: func() string {
|
||||
if setting.IsEnterprise {
|
||||
return "user is not authorized to query one or many data sources used by the rule"
|
||||
}
|
||||
return "invalid queries or expressions: invalid query A: data source not found: unknown"
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -2642,13 +2680,12 @@ func TestEval(t *testing.T) {
|
||||
err = json.Unmarshal(b, &res)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
|
||||
if tc.expectedResponse != "" {
|
||||
require.JSONEq(t, tc.expectedResponse, string(b))
|
||||
assert.Equal(t, tc.expectedStatusCode(), resp.StatusCode)
|
||||
if tc.expectedResponse() != "" {
|
||||
require.JSONEq(t, tc.expectedResponse(), string(b))
|
||||
}
|
||||
|
||||
if tc.expectedMessage != "" {
|
||||
require.Equal(t, tc.expectedMessage, res.Message)
|
||||
if tc.expectedMessage() != "" {
|
||||
require.Equal(t, tc.expectedMessage(), res.Message)
|
||||
require.NotEmpty(t, res.TraceID)
|
||||
}
|
||||
})
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/extensions"
|
||||
"github.com/grafana/grafana/pkg/infra/fs"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/server"
|
||||
@ -35,6 +36,7 @@ func StartGrafanaEnv(t *testing.T, grafDir, cfgPath string) (string, *server.Tes
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
|
||||
setting.IsEnterprise = extensions.IsEnterprise
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
cmdLineArgs := setting.CommandLineArgs{Config: cfgPath, HomePath: grafDir}
|
||||
|
Loading…
Reference in New Issue
Block a user