The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/oauthserver/external_service_test.go

210 lines
6.6 KiB

package oauthserver
import (
"context"
"testing"
"github.com/stretchr/testify/require"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
func setupTestEnv(t *testing.T) *ExternalService {
t.Helper()
client := &ExternalService{
Name: "my-ext-service",
ClientID: "RANDOMID",
Secret: "RANDOMSECRET",
GrantTypes: "client_credentials,urn:ietf:params:oauth:grant-type:jwt-bearer",
ServiceAccountID: 2,
SelfPermissions: []ac.Permission{
{Action: ac.ActionUsersImpersonate, Scope: ac.ScopeUsersAll},
},
SignedInUser: &user.SignedInUser{
UserID: 2,
OrgID: 1,
},
}
return client
}
func TestExternalService_GetScopesOnUser(t *testing.T) {
testCases := []struct {
name string
impersonatePermissions []ac.Permission
initTestEnv func(*ExternalService)
expectedScopes []string
}{
{
name: "should return nil when the service account has no impersonate permissions",
expectedScopes: nil,
},
{
name: "should return the 'profile', 'email' and associated RBAC action",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
},
}
c.ImpersonatePermissions = []ac.Permission{
{Action: ac.ActionUsersRead, Scope: ScopeGlobalUsersSelf},
}
},
expectedScopes: []string{"profile", "email", ac.ActionUsersRead},
},
{
name: "should return 'entitlements' and associated RBAC action scopes",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
},
}
c.ImpersonatePermissions = []ac.Permission{
{Action: ac.ActionUsersPermissionsRead, Scope: ScopeUsersSelf},
}
},
expectedScopes: []string{"entitlements", ac.ActionUsersPermissionsRead},
},
{
name: "should return 'groups' and associated RBAC action scopes",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
},
}
c.ImpersonatePermissions = []ac.Permission{
{Action: ac.ActionTeamsRead, Scope: ScopeTeamsSelf},
}
},
expectedScopes: []string{"groups", ac.ActionTeamsRead},
},
{
name: "should return all scopes",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
},
}
c.ImpersonatePermissions = []ac.Permission{
{Action: ac.ActionUsersRead, Scope: ScopeGlobalUsersSelf},
{Action: ac.ActionUsersPermissionsRead, Scope: ScopeUsersSelf},
{Action: ac.ActionTeamsRead, Scope: ScopeTeamsSelf},
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeDashboardsAll},
}
},
expectedScopes: []string{"profile", "email", ac.ActionUsersRead,
"entitlements", ac.ActionUsersPermissionsRead,
"groups", ac.ActionTeamsRead,
"dashboards:read"},
},
{
name: "should return stored scopes when the client's impersonate scopes has already been set",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
},
}
c.ImpersonateScopes = []string{"dashboard:create", "profile", "email", "entitlements", "groups"}
},
expectedScopes: []string{"profile", "email", "entitlements", "groups", "dashboard:create"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
c := setupTestEnv(t)
if tc.initTestEnv != nil {
tc.initTestEnv(c)
}
scopes := c.GetScopesOnUser(context.Background(), acimpl.ProvideAccessControl(setting.NewCfg()), 3)
require.ElementsMatch(t, tc.expectedScopes, scopes)
})
}
}
func TestExternalService_GetScopes(t *testing.T) {
testCases := []struct {
name string
impersonatePermissions []ac.Permission
initTestEnv func(*ExternalService)
expectedScopes []string
}{
{
name: "should return default scopes when the signed in user is nil",
initTestEnv: func(c *ExternalService) {
c.SignedInUser = nil
},
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
},
{
name: "should return default scopes when the signed in user has no permissions",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{}
},
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
},
{
name: "should return additional scopes from signed in user's permissions",
initTestEnv: func(c *ExternalService) {
c.SignedInUser.Permissions = map[int64]map[string][]string{
1: {
dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll},
},
}
},
expectedScopes: []string{"profile", "email", "entitlements", "groups", "dashboards:read"},
},
{
name: "should return stored scopes when the client's scopes has already been set",
initTestEnv: func(c *ExternalService) {
c.Scopes = []string{"profile", "email", "entitlements", "groups"}
},
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
c := setupTestEnv(t)
if tc.initTestEnv != nil {
tc.initTestEnv(c)
}
scopes := c.GetScopes()
require.ElementsMatch(t, tc.expectedScopes, scopes)
})
}
}
func TestExternalService_ToDTO(t *testing.T) {
client := &ExternalService{
ID: 1,
Name: "my-ext-service",
ClientID: "test",
Secret: "testsecret",
RedirectURI: "http://localhost:3000",
GrantTypes: "client_credentials,urn:ietf:params:oauth:grant-type:jwt-bearer",
Audiences: "https://example.org,https://second.example.org",
PublicPem: []byte("pem_encoded_public_key"),
}
dto := client.ToDTO()
require.Equal(t, client.ClientID, dto.ID)
require.Equal(t, client.Name, dto.Name)
require.Equal(t, client.RedirectURI, dto.RedirectURI)
require.Equal(t, client.GrantTypes, dto.GrantTypes)
require.Equal(t, client.Audiences, dto.Audiences)
require.Equal(t, client.PublicPem, []byte(dto.KeyResult.PublicPem))
require.Empty(t, dto.KeyResult.PrivatePem)
require.Empty(t, dto.KeyResult.URL)
require.False(t, dto.KeyResult.Generated)
require.Equal(t, client.Secret, dto.Secret)
}