Access control: Change data source permissions to be based on UID (#46741)

* Add ResourceAttribute

* Add ResourceAttribute option

* Set ResourceAttribute option

* Change resolvers to return uid based scopes

* update swagger to correct scope

* use ResourceAttribute for endpoint scope

* bump role version

* Add support for different attributes for access control metadata

* evaluate data source metadata based on uid

* Fix test

* uncomment benchmarks

* Use resourceID

* use evaluator for access control metadata

* update comment

* Set default permissions based on uid

* Add attribute to accesscontrol filter

* validate that scopes has correct attribute

* lint

* Update comment

* remove attribute parameter and extend prefix

* refactor to use scope prefix

* Get metadata with prefix

* fix test

* fix comparision

* remove unused type

* fix attribute index

* fix typo

* restructure logic

* Get metadata by uid

* fix imports

Co-authored-by: jguer <joao.guerreiro@grafana.com>
This commit is contained in:
Karl Persson
2022-03-24 12:21:26 +01:00
committed by GitHub
co-authored by jguer
parent 758ccfb69e
commit cac6936015
5 changed files with 47 additions and 44 deletions
@@ -75,9 +75,10 @@ type dataSourceMockRetriever struct {
func (d *dataSourceMockRetriever) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
for _, datasource := range d.res {
nameMatch := query.Name != "" && query.Name == datasource.Name
idMatch := query.Id != 0 && query.Id == datasource.Id
uidMatch := query.Uid != "" && query.Uid == datasource.Uid
if nameMatch || uidMatch {
nameMatch := query.Name != "" && query.Name == datasource.Name
if idMatch || nameMatch || uidMatch {
query.Result = datasource
return nil
@@ -88,10 +89,10 @@ func (d *dataSourceMockRetriever) GetDataSource(ctx context.Context, query *mode
func TestService_NameScopeResolver(t *testing.T) {
retriever := &dataSourceMockRetriever{[]*models.DataSource{
{Id: 1, Name: "test-datasource"},
{Id: 2, Name: "*"},
{Id: 3, Name: ":/*"},
{Id: 4, Name: ":"},
{Name: "test-datasource", Uid: "1"},
{Name: "*", Uid: "2"},
{Name: ":/*", Uid: "3"},
{Name: ":", Uid: "4"},
}}
type testCaseResolver struct {
@@ -105,25 +106,25 @@ func TestService_NameScopeResolver(t *testing.T) {
{
desc: "correct",
given: "datasources:name:test-datasource",
want: "datasources:id:1",
want: "datasources:uid:1",
wantErr: nil,
},
{
desc: "asterisk in name",
given: "datasources:name:*",
want: "datasources:id:2",
want: "datasources:uid:2",
wantErr: nil,
},
{
desc: "complex name",
given: "datasources:name::/*",
want: "datasources:id:3",
want: "datasources:uid:3",
wantErr: nil,
},
{
desc: "colon in name",
given: "datasources:name::",
want: "datasources:id:4",
want: "datasources:uid:4",
wantErr: nil,
},
{
@@ -162,7 +163,7 @@ func TestService_NameScopeResolver(t *testing.T) {
}
}
func TestService_UIDScopeResolver(t *testing.T) {
func TestService_IDScopeResolver(t *testing.T) {
retriever := &dataSourceMockRetriever{[]*models.DataSource{
{Id: 1, Uid: "NnftN9Lnz"},
}}
@@ -177,15 +178,15 @@ func TestService_UIDScopeResolver(t *testing.T) {
testCases := []testCaseResolver{
{
desc: "correct",
given: "datasources:uid:NnftN9Lnz",
want: "datasources:id:1",
given: "datasources:id:1",
want: "datasources:uid:NnftN9Lnz",
wantErr: nil,
},
{
desc: "unknown datasource",
given: "datasources:uid:unknown",
given: "datasources:id:unknown",
want: "",
wantErr: models.ErrDataSourceNotFound,
wantErr: accesscontrol.ErrInvalidScope,
},
{
desc: "malformed scope",
@@ -195,13 +196,13 @@ func TestService_UIDScopeResolver(t *testing.T) {
},
{
desc: "empty uid scope",
given: "datasources:uid:",
given: "datasources:id:",
want: "",
wantErr: accesscontrol.ErrInvalidScope,
},
}
prefix, resolver := NewUidScopeResolver(retriever)
require.Equal(t, "datasources:uid:", prefix)
prefix, resolver := NewIDScopeResolver(retriever)
require.Equal(t, "datasources:id:", prefix)
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {