mirror of https://github.com/grafana/grafana.git
				
				
				
			AuthN: Fix namespaces for anonymous and render (#75661)
* AuthN: remove IsAnonymous from identity struct and set correct namespace for anonymous and render * Don't parse user id for render namespace
This commit is contained in:
		
							parent
							
								
									0e2b741fc3
								
							
						
					
					
						commit
						7a38090bc0
					
				|  | @ -188,7 +188,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa | ||||||
| 		cfg, | 		cfg, | ||||||
| 		tracing.InitializeTracerForTest(), | 		tracing.InitializeTracerForTest(), | ||||||
| 		featuremgmt.WithFeatures(), | 		featuremgmt.WithFeatures(), | ||||||
| 		&authntest.FakeService{ExpectedIdentity: &authn.Identity{IsAnonymous: true, SessionToken: &usertoken.UserToken{}}}, | 		&authntest.FakeService{ExpectedIdentity: &authn.Identity{ID: authn.AnonymousNamespaceID, SessionToken: &usertoken.UserToken{}}}, | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ func TestAuth_Middleware(t *testing.T) { | ||||||
| 			desc:           "ReqSignedIn should return 200 for anonymous user", | 			desc:           "ReqSignedIn should return 200 for anonymous user", | ||||||
| 			path:           "/api/secure", | 			path:           "/api/secure", | ||||||
| 			authMiddleware: ReqSignedIn, | 			authMiddleware: ReqSignedIn, | ||||||
| 			identity:       &authn.Identity{IsAnonymous: true}, | 			identity:       &authn.Identity{ID: authn.AnonymousNamespaceID}, | ||||||
| 			expecedReached: true, | 			expecedReached: true, | ||||||
| 			expectedCode:   http.StatusOK, | 			expectedCode:   http.StatusOK, | ||||||
| 		}, | 		}, | ||||||
|  | @ -65,7 +65,7 @@ func TestAuth_Middleware(t *testing.T) { | ||||||
| 			desc:           "ReqSignedIn should return redirect anonymous user with forceLogin query string", | 			desc:           "ReqSignedIn should return redirect anonymous user with forceLogin query string", | ||||||
| 			path:           "/secure?forceLogin=true", | 			path:           "/secure?forceLogin=true", | ||||||
| 			authMiddleware: ReqSignedIn, | 			authMiddleware: ReqSignedIn, | ||||||
| 			identity:       &authn.Identity{IsAnonymous: true}, | 			identity:       &authn.Identity{ID: authn.AnonymousNamespaceID}, | ||||||
| 			expecedReached: false, | 			expecedReached: false, | ||||||
| 			expectedCode:   http.StatusFound, | 			expectedCode:   http.StatusFound, | ||||||
| 		}, | 		}, | ||||||
|  | @ -73,7 +73,7 @@ func TestAuth_Middleware(t *testing.T) { | ||||||
| 			desc:           "ReqSignedIn should return redirect anonymous user when orgId in query string is different from currently used", | 			desc:           "ReqSignedIn should return redirect anonymous user when orgId in query string is different from currently used", | ||||||
| 			path:           "/secure?orgId=2", | 			path:           "/secure?orgId=2", | ||||||
| 			authMiddleware: ReqSignedIn, | 			authMiddleware: ReqSignedIn, | ||||||
| 			identity:       &authn.Identity{IsAnonymous: true, OrgID: 1}, | 			identity:       &authn.Identity{ID: authn.AnonymousNamespaceID, OrgID: 1}, | ||||||
| 			expecedReached: false, | 			expecedReached: false, | ||||||
| 			expectedCode:   http.StatusFound, | 			expectedCode:   http.StatusFound, | ||||||
| 		}, | 		}, | ||||||
|  | @ -81,7 +81,7 @@ func TestAuth_Middleware(t *testing.T) { | ||||||
| 			desc:           "ReqSignedInNoAnonymous should return 401 for anonymous user", | 			desc:           "ReqSignedInNoAnonymous should return 401 for anonymous user", | ||||||
| 			path:           "/api/secure", | 			path:           "/api/secure", | ||||||
| 			authMiddleware: ReqSignedInNoAnonymous, | 			authMiddleware: ReqSignedInNoAnonymous, | ||||||
| 			identity:       &authn.Identity{IsAnonymous: true}, | 			identity:       &authn.Identity{ID: authn.AnonymousNamespaceID}, | ||||||
| 			expecedReached: false, | 			expecedReached: false, | ||||||
| 			expectedCode:   http.StatusUnauthorized, | 			expectedCode:   http.StatusUnauthorized, | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | @ -120,7 +120,7 @@ func (s *Service) getUserPermissions(ctx context.Context, user identity.Requeste | ||||||
| 
 | 
 | ||||||
| 	var userID int64 | 	var userID int64 | ||||||
| 	switch namespace { | 	switch namespace { | ||||||
| 	case authn.NamespaceUser, authn.NamespaceServiceAccount, identity.NamespaceRenderService: | 	case authn.NamespaceUser, authn.NamespaceServiceAccount: | ||||||
| 		var err error | 		var err error | ||||||
| 		userID, err = strconv.ParseInt(identifier, 10, 64) | 		userID, err = strconv.ParseInt(identifier, 10, 64) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ func (a *Anonymous) Authenticate(ctx context.Context, r *authn.Request) (*authn. | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
| 	return &authn.Identity{ | 	return &authn.Identity{ | ||||||
| 		IsAnonymous:  true, | 		ID:           authn.AnonymousNamespaceID, | ||||||
| 		OrgID:        o.ID, | 		OrgID:        o.ID, | ||||||
| 		OrgName:      o.Name, | 		OrgName:      o.Name, | ||||||
| 		OrgRoles:     map[int64]org.RoleType{o.ID: org.RoleType(a.cfg.AnonymousOrgRole)}, | 		OrgRoles:     map[int64]org.RoleType{o.ID: org.RoleType(a.cfg.AnonymousOrgRole)}, | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ func TestAnonymous_Authenticate(t *testing.T) { | ||||||
| 			} else { | 			} else { | ||||||
| 				require.Nil(t, err) | 				require.Nil(t, err) | ||||||
| 
 | 
 | ||||||
| 				assert.Equal(t, true, identity.ID == "") | 				assert.Equal(t, authn.AnonymousNamespaceID, identity.ID) | ||||||
| 				assert.Equal(t, tt.org.ID, identity.OrgID) | 				assert.Equal(t, tt.org.ID, identity.OrgID) | ||||||
| 				assert.Equal(t, tt.org.Name, identity.OrgName) | 				assert.Equal(t, tt.org.Name, identity.OrgName) | ||||||
| 				assert.Equal(t, tt.cfg.AnonymousOrgRole, string(identity.GetOrgRole())) | 				assert.Equal(t, tt.cfg.AnonymousOrgRole, string(identity.GetOrgRole())) | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ func (c *Render) Authenticate(ctx context.Context, r *authn.Request) (*authn.Ide | ||||||
| 	var identity *authn.Identity | 	var identity *authn.Identity | ||||||
| 	if renderUsr.UserID <= 0 { | 	if renderUsr.UserID <= 0 { | ||||||
| 		identity = &authn.Identity{ | 		identity = &authn.Identity{ | ||||||
| 			ID:           authn.NamespacedID(authn.NamespaceUser, 0), | 			ID:           authn.NamespacedID(authn.NamespaceRenderService, 0), | ||||||
| 			OrgID:        renderUsr.OrgID, | 			OrgID:        renderUsr.OrgID, | ||||||
| 			OrgRoles:     map[int64]org.RoleType{renderUsr.OrgID: org.RoleType(renderUsr.OrgRole)}, | 			OrgRoles:     map[int64]org.RoleType{renderUsr.OrgID: org.RoleType(renderUsr.OrgRole)}, | ||||||
| 			ClientParams: authn.ClientParams{SyncPermissions: true}, | 			ClientParams: authn.ClientParams{SyncPermissions: true}, | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ func TestRender_Authenticate(t *testing.T) { | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			expectedIdentity: &authn.Identity{ | 			expectedIdentity: &authn.Identity{ | ||||||
| 				ID:              "user:0", | 				ID:              "render:0", | ||||||
| 				OrgID:           1, | 				OrgID:           1, | ||||||
| 				OrgRoles:        map[int64]org.RoleType{1: org.RoleViewer}, | 				OrgRoles:        map[int64]org.RoleType{1: org.RoleViewer}, | ||||||
| 				AuthenticatedBy: login.RenderModule, | 				AuthenticatedBy: login.RenderModule, | ||||||
|  |  | ||||||
|  | @ -29,6 +29,10 @@ const ( | ||||||
| 	NamespaceRenderService  = identity.NamespaceRenderService | 	NamespaceRenderService  = identity.NamespaceRenderService | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | const ( | ||||||
|  | 	AnonymousNamespaceID = NamespaceAnonymous + ":0" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| var _ identity.Requester = (*Identity)(nil) | var _ identity.Requester = (*Identity)(nil) | ||||||
| 
 | 
 | ||||||
| type Identity struct { | type Identity struct { | ||||||
|  | @ -43,8 +47,6 @@ type Identity struct { | ||||||
| 	// Namespace* constants. For example, "user:1" or "api-key:1".
 | 	// Namespace* constants. For example, "user:1" or "api-key:1".
 | ||||||
| 	// If the entity is not found in the DB or this entity is non-persistent, this field will be empty.
 | 	// If the entity is not found in the DB or this entity is non-persistent, this field will be empty.
 | ||||||
| 	ID string | 	ID string | ||||||
| 	// IsAnonymous
 |  | ||||||
| 	IsAnonymous bool |  | ||||||
| 	// Login is the shorthand identifier of the entity. Should be unique.
 | 	// Login is the shorthand identifier of the entity. Should be unique.
 | ||||||
| 	Login string | 	Login string | ||||||
| 	// Name is the display name of the entity. It is not guaranteed to be unique.
 | 	// Name is the display name of the entity. It is not guaranteed to be unique.
 | ||||||
|  | @ -202,6 +204,8 @@ func (i *Identity) NamespacedID() (string, int64) { | ||||||
| 
 | 
 | ||||||
| // SignedInUser returns a SignedInUser from the identity.
 | // SignedInUser returns a SignedInUser from the identity.
 | ||||||
| func (i *Identity) SignedInUser() *user.SignedInUser { | func (i *Identity) SignedInUser() *user.SignedInUser { | ||||||
|  | 	namespace, id := i.GetNamespacedID() | ||||||
|  | 
 | ||||||
| 	u := &user.SignedInUser{ | 	u := &user.SignedInUser{ | ||||||
| 		OrgID:           i.OrgID, | 		OrgID:           i.OrgID, | ||||||
| 		OrgName:         i.OrgName, | 		OrgName:         i.OrgName, | ||||||
|  | @ -211,7 +215,7 @@ func (i *Identity) SignedInUser() *user.SignedInUser { | ||||||
| 		Email:           i.Email, | 		Email:           i.Email, | ||||||
| 		AuthenticatedBy: i.AuthenticatedBy, | 		AuthenticatedBy: i.AuthenticatedBy, | ||||||
| 		IsGrafanaAdmin:  i.GetIsGrafanaAdmin(), | 		IsGrafanaAdmin:  i.GetIsGrafanaAdmin(), | ||||||
| 		IsAnonymous:     i.IsAnonymous, | 		IsAnonymous:     namespace == NamespaceAnonymous, | ||||||
| 		IsDisabled:      i.IsDisabled, | 		IsDisabled:      i.IsDisabled, | ||||||
| 		HelpFlags1:      i.HelpFlags1, | 		HelpFlags1:      i.HelpFlags1, | ||||||
| 		LastSeenAt:      i.LastSeenAt, | 		LastSeenAt:      i.LastSeenAt, | ||||||
|  | @ -220,7 +224,6 @@ func (i *Identity) SignedInUser() *user.SignedInUser { | ||||||
| 		IDToken:         i.IDToken, | 		IDToken:         i.IDToken, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	namespace, id := i.GetNamespacedID() |  | ||||||
| 	if namespace == NamespaceAPIKey { | 	if namespace == NamespaceAPIKey { | ||||||
| 		u.ApiKeyID = intIdentifier(id) | 		u.ApiKeyID = intIdentifier(id) | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
|  | @ -119,8 +119,8 @@ func (h *ContextHandler) Middleware(next http.Handler) http.Handler { | ||||||
| 		} else { | 		} else { | ||||||
| 			reqContext.SignedInUser = identity.SignedInUser() | 			reqContext.SignedInUser = identity.SignedInUser() | ||||||
| 			reqContext.UserToken = identity.SessionToken | 			reqContext.UserToken = identity.SessionToken | ||||||
| 			reqContext.IsSignedIn = !identity.IsAnonymous | 			reqContext.IsSignedIn = !reqContext.SignedInUser.IsAnonymous | ||||||
| 			reqContext.AllowAnonymous = identity.IsAnonymous | 			reqContext.AllowAnonymous = reqContext.SignedInUser.IsAnonymous | ||||||
| 			reqContext.IsRenderCall = identity.AuthenticatedBy == login.RenderModule | 			reqContext.IsRenderCall = identity.AuthenticatedBy == login.RenderModule | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ func TestContextHandler(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("should not set IsSignedIn on anonymous identity", func(t *testing.T) { | 	t.Run("should not set IsSignedIn on anonymous identity", func(t *testing.T) { | ||||||
| 		identity := &authn.Identity{IsAnonymous: true, OrgID: 1} | 		identity := &authn.Identity{ID: authn.AnonymousNamespaceID, OrgID: 1} | ||||||
| 		handler := contexthandler.ProvideService( | 		handler := contexthandler.ProvideService( | ||||||
| 			setting.NewCfg(), | 			setting.NewCfg(), | ||||||
| 			tracing.InitializeTracerForTest(), | 			tracing.InitializeTracerForTest(), | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue