| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | package ossaccesscontrol | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/usagestats" | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/registry" | 
					
						
							| 
									
										
										
										
											2021-04-14 22:31:27 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupTestEnv(t testing.TB) *OSSAccessControlService { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg := setting.NewCfg() | 
					
						
							|  |  |  | 	cfg.FeatureToggles = map[string]bool{"accesscontrol": true} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ac := OSSAccessControlService{ | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 		Cfg:        cfg, | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 		UsageStats: &usageStatsMock{metricsFuncs: make([]usagestats.MetricsFunc, 0)}, | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 		Log:        log.New("accesscontrol-test"), | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := ac.Init() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	return &ac | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | type usageStatsMock struct { | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 	t            *testing.T | 
					
						
							|  |  |  | 	metricsFuncs []usagestats.MetricsFunc | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | func (usm *usageStatsMock) RegisterMetricsFunc(fn usagestats.MetricsFunc) { | 
					
						
							|  |  |  | 	usm.metricsFuncs = append(usm.metricsFuncs, fn) | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.UsageReport, error) { | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 	all := make(map[string]interface{}) | 
					
						
							|  |  |  | 	for _, fn := range usm.metricsFuncs { | 
					
						
							|  |  |  | 		fnMetrics, err := fn() | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 		require.NoError(usm.t, err) | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for name, value := range fnMetrics { | 
					
						
							|  |  |  | 			all[name] = value | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 	return usagestats.UsageReport{Metrics: all}, nil | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 05:12:00 +08:00
										 |  |  | func (usm *usageStatsMock) ShouldBeReported(_ string) bool { | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | type evaluatingPermissionsTestCase struct { | 
					
						
							|  |  |  | 	desc       string | 
					
						
							|  |  |  | 	user       userTestCase | 
					
						
							|  |  |  | 	endpoints  []endpointTestCase | 
					
						
							|  |  |  | 	evalResult bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type userTestCase struct { | 
					
						
							|  |  |  | 	name           string | 
					
						
							|  |  |  | 	orgRole        models.RoleType | 
					
						
							|  |  |  | 	isGrafanaAdmin bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type endpointTestCase struct { | 
					
						
							|  |  |  | 	permission string | 
					
						
							|  |  |  | 	scope      []string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestEvaluatingPermissions(t *testing.T) { | 
					
						
							|  |  |  | 	testCases := []evaluatingPermissionsTestCase{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "should successfully evaluate access to the endpoint", | 
					
						
							|  |  |  | 			user: userTestCase{ | 
					
						
							|  |  |  | 				name:           "testuser", | 
					
						
							| 
									
										
										
										
											2021-04-14 22:31:27 +08:00
										 |  |  | 				orgRole:        "Grafana Admin", | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 				isGrafanaAdmin: false, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			endpoints: []endpointTestCase{ | 
					
						
							| 
									
										
										
										
											2021-05-03 16:27:12 +08:00
										 |  |  | 				{permission: accesscontrol.ActionUsersDisable, scope: []string{accesscontrol.ScopeGlobalUsersAll}}, | 
					
						
							|  |  |  | 				{permission: accesscontrol.ActionUsersEnable, scope: []string{accesscontrol.ScopeGlobalUsersAll}}, | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			evalResult: true, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "should restrict access to the unauthorized endpoints", | 
					
						
							|  |  |  | 			user: userTestCase{ | 
					
						
							|  |  |  | 				name:           "testuser", | 
					
						
							|  |  |  | 				orgRole:        models.ROLE_VIEWER, | 
					
						
							|  |  |  | 				isGrafanaAdmin: false, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			endpoints: []endpointTestCase{ | 
					
						
							| 
									
										
										
										
											2021-05-03 16:27:12 +08:00
										 |  |  | 				{permission: accesscontrol.ActionUsersCreate, scope: []string{accesscontrol.ScopeGlobalUsersAll}}, | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			evalResult: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, tc := range testCases { | 
					
						
							|  |  |  | 		t.Run(tc.desc, func(t *testing.T) { | 
					
						
							|  |  |  | 			ac := setupTestEnv(t) | 
					
						
							|  |  |  | 			t.Cleanup(registry.ClearOverrides) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			user := &models.SignedInUser{ | 
					
						
							|  |  |  | 				UserId:         1, | 
					
						
							|  |  |  | 				OrgId:          1, | 
					
						
							|  |  |  | 				Name:           tc.user.name, | 
					
						
							|  |  |  | 				OrgRole:        tc.user.orgRole, | 
					
						
							|  |  |  | 				IsGrafanaAdmin: tc.user.isGrafanaAdmin, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for _, endpoint := range tc.endpoints { | 
					
						
							|  |  |  | 				result, err := ac.Evaluate(context.Background(), user, endpoint.permission, endpoint.scope...) | 
					
						
							|  |  |  | 				require.NoError(t, err) | 
					
						
							|  |  |  | 				assert.Equal(t, tc.evalResult, result) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestUsageMetrics(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name          string | 
					
						
							|  |  |  | 		enabled       bool | 
					
						
							|  |  |  | 		expectedValue int | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "Expecting metric with value 0", | 
					
						
							|  |  |  | 			enabled:       false, | 
					
						
							|  |  |  | 			expectedValue: 0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "Expecting metric with value 1", | 
					
						
							|  |  |  | 			enabled:       true, | 
					
						
							|  |  |  | 			expectedValue: 1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tt := range tests { | 
					
						
							|  |  |  | 		t.Run(tt.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			cfg := setting.NewCfg() | 
					
						
							|  |  |  | 			if tt.enabled { | 
					
						
							|  |  |  | 				cfg.FeatureToggles = map[string]bool{"accesscontrol": true} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			s := &OSSAccessControlService{ | 
					
						
							|  |  |  | 				Cfg:        cfg, | 
					
						
							| 
									
										
										
										
											2021-05-27 16:53:10 +08:00
										 |  |  | 				UsageStats: &usageStatsMock{t: t, metricsFuncs: make([]usagestats.MetricsFunc, 0)}, | 
					
						
							| 
									
										
										
										
											2021-05-17 22:33:38 +08:00
										 |  |  | 				Log:        log.New("accesscontrol-test"), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err := s.Init() | 
					
						
							|  |  |  | 			assert.Nil(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			report, err := s.UsageStats.GetUsageReport(context.Background()) | 
					
						
							|  |  |  | 			assert.Nil(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			assert.Equal(t, tt.expectedValue, report.Metrics["stats.oss.accesscontrol.enabled.count"]) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |