| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | package accesscontrol_test | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 16:34:18 +08:00
										 |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 19:29:17 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/datasources" | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 19:29:17 +08:00
										 |  |  | func TestResolvers_AttributeScope(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 	// Calls allow us to see how many times the fakeDataSourceResolution has been called
 | 
					
						
							|  |  |  | 	calls := 0 | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 	fakeDataSourceResolver := accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) { | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		calls++ | 
					
						
							|  |  |  | 		if initialScope == "datasources:name:testds" { | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			return []string{accesscontrol.Scope("datasources", "id", "1")}, nil | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		} else if initialScope == "datasources:name:testds2" { | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			return []string{accesscontrol.Scope("datasources", "id", "2")}, nil | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		} else if initialScope == "datasources:name:test:ds4" { | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			return []string{accesscontrol.Scope("datasources", "id", "4")}, nil | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		} else if initialScope == "datasources:name:testds5*" { | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			return []string{accesscontrol.Scope("datasources", "id", "5")}, nil | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			return nil, datasources.ErrDataSourceNotFound | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name          string | 
					
						
							|  |  |  | 		orgID         int64 | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 		evaluator     accesscontrol.Evaluator | 
					
						
							|  |  |  | 		wantEvaluator accesscontrol.Evaluator | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 		wantCalls     int | 
					
						
							|  |  |  | 		wantErr       error | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "should work with scope less permissions", | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator:     accesscontrol.EvalPermission("datasources:read"), | 
					
						
							|  |  |  | 			wantEvaluator: accesscontrol.EvalPermission("datasources:read"), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 			wantCalls:     0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:      "should handle an error", | 
					
						
							|  |  |  | 			orgID:     1, | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds3")), | 
					
						
							|  |  |  | 			wantErr:   datasources.ErrDataSourceNotFound, | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 			wantCalls: 1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "should resolve a scope", | 
					
						
							|  |  |  | 			orgID:         1, | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator:     accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")), | 
					
						
							|  |  |  | 			wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 			wantCalls:     1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:  "should resolve nested scopes with cache", | 
					
						
							|  |  |  | 			orgID: 1, | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator: accesscontrol.EvalAll( | 
					
						
							|  |  |  | 				accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")), | 
					
						
							|  |  |  | 				accesscontrol.EvalAny( | 
					
						
							|  |  |  | 					accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")), | 
					
						
							|  |  |  | 					accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds2")), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 				), | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			wantEvaluator: accesscontrol.EvalAll( | 
					
						
							|  |  |  | 				accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")), | 
					
						
							|  |  |  | 				accesscontrol.EvalAny( | 
					
						
							|  |  |  | 					accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")), | 
					
						
							|  |  |  | 					accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "2")), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 				), | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			wantCalls: 2, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "should resolve name with colon", | 
					
						
							|  |  |  | 			orgID:         1, | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator:     accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "test:ds4")), | 
					
						
							|  |  |  | 			wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "4")), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 			wantCalls:     1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "should resolve names with '*'", | 
					
						
							|  |  |  | 			orgID:         1, | 
					
						
							| 
									
										
										
										
											2022-06-28 00:23:15 +08:00
										 |  |  | 			evaluator:     accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds5*")), | 
					
						
							|  |  |  | 			wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "5")), | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 			wantCalls:     1, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-08-25 18:50:27 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			name:          "should return error if no resolver is found for scope", | 
					
						
							|  |  |  | 			orgID:         1, | 
					
						
							|  |  |  | 			evaluator:     accesscontrol.EvalPermission("dashboards:read", "dashboards:id:1"), | 
					
						
							|  |  |  | 			wantEvaluator: nil, | 
					
						
							|  |  |  | 			wantCalls:     0, | 
					
						
							|  |  |  | 			wantErr:       accesscontrol.ErrResolverNotFound, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for _, tt := range tests { | 
					
						
							| 
									
										
										
										
											2022-08-25 18:50:27 +08:00
										 |  |  | 		t.Run(tt.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			resolvers := accesscontrol.NewResolvers(log.NewNopLogger()) | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 18:50:27 +08:00
										 |  |  | 			// Reset calls counter
 | 
					
						
							|  |  |  | 			calls = 0 | 
					
						
							|  |  |  | 			// Register a resolution method
 | 
					
						
							|  |  |  | 			resolvers.AddScopeAttributeResolver("datasources:name:", fakeDataSourceResolver) | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 18:50:27 +08:00
										 |  |  | 			// Test
 | 
					
						
							|  |  |  | 			mutate := resolvers.GetScopeAttributeMutator(tt.orgID) | 
					
						
							|  |  |  | 			resolvedEvaluator, err := tt.evaluator.MutateScopes(context.Background(), mutate) | 
					
						
							|  |  |  | 			if tt.wantErr != nil { | 
					
						
							|  |  |  | 				assert.ErrorAs(t, err, &tt.wantErr, "expected an error during the resolution of the scope") | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			assert.NoError(t, err) | 
					
						
							|  |  |  | 			assert.EqualValues(t, tt.wantEvaluator, resolvedEvaluator, "permission did not match expected resolution") | 
					
						
							|  |  |  | 			assert.Equal(t, tt.wantCalls, calls, "cache has not been used") | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-05-02 15:29:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |