| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | package ossaccesscontrol | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-08-04 20:44:37 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 	"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-08-04 20:44:37 +08:00
										 |  |  | func removeRoleHelper(role string) { | 
					
						
							|  |  |  | 	delete(accesscontrol.FixedRoles, role) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Compute new grants removing any appearance of the role in the list
 | 
					
						
							|  |  |  | 	replaceGrants := map[string][]string{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for builtInRole, grants := range accesscontrol.FixedRoleGrants { | 
					
						
							|  |  |  | 		newGrants := make([]string, len(grants)) | 
					
						
							|  |  |  | 		for _, r := range grants { | 
					
						
							|  |  |  | 			if r != role { | 
					
						
							|  |  |  | 				newGrants = append(newGrants, r) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		replaceGrants[builtInRole] = newGrants | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Replace grants
 | 
					
						
							|  |  |  | 	for br, grants := range replaceGrants { | 
					
						
							|  |  |  | 		accesscontrol.FixedRoleGrants[br] = grants | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2021-08-24 17:36:28 +08:00
										 |  |  | 	evaluator accesscontrol.Evaluator | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-08-24 17:36:28 +08:00
										 |  |  | 				{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersDisable, accesscontrol.ScopeGlobalUsersAll)}, | 
					
						
							|  |  |  | 				{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersEnable, 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-08-24 17:36:28 +08:00
										 |  |  | 				{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersCreate, 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 { | 
					
						
							| 
									
										
										
										
											2021-08-24 17:36:28 +08:00
										 |  |  | 				result, err := ac.Evaluate(context.Background(), user, endpoint.evaluator) | 
					
						
							| 
									
										
										
										
											2021-04-06 21:49:09 +08:00
										 |  |  | 				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"]) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-04 20:44:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type assignmentTestCase struct { | 
					
						
							|  |  |  | 	role         accesscontrol.RoleDTO | 
					
						
							|  |  |  | 	builtInRoles []string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestOSSAccessControlService_RegisterFixedRole(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name string | 
					
						
							|  |  |  | 		runs []assignmentTestCase | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "Successfully register role no assignments", | 
					
						
							|  |  |  | 			runs: []assignmentTestCase{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "Successfully ignore overwriting existing role", | 
					
						
							|  |  |  | 			runs: []assignmentTestCase{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "Successfully register and assign role", | 
					
						
							|  |  |  | 			runs: []assignmentTestCase{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					builtInRoles: []string{"Viewer", "Editor", "Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "Successfully ignore unchanged assignment", | 
					
						
							|  |  |  | 			runs: []assignmentTestCase{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					builtInRoles: []string{"Viewer"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 2, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					builtInRoles: []string{"Viewer"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "Successfully add a new assignment", | 
					
						
							|  |  |  | 			runs: []assignmentTestCase{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					builtInRoles: []string{"Viewer"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					builtInRoles: []string{"Editor"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check all runs performed so far to get the number of assignments seeder
 | 
					
						
							|  |  |  | 	// should have recorded
 | 
					
						
							|  |  |  | 	getTotalAssignCount := func(curRunIdx int, runs []assignmentTestCase) int { | 
					
						
							|  |  |  | 		builtIns := map[string]struct{}{} | 
					
						
							|  |  |  | 		for i := 0; i < curRunIdx+1; i++ { | 
					
						
							|  |  |  | 			for _, br := range runs[i].builtInRoles { | 
					
						
							|  |  |  | 				builtIns[br] = struct{}{} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return len(builtIns) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tc := range tests { | 
					
						
							|  |  |  | 		t.Run(tc.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			ac := &OSSAccessControlService{ | 
					
						
							|  |  |  | 				Cfg:        setting.NewCfg(), | 
					
						
							|  |  |  | 				UsageStats: &usageStatsMock{t: t, metricsFuncs: make([]usagestats.MetricsFunc, 0)}, | 
					
						
							|  |  |  | 				Log:        log.New("accesscontrol-test"), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for i, run := range tc.runs { | 
					
						
							|  |  |  | 				// Remove any inserted role after the test case has been run
 | 
					
						
							|  |  |  | 				t.Cleanup(func() { removeRoleHelper(run.role.Name) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ac.registerFixedRole(run.role, run.builtInRoles) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Check role has been registered
 | 
					
						
							|  |  |  | 				storedRole, ok := accesscontrol.FixedRoles[run.role.Name] | 
					
						
							|  |  |  | 				assert.True(t, ok, "role should have been registered") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Check registered role has not been altered
 | 
					
						
							|  |  |  | 				assert.Equal(t, run.role, storedRole, "role should not have been altered") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Check assignments
 | 
					
						
							|  |  |  | 				// Count number of times the role has been assigned
 | 
					
						
							|  |  |  | 				assignCnt := 0 | 
					
						
							|  |  |  | 				for _, grants := range accesscontrol.FixedRoleGrants { | 
					
						
							|  |  |  | 					for _, r := range grants { | 
					
						
							|  |  |  | 						if r == run.role.Name { | 
					
						
							|  |  |  | 							assignCnt++ | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				assert.Equal(t, getTotalAssignCount(i, tc.runs), assignCnt, | 
					
						
							|  |  |  | 					"assignments should only be added, never removed") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for _, br := range run.builtInRoles { | 
					
						
							|  |  |  | 					assigns, ok := accesscontrol.FixedRoleGrants[br] | 
					
						
							|  |  |  | 					assert.True(t, ok, | 
					
						
							|  |  |  | 						fmt.Sprintf("role %s should have been assigned to %s", run.role.Name, br)) | 
					
						
							|  |  |  | 					assert.Contains(t, assigns, run.role.Name, | 
					
						
							|  |  |  | 						fmt.Sprintf("role %s should have been assigned to %s", run.role.Name, br)) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestOSSAccessControlService_DeclareFixedRoles(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name          string | 
					
						
							|  |  |  | 		registrations []accesscontrol.RoleRegistration | 
					
						
							|  |  |  | 		wantErr       bool | 
					
						
							|  |  |  | 		err           error | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:    "should work with empty list", | 
					
						
							|  |  |  | 			wantErr: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should add registration", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should fail registration invalid role name", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "custom:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: true, | 
					
						
							|  |  |  | 			err:     accesscontrol.ErrFixedRolePrefixMissing, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should fail registration invalid builtin role assignment", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"WrongAdmin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: true, | 
					
						
							|  |  |  | 			err:     accesscontrol.ErrInvalidBuiltinRole, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should add multiple registrations at once", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test2:test2", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, tt := range tests { | 
					
						
							|  |  |  | 		t.Run(tt.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			ac := &OSSAccessControlService{ | 
					
						
							|  |  |  | 				Cfg:           setting.NewCfg(), | 
					
						
							|  |  |  | 				UsageStats:    &usageStatsMock{t: t, metricsFuncs: make([]usagestats.MetricsFunc, 0)}, | 
					
						
							|  |  |  | 				Log:           log.New("accesscontrol-test"), | 
					
						
							|  |  |  | 				registrations: accesscontrol.RegistrationList{}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ac.Cfg.FeatureToggles = map[string]bool{"accesscontrol": true} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Test
 | 
					
						
							|  |  |  | 			err := ac.DeclareFixedRoles(tt.registrations...) | 
					
						
							|  |  |  | 			if tt.wantErr { | 
					
						
							|  |  |  | 				require.Error(t, err) | 
					
						
							|  |  |  | 				assert.ErrorIs(t, err, tt.err) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			registrationCnt := 0 | 
					
						
							|  |  |  | 			ac.registrations.Range(func(registration accesscontrol.RoleRegistration) bool { | 
					
						
							|  |  |  | 				registrationCnt++ | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			assert.Equal(t, len(tt.registrations), registrationCnt, | 
					
						
							|  |  |  | 				"expected service registration list to contain all test registrations") | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestOSSAccessControlService_RegisterFixedRoles(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name          string | 
					
						
							|  |  |  | 		token         models.Licensing | 
					
						
							|  |  |  | 		registrations []accesscontrol.RoleRegistration | 
					
						
							|  |  |  | 		wantErr       bool | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should work with empty list", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should register and assign role", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "should register and assign multiple roles", | 
					
						
							|  |  |  | 			registrations: []accesscontrol.RoleRegistration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test:test", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Role: accesscontrol.RoleDTO{ | 
					
						
							|  |  |  | 						Version: 1, | 
					
						
							|  |  |  | 						Name:    "fixed:test2:test2", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Grants: []string{"Admin"}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tt := range tests { | 
					
						
							|  |  |  | 		cfg := setting.NewCfg() | 
					
						
							|  |  |  | 		cfg.FeatureToggles = map[string]bool{"accesscontrol": true} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run(tt.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			// Remove any inserted role after the test case has been run
 | 
					
						
							|  |  |  | 			t.Cleanup(func() { | 
					
						
							|  |  |  | 				for _, registration := range tt.registrations { | 
					
						
							|  |  |  | 					removeRoleHelper(registration.Role.Name) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Setup
 | 
					
						
							|  |  |  | 			ac := &OSSAccessControlService{ | 
					
						
							|  |  |  | 				Cfg:           setting.NewCfg(), | 
					
						
							|  |  |  | 				UsageStats:    &usageStatsMock{t: t, metricsFuncs: make([]usagestats.MetricsFunc, 0)}, | 
					
						
							|  |  |  | 				Log:           log.New("accesscontrol-test"), | 
					
						
							|  |  |  | 				registrations: accesscontrol.RegistrationList{}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ac.Cfg.FeatureToggles = map[string]bool{"accesscontrol": true} | 
					
						
							|  |  |  | 			ac.registrations.Append(tt.registrations...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Test
 | 
					
						
							|  |  |  | 			err := ac.RegisterFixedRoles() | 
					
						
							|  |  |  | 			if tt.wantErr { | 
					
						
							|  |  |  | 				require.Error(t, err) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Check
 | 
					
						
							|  |  |  | 			for _, registration := range tt.registrations { | 
					
						
							|  |  |  | 				role, ok := accesscontrol.FixedRoles[registration.Role.Name] | 
					
						
							|  |  |  | 				assert.True(t, ok, | 
					
						
							|  |  |  | 					fmt.Sprintf("role %s should have been registered", registration.Role.Name)) | 
					
						
							|  |  |  | 				assert.NotNil(t, role, | 
					
						
							|  |  |  | 					fmt.Sprintf("role %s should have been registered", registration.Role.Name)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for _, br := range registration.Grants { | 
					
						
							|  |  |  | 					rolesWithGrant, ok := accesscontrol.FixedRoleGrants[br] | 
					
						
							|  |  |  | 					assert.True(t, ok, | 
					
						
							|  |  |  | 						fmt.Sprintf("role %s should have been assigned to %s", registration.Role.Name, br)) | 
					
						
							|  |  |  | 					assert.Contains(t, rolesWithGrant, registration.Role.Name, | 
					
						
							|  |  |  | 						fmt.Sprintf("role %s should have been assigned to %s", registration.Role.Name, br)) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |