mirror of
https://github.com/grafana/grafana.git
synced 2024-12-27 09:21:35 -06:00
2788817107
* AuthZ: Implement Check --------- Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com>
219 lines
5.4 KiB
Go
219 lines
5.4 KiB
Go
package authz
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
|
"github.com/grafana/authlib/claims"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
|
"github.com/grafana/grafana/pkg/services/authn"
|
|
"github.com/grafana/grafana/pkg/services/authn/authntest"
|
|
"github.com/grafana/grafana/pkg/services/authz/mappers"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
|
)
|
|
|
|
var folderTree = []*folder.Folder{
|
|
{
|
|
ID: 1,
|
|
UID: "top",
|
|
Title: "top",
|
|
},
|
|
{
|
|
ID: 2,
|
|
UID: "sub",
|
|
Title: "sub",
|
|
ParentUID: "top",
|
|
},
|
|
{
|
|
ID: 3,
|
|
UID: "sub2",
|
|
Title: "sub2",
|
|
ParentUID: "sub",
|
|
},
|
|
{
|
|
ID: 4,
|
|
UID: "sub3",
|
|
Title: "sub3",
|
|
ParentUID: "sub2",
|
|
},
|
|
}
|
|
|
|
func Test_legacyServer_Check(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
req *authzv1.CheckRequest
|
|
parents []*folder.Folder
|
|
userPerms map[string][]string
|
|
wantAllowed bool
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "should not allow access to a dashboard without read permission",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
userPerms: map[string][]string{},
|
|
wantAllowed: false,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "should allow access to a dashboard with read permission",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
userPerms: map[string][]string{"dashboards:read": {"dashboards:uid:dash1"}},
|
|
wantAllowed: true,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "should allow access to a dashboard through read permission on a parent folder",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
Folder: "sub4",
|
|
},
|
|
parents: folderTree,
|
|
userPerms: map[string][]string{
|
|
"dashboards:read": {"folders:uid:sub"},
|
|
},
|
|
wantAllowed: true,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "should check action only",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Namespace: "org-2",
|
|
},
|
|
userPerms: map[string][]string{"dashboards:read": {"dashboards:uid:dash1"}},
|
|
wantAllowed: true,
|
|
wantErr: false,
|
|
},
|
|
// Input validation
|
|
{
|
|
name: "should return error when group is not set",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "should return error when resource is not set",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "should return error when verb is not set",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "should return error when subject is not set",
|
|
req: &authzv1.CheckRequest{
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "org-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "should return error when namespace is incorrect",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "dashboards.grafana.app",
|
|
Resource: "dashboards",
|
|
Name: "dash1",
|
|
Namespace: "stacks-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "should return error when action is not found",
|
|
req: &authzv1.CheckRequest{
|
|
Subject: "user:1",
|
|
Verb: "get",
|
|
Group: "unknown.grafana.app",
|
|
Resource: "unknown",
|
|
Name: "unknown",
|
|
Namespace: "org-2",
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
f := featuremgmt.WithFeatures()
|
|
l := &legacyServer{
|
|
ac: acimpl.ProvideAccessControl(f, nil),
|
|
authnSvc: &authntest.FakeService{
|
|
ExpectedIdentity: &authn.Identity{
|
|
ID: "user:1",
|
|
UID: "1",
|
|
Type: claims.TypeUser,
|
|
OrgID: 2,
|
|
OrgRoles: map[int64]identity.RoleType{2: identity.RoleNone},
|
|
Login: "user1",
|
|
Permissions: map[int64]map[string][]string{2: tt.userPerms},
|
|
},
|
|
},
|
|
folderSvc: &foldertest.FakeService{ExpectedFolders: tt.parents},
|
|
logger: log.New("authz-grpc-server.test"),
|
|
tracer: tracing.InitializeTracerForTest(),
|
|
mapper: mappers.NewK8sRbacMapper(),
|
|
}
|
|
got, err := l.Check(context.Background(), tt.req)
|
|
if tt.wantErr {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
require.NotNil(t, got)
|
|
require.Equal(t, tt.wantAllowed, got.Allowed)
|
|
})
|
|
}
|
|
}
|