Auth: use IdentityType from authlib (#91763)

This commit is contained in:
Ryan McKinley
2024-08-12 09:26:53 +03:00
committed by GitHub
parent faf7cb9312
commit 21d4a4f49e
70 changed files with 230 additions and 212 deletions
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/authn"
@@ -110,7 +111,7 @@ func (s *SearchOptions) ComputeUserID() (int64, error) {
}
// Validate namespace type is user or service account
if s.TypedID.Type() != identity.TypeUser && s.TypedID.Type() != identity.TypeServiceAccount {
if s.TypedID.Type() != claims.TypeUser && s.TypedID.Type() != claims.TypeServiceAccount {
return 0, fmt.Errorf("invalid type: %s", s.TypedID.Type())
}
+2 -1
View File
@@ -11,6 +11,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/attribute"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/db"
@@ -211,7 +212,7 @@ func (s *Service) getUserDirectPermissions(ctx context.Context, user identity.Re
defer span.End()
var userID int64
if identity.IsIdentityType(user.GetID(), identity.TypeUser, identity.TypeServiceAccount) {
if identity.IsIdentityType(user.GetID(), claims.TypeUser, claims.TypeServiceAccount) {
var err error
userID, err = identity.UserIdentifier(user.GetID())
if err != nil {
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/localcache"
@@ -262,7 +263,7 @@ func benchSearchUserWithAction(b *testing.B, usersCount, resourceCount int) {
for n := 0; n < b.N; n++ {
usersPermissions, err := acService.SearchUsersPermissions(context.Background(), siu,
accesscontrol.SearchOptions{Action: "resources:action2", TypedID: identity.NewTypedID(identity.TypeUser, 14)})
accesscontrol.SearchOptions{Action: "resources:action2", TypedID: identity.NewTypedID(claims.TypeUser, 14)})
require.NoError(b, err)
require.Len(b, usersPermissions, 1)
for _, permissions := range usersPermissions {
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/localcache"
@@ -546,7 +547,7 @@ func TestService_SearchUsersPermissions(t *testing.T) {
// only the user's basic roles and the user's stored permissions
name: "check namespacedId filter works correctly",
siuPermissions: listAllPerms,
searchOption: accesscontrol.SearchOptions{TypedID: identity.NewTypedID(identity.TypeServiceAccount, 1)},
searchOption: accesscontrol.SearchOptions{TypedID: identity.NewTypedID(claims.TypeServiceAccount, 1)},
ramRoles: map[string]*accesscontrol.RoleDTO{
string(identity.RoleEditor): {Permissions: []accesscontrol.Permission{
{Action: accesscontrol.ActionTeamsRead, Scope: "teams:*"},
@@ -618,7 +619,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "ram only",
searchOption: accesscontrol.SearchOptions{
ActionPrefix: "teams",
TypedID: identity.NewTypedID(identity.TypeUser, 2),
TypedID: identity.NewTypedID(claims.TypeUser, 2),
},
ramRoles: map[string]*accesscontrol.RoleDTO{
string(identity.RoleEditor): {Permissions: []accesscontrol.Permission{
@@ -643,7 +644,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "stored only",
searchOption: accesscontrol.SearchOptions{
ActionPrefix: "teams",
TypedID: identity.NewTypedID(identity.TypeUser, 2),
TypedID: identity.NewTypedID(claims.TypeUser, 2),
},
storedPerms: map[int64][]accesscontrol.Permission{
1: {{Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}},
@@ -663,7 +664,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "ram and stored",
searchOption: accesscontrol.SearchOptions{
ActionPrefix: "teams",
TypedID: identity.NewTypedID(identity.TypeUser, 2),
TypedID: identity.NewTypedID(claims.TypeUser, 2),
},
ramRoles: map[string]*accesscontrol.RoleDTO{
string(identity.RoleAdmin): {Permissions: []accesscontrol.Permission{
@@ -693,7 +694,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "check action prefix filter works correctly",
searchOption: accesscontrol.SearchOptions{
ActionPrefix: "teams",
TypedID: identity.NewTypedID(identity.TypeUser, 1),
TypedID: identity.NewTypedID(claims.TypeUser, 1),
},
ramRoles: map[string]*accesscontrol.RoleDTO{
string(identity.RoleEditor): {Permissions: []accesscontrol.Permission{
@@ -715,7 +716,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "check action filter works correctly",
searchOption: accesscontrol.SearchOptions{
Action: accesscontrol.ActionTeamsRead,
TypedID: identity.NewTypedID(identity.TypeUser, 1),
TypedID: identity.NewTypedID(claims.TypeUser, 1),
},
ramRoles: map[string]*accesscontrol.RoleDTO{
string(identity.RoleEditor): {Permissions: []accesscontrol.Permission{
@@ -737,7 +738,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "check action sets are correctly included if an action is specified",
searchOption: accesscontrol.SearchOptions{
Action: "dashboards:read",
TypedID: identity.NewTypedID(identity.TypeUser, 1),
TypedID: identity.NewTypedID(claims.TypeUser, 1),
},
withActionSets: true,
actionSets: map[string][]string{
@@ -770,7 +771,7 @@ func TestService_SearchUserPermissions(t *testing.T) {
name: "check action sets are correctly included if an action prefix is specified",
searchOption: accesscontrol.SearchOptions{
ActionPrefix: "dashboards",
TypedID: identity.NewTypedID(identity.TypeUser, 1),
TypedID: identity.NewTypedID(claims.TypeUser, 1),
},
withActionSets: true,
actionSets: map[string][]string{
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
@@ -187,7 +188,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/api/endpoint", nil)
expectedIdentity := &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, tc.ctxSignedInUser.UserID),
ID: identity.NewTypedID(claims.TypeUser, tc.ctxSignedInUser.UserID),
OrgID: tc.targetOrgId,
Permissions: map[int64]map[string][]string{},
}
@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
)
@@ -21,7 +21,7 @@ func TestPermissionCacheKey(t *testing.T) {
signedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
FallbackType: identity.TypeUser,
FallbackType: claims.TypeUser,
},
expected: "rbac-permissions-1-user-1",
},
@@ -31,7 +31,7 @@ func TestPermissionCacheKey(t *testing.T) {
OrgID: 1,
ApiKeyID: 1,
IsServiceAccount: false,
FallbackType: identity.TypeUser,
FallbackType: claims.TypeUser,
},
expected: "rbac-permissions-1-api-key-1",
},
@@ -41,7 +41,7 @@ func TestPermissionCacheKey(t *testing.T) {
OrgID: 1,
UserID: 1,
IsServiceAccount: true,
FallbackType: identity.TypeUser,
FallbackType: claims.TypeUser,
},
expected: "rbac-permissions-1-service-account-1",
},
@@ -51,7 +51,7 @@ func TestPermissionCacheKey(t *testing.T) {
OrgID: 1,
UserID: -1,
IsServiceAccount: true,
FallbackType: identity.TypeUser, // NOTE, this is still a service account!
FallbackType: claims.TypeUser, // NOTE, this is still a service account!
},
expected: "rbac-permissions-1-service-account--1",
},
@@ -60,7 +60,7 @@ func TestPermissionCacheKey(t *testing.T) {
signedInUser: &user.SignedInUser{
OrgID: 1,
OrgRole: org.RoleNone,
FallbackType: identity.TypeUser,
FallbackType: claims.TypeUser,
},
expected: "rbac-permissions-1-user-None",
},
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/localcache"
@@ -626,7 +627,7 @@ func TestIntegrationAccessControlStore_SearchUsersPermissions(t *testing.T) {
},
options: accesscontrol.SearchOptions{
ActionPrefix: "teams:",
TypedID: identity.NewTypedID(identity.TypeUser, 1),
TypedID: identity.NewTypedID(claims.TypeUser, 1),
},
wantPerm: map[int64][]accesscontrol.Permission{
1: {{Action: "teams:read", Scope: "teams:id:1"}, {Action: "teams:read", Scope: "teams:id:10"},
+3 -2
View File
@@ -6,6 +6,7 @@ import (
"net/http"
"strings"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -69,8 +70,8 @@ func (a *Anonymous) Test(ctx context.Context, r *authn.Request) bool {
return true
}
func (a *Anonymous) IdentityType() identity.IdentityType {
return identity.TypeAnonymous
func (a *Anonymous) IdentityType() claims.IdentityType {
return claims.TypeAnonymous
}
func (a *Anonymous) ResolveIdentity(ctx context.Context, orgID int64, namespaceID identity.TypedID) (*authn.Identity, error) {
+2 -1
View File
@@ -8,6 +8,7 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
authnlib "github.com/grafana/authlib/authn"
authnlibclaims "github.com/grafana/authlib/claims"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sync/singleflight"
@@ -99,7 +100,7 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
},
}
if identity.IsIdentityType(id.GetID(), identity.TypeUser) {
if identity.IsIdentityType(id.GetID(), authnlibclaims.TypeUser) {
claims.Rest.Email = id.GetEmail()
claims.Rest.EmailVerified = id.IsEmailVerified()
claims.Rest.AuthenticatedBy = id.GetAuthenticatedBy()
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/services/auth"
@@ -85,7 +86,7 @@ func TestService_SignIdentity(t *testing.T) {
ID: identity.MustParseTypedID("user:1"),
AuthenticatedBy: login.AzureADAuthModule,
Login: "U1",
UID: identity.NewTypedIDString(identity.TypeUser, "edpu3nnt61se8e")})
UID: identity.NewTypedIDString(claims.TypeUser, "edpu3nnt61se8e")})
require.NoError(t, err)
parsed, err := jwt.ParseSigned(token)
@@ -108,7 +109,7 @@ func TestService_SignIdentity(t *testing.T) {
ID: identity.MustParseTypedID("user:1"),
AuthenticatedBy: login.AzureADAuthModule,
Login: "U1",
UID: identity.NewTypedIDString(identity.TypeUser, "edpu3nnt61se8e")})
UID: identity.NewTypedIDString(claims.TypeUser, "edpu3nnt61se8e")})
require.NoError(t, err)
assert.Equal(t, login.AzureADAuthModule, gotClaims.Rest.AuthenticatedBy)
+2 -1
View File
@@ -8,6 +8,7 @@ import (
"strconv"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/middleware/cookies"
@@ -179,7 +180,7 @@ type UsageStatClient interface {
// Clients that implements this interface can resolve an full identity from an orgID and namespaceID.
type IdentityResolverClient interface {
Client
IdentityType() identity.IdentityType
IdentityType() claims.IdentityType
ResolveIdentity(ctx context.Context, orgID int64, namespaceID identity.TypedID) (*Identity, error)
}
+5 -4
View File
@@ -12,6 +12,7 @@ import (
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -217,7 +218,7 @@ func (s *Service) Login(ctx context.Context, client string, r *authn.Request) (i
}
// Login is only supported for users
if !id.ID.IsType(identity.TypeUser) {
if !id.ID.IsType(claims.TypeUser) {
s.metrics.failedLogin.WithLabelValues(client).Inc()
return nil, authn.ErrUnsupportedIdentity.Errorf("expected identity of type user but got: %s", id.ID.Type())
}
@@ -281,7 +282,7 @@ func (s *Service) Logout(ctx context.Context, user identity.Requester, sessionTo
redirect.URL = s.cfg.SignoutRedirectUrl
}
if !user.GetID().IsType(identity.TypeUser) {
if !user.GetID().IsType(claims.TypeUser) {
return redirect, nil
}
@@ -380,7 +381,7 @@ func (s *Service) resolveIdenity(ctx context.Context, orgID int64, namespaceID i
ctx, span := s.tracer.Start(ctx, "authn.resolveIdentity")
defer span.End()
if namespaceID.IsType(identity.TypeUser) {
if namespaceID.IsType(claims.TypeUser) {
return &authn.Identity{
OrgID: orgID,
ID: namespaceID,
@@ -391,7 +392,7 @@ func (s *Service) resolveIdenity(ctx context.Context, orgID int64, namespaceID i
}}, nil
}
if namespaceID.IsType(identity.TypeServiceAccount) {
if namespaceID.IsType(claims.TypeServiceAccount) {
return &authn.Identity{
ID: namespaceID,
OrgID: orgID,
+8 -7
View File
@@ -15,6 +15,7 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
@@ -420,31 +421,31 @@ func TestService_Logout(t *testing.T) {
tests := []TestCase{
{
desc: "should redirect to default redirect url when identity is not a user",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeServiceAccount, 1)},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeServiceAccount, 1)},
expectedRedirect: &authn.Redirect{URL: "http://localhost:3000/login"},
},
{
desc: "should redirect to default redirect url when no external provider was used to authenticate",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1)},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1)},
expectedRedirect: &authn.Redirect{URL: "http://localhost:3000/login"},
expectedTokenRevoked: true,
},
{
desc: "should redirect to default redirect url when client is not found",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1), AuthenticatedBy: "notfound"},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1), AuthenticatedBy: "notfound"},
expectedRedirect: &authn.Redirect{URL: "http://localhost:3000/login"},
expectedTokenRevoked: true,
},
{
desc: "should redirect to default redirect url when client do not implement logout extension",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1), AuthenticatedBy: "azuread"},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1), AuthenticatedBy: "azuread"},
expectedRedirect: &authn.Redirect{URL: "http://localhost:3000/login"},
client: &authntest.FakeClient{ExpectedName: "auth.client.azuread"},
expectedTokenRevoked: true,
},
{
desc: "should use signout redirect url if configured",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1), AuthenticatedBy: "azuread"},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1), AuthenticatedBy: "azuread"},
expectedRedirect: &authn.Redirect{URL: "some-url"},
client: &authntest.FakeClient{ExpectedName: "auth.client.azuread"},
signoutRedirectURL: "some-url",
@@ -452,7 +453,7 @@ func TestService_Logout(t *testing.T) {
},
{
desc: "should redirect to client specific url",
identity: &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1), AuthenticatedBy: "azuread"},
identity: &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1), AuthenticatedBy: "azuread"},
expectedRedirect: &authn.Redirect{URL: "http://idp.com/logout"},
client: &authntest.MockClient{
NameFunc: func() string { return "auth.client.azuread" },
@@ -527,7 +528,7 @@ func TestService_ResolveIdentity(t *testing.T) {
t.Run("should resolve for valid namespace if client is registered", func(t *testing.T) {
svc := setupTests(t, func(svc *Service) {
svc.RegisterClient(&authntest.MockClient{
IdentityTypeFunc: func() identity.IdentityType { return identity.TypeAPIKey },
IdentityTypeFunc: func() claims.IdentityType { return claims.TypeAPIKey },
ResolveIdentityFunc: func(ctx context.Context, orgID int64, namespaceID identity.TypedID) (*authn.Identity, error) {
return &authn.Identity{}, nil
},
@@ -8,7 +8,7 @@ import (
"golang.org/x/sync/singleflight"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/login/social"
@@ -42,7 +42,7 @@ func (s *OAuthTokenSync) SyncOauthTokenHook(ctx context.Context, id *authn.Ident
defer span.End()
// only perform oauth token check if identity is a user
if !id.ID.IsType(identity.TypeUser) {
if !id.ID.IsType(claims.TypeUser) {
return nil
}
@@ -6,7 +6,7 @@ import (
"fmt"
"sort"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
@@ -39,7 +39,7 @@ func (s *OrgSync) SyncOrgRolesHook(ctx context.Context, id *authn.Identity, _ *a
ctxLogger := s.log.FromContext(ctx).New("id", id.ID, "login", id.Login)
if !id.ID.IsType(identity.TypeUser) {
if !id.ID.IsType(claims.TypeUser) {
ctxLogger.Warn("Failed to sync org role, invalid namespace for identity", "type", id.ID.Type())
return nil
}
@@ -145,7 +145,7 @@ func (s *OrgSync) SetDefaultOrgHook(ctx context.Context, currentIdentity *authn.
ctxLogger := s.log.FromContext(ctx)
if !currentIdentity.ID.IsType(identity.TypeUser) {
if !currentIdentity.ID.IsType(claims.TypeUser) {
ctxLogger.Debug("Skipping default org sync, not a user", "type", currentIdentity.ID.Type())
return
}
@@ -6,8 +6,8 @@ import (
"golang.org/x/exp/maps"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
@@ -148,7 +148,7 @@ func (s *RBACSync) SyncCloudRoles(ctx context.Context, ident *authn.Identity, r
return nil
}
if !ident.ID.IsType(identity.TypeUser) {
if !ident.ID.IsType(claims.TypeUser) {
s.log.FromContext(ctx).Debug("Skip syncing cloud role", "id", ident.ID)
return nil
}
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
@@ -67,7 +68,7 @@ func TestRBACSync_SyncCloudRoles(t *testing.T) {
desc: "should call sync when authenticated with grafana com and has viewer role",
module: login.GrafanaComAuthModule,
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleViewer},
},
@@ -78,7 +79,7 @@ func TestRBACSync_SyncCloudRoles(t *testing.T) {
desc: "should call sync when authenticated with grafana com and has editor role",
module: login.GrafanaComAuthModule,
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleEditor},
},
@@ -89,7 +90,7 @@ func TestRBACSync_SyncCloudRoles(t *testing.T) {
desc: "should call sync when authenticated with grafana com and has admin role",
module: login.GrafanaComAuthModule,
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
},
@@ -100,7 +101,7 @@ func TestRBACSync_SyncCloudRoles(t *testing.T) {
desc: "should not call sync when authenticated with grafana com and has invalid role",
module: login.GrafanaComAuthModule,
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleType("something else")},
},
@@ -111,7 +112,7 @@ func TestRBACSync_SyncCloudRoles(t *testing.T) {
desc: "should not call sync when not authenticated with grafana com",
module: login.LDAPAuthModule,
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
},
@@ -157,7 +158,7 @@ func TestRBACSync_cloudRolesToAddAndRemove(t *testing.T) {
{
desc: "should map Cloud Viewer to Grafana Cloud Viewer and Support ticket reader",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleViewer},
},
@@ -176,7 +177,7 @@ func TestRBACSync_cloudRolesToAddAndRemove(t *testing.T) {
{
desc: "should map Cloud Editor to Grafana Cloud Editor and Support ticket admin",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleEditor},
},
@@ -194,7 +195,7 @@ func TestRBACSync_cloudRolesToAddAndRemove(t *testing.T) {
{
desc: "should map Cloud Admin to Grafana Cloud Admin and Support ticket admin",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
},
@@ -212,7 +213,7 @@ func TestRBACSync_cloudRolesToAddAndRemove(t *testing.T) {
{
desc: "should return an error for not supported role",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
OrgID: 1,
OrgRoles: map[int64]org.RoleType{1: org.RoleNone},
},
+10 -9
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -118,7 +119,7 @@ func (s *UserSync) FetchSyncedUserHook(ctx context.Context, id *authn.Identity,
return nil
}
if !id.ID.IsType(identity.TypeUser, identity.TypeServiceAccount) {
if !id.ID.IsType(claims.TypeUser, claims.TypeServiceAccount) {
return nil
}
@@ -159,7 +160,7 @@ func (s *UserSync) SyncLastSeenHook(ctx context.Context, id *authn.Identity, r *
return nil
}
if !id.ID.IsType(identity.TypeUser, identity.TypeServiceAccount) {
if !id.ID.IsType(claims.TypeUser, claims.TypeServiceAccount) {
return nil
}
@@ -195,7 +196,7 @@ func (s *UserSync) EnableUserHook(ctx context.Context, id *authn.Identity, _ *au
return nil
}
if !id.ID.IsType(identity.TypeUser) {
if !id.ID.IsType(claims.TypeUser) {
return nil
}
@@ -418,8 +419,8 @@ func (s *UserSync) lookupByOneOf(ctx context.Context, params login.UserLookupPar
// syncUserToIdentity syncs a user to an identity.
// This is used to update the identity with the latest user information.
func syncUserToIdentity(usr *user.User, id *authn.Identity) {
id.ID = identity.NewTypedID(identity.TypeUser, usr.ID)
id.UID = identity.NewTypedIDString(identity.TypeUser, usr.UID)
id.ID = identity.NewTypedID(claims.TypeUser, usr.ID)
id.UID = identity.NewTypedIDString(claims.TypeUser, usr.UID)
id.Login = usr.Login
id.Email = usr.Email
id.Name = usr.Name
@@ -429,11 +430,11 @@ func syncUserToIdentity(usr *user.User, id *authn.Identity) {
// syncSignedInUserToIdentity syncs a user to an identity.
func syncSignedInUserToIdentity(usr *user.SignedInUser, id *authn.Identity) {
var ns identity.IdentityType
if id.ID.IsType(identity.TypeServiceAccount) {
ns = identity.TypeServiceAccount
var ns claims.IdentityType
if id.ID.IsType(claims.TypeServiceAccount) {
ns = claims.TypeServiceAccount
} else {
ns = identity.TypeUser
ns = claims.TypeUser
}
id.UID = identity.NewTypedIDString(ns, usr.UserUID)
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/authn"
@@ -484,7 +485,7 @@ func TestUserSync_EnableDisabledUserHook(t *testing.T) {
{
desc: "should skip if correct flag is not set",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
IsDisabled: true,
ClientParams: authn.ClientParams{EnableUser: false},
},
@@ -493,7 +494,7 @@ func TestUserSync_EnableDisabledUserHook(t *testing.T) {
{
desc: "should skip if identity is not a user",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeAPIKey, 1),
ID: identity.NewTypedID(claims.TypeAPIKey, 1),
IsDisabled: true,
ClientParams: authn.ClientParams{EnableUser: true},
},
@@ -502,7 +503,7 @@ func TestUserSync_EnableDisabledUserHook(t *testing.T) {
{
desc: "should enabled disabled user",
identity: &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, 1),
ID: identity.NewTypedID(claims.TypeUser, 1),
IsDisabled: true,
ClientParams: authn.ClientParams{EnableUser: true},
},
+4 -3
View File
@@ -3,6 +3,7 @@ package authntest
import (
"context"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/authn"
@@ -77,7 +78,7 @@ type MockClient struct {
PriorityFunc func() uint
HookFunc func(ctx context.Context, identity *authn.Identity, r *authn.Request) error
LogoutFunc func(ctx context.Context, user identity.Requester) (*authn.Redirect, bool)
IdentityTypeFunc func() identity.IdentityType
IdentityTypeFunc func() claims.IdentityType
ResolveIdentityFunc func(ctx context.Context, orgID int64, namespaceID identity.TypedID) (*authn.Identity, error)
}
@@ -127,11 +128,11 @@ func (m *MockClient) Logout(ctx context.Context, user identity.Requester) (*auth
return nil, false
}
func (m *MockClient) IdentityType() identity.IdentityType {
func (m *MockClient) IdentityType() claims.IdentityType {
if m.IdentityTypeFunc != nil {
return m.IdentityTypeFunc()
}
return identity.TypeEmpty
return claims.TypeEmpty
}
// ResolveIdentity implements authn.IdentityResolverClient.
+8 -7
View File
@@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/components/apikeygen"
@@ -135,12 +136,12 @@ func (s *APIKey) Priority() uint {
return 30
}
func (s *APIKey) IdentityType() identity.IdentityType {
return identity.TypeAPIKey
func (s *APIKey) IdentityType() claims.IdentityType {
return claims.TypeAPIKey
}
func (s *APIKey) ResolveIdentity(ctx context.Context, orgID int64, namespaceID identity.TypedID) (*authn.Identity, error) {
if !namespaceID.IsType(identity.TypeAPIKey) {
if !namespaceID.IsType(claims.TypeAPIKey) {
return nil, identity.ErrInvalidTypedID.Errorf("got unspected namespace: %s", namespaceID.Type())
}
@@ -195,11 +196,11 @@ func (s *APIKey) getAPIKeyID(ctx context.Context, id *authn.Identity, r *authn.R
return -1, false
}
if id.ID.IsType(identity.TypeAPIKey) {
if id.ID.IsType(claims.TypeAPIKey) {
return internalId, true
}
if id.ID.IsType(identity.TypeServiceAccount) {
if id.ID.IsType(claims.TypeServiceAccount) {
// When the identity is service account, the ID in from the namespace is the service account ID.
// We need to fetch the API key in this scenario, as we could use it to uniquely identify a service account token.
apiKey, err := s.getAPIKey(ctx, getTokenFromRequest(r))
@@ -256,7 +257,7 @@ func validateApiKey(orgID int64, key *apikey.APIKey) error {
func newAPIKeyIdentity(key *apikey.APIKey) *authn.Identity {
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeAPIKey, key.ID),
ID: identity.NewTypedID(claims.TypeAPIKey, key.ID),
OrgID: key.OrgID,
OrgRoles: map[int64]org.RoleType{key.OrgID: key.Role},
ClientParams: authn.ClientParams{SyncPermissions: true},
@@ -266,7 +267,7 @@ func newAPIKeyIdentity(key *apikey.APIKey) *authn.Identity {
func newServiceAccountIdentity(key *apikey.APIKey) *authn.Identity {
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeServiceAccount, *key.ServiceAccountId),
ID: identity.NewTypedID(claims.TypeServiceAccount, *key.ServiceAccountId),
OrgID: key.OrgID,
AuthenticatedBy: login.APIKeyAuthModule,
ClientParams: authn.ClientParams{FetchSyncedUser: true, SyncPermissions: true},
+4 -4
View File
@@ -8,7 +8,7 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
authlib "github.com/grafana/authlib/authn"
authlibclaims "github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -114,7 +114,7 @@ func (s *ExtendedJWT) authenticateAsUser(
return nil, errExtJWTInvalidSubject.Errorf("unexpected identity: %s", accessID.String())
}
if !accessID.IsType(identity.TypeAccessPolicy) {
if !accessID.IsType(authlibclaims.TypeAccessPolicy) {
return nil, errExtJWTInvalid.Errorf("unexpected identity: %s", accessID.String())
}
@@ -123,7 +123,7 @@ func (s *ExtendedJWT) authenticateAsUser(
return nil, errExtJWTInvalid.Errorf("failed to parse id token subject: %w", err)
}
if !userID.IsType(identity.TypeUser) {
if !userID.IsType(authlibclaims.TypeUser) {
return nil, errExtJWTInvalidSubject.Errorf("unexpected identity: %s", userID.String())
}
@@ -160,7 +160,7 @@ func (s *ExtendedJWT) authenticateAsService(claims *authlib.Claims[authlib.Acces
return nil, fmt.Errorf("failed to parse access token subject: %w", err)
}
if !id.IsType(identity.TypeAccessPolicy) {
if !id.IsType(authlibclaims.TypeAccessPolicy) {
return nil, errExtJWTInvalidSubject.Errorf("unexpected identity: %s", id.String())
}
+2 -5
View File
@@ -11,15 +11,12 @@ import (
"github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
authnlib "github.com/grafana/authlib/authn"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type (
+2 -1
View File
@@ -6,6 +6,7 @@ import (
"errors"
"net/mail"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/login"
@@ -106,7 +107,7 @@ func (c *Grafana) AuthenticatePassword(ctx context.Context, r *authn.Request, us
}
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, usr.ID),
ID: identity.NewTypedID(claims.TypeUser, usr.ID),
OrgID: r.OrgID,
ClientParams: authn.ClientParams{FetchSyncedUser: true, SyncPermissions: true},
AuthenticatedBy: login.PasswordAuthModule,
+2 -1
View File
@@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/login/social/socialtest"
@@ -485,7 +486,7 @@ func TestOAuth_Logout(t *testing.T) {
}
c := ProvideOAuth(authn.ClientWithPrefix("azuread"), tt.cfg, mockService, fakeSocialSvc, &setting.OSSImpl{Cfg: tt.cfg}, featuremgmt.WithFeatures())
redirect, ok := c.Logout(context.Background(), &authn.Identity{ID: identity.NewTypedIDString(identity.TypeUser, "1")})
redirect, ok := c.Logout(context.Background(), &authn.Identity{ID: identity.NewTypedIDString(claims.TypeUser, "1")})
assert.Equal(t, tt.expectedOK, ok)
if tt.expectedOK {
+3 -2
View File
@@ -12,6 +12,7 @@ import (
"strings"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -125,7 +126,7 @@ func (c *Proxy) retrieveIDFromCache(ctx context.Context, cacheKey string, r *aut
}
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, uid),
ID: identity.NewTypedID(claims.TypeUser, uid),
OrgID: r.OrgID,
// FIXME: This does not match the actual auth module used, but should not have any impact
// Maybe caching the auth module used with the user ID would be a good idea
@@ -150,7 +151,7 @@ func (c *Proxy) Hook(ctx context.Context, id *authn.Identity, r *authn.Request)
return nil
}
if !id.ID.IsType(identity.TypeUser) {
if !id.ID.IsType(claims.TypeUser) {
return nil
}
+2 -1
View File
@@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/authn/authntest"
@@ -204,7 +205,7 @@ func TestProxy_Hook(t *testing.T) {
}
cache := &fakeCache{data: make(map[string][]byte)}
userId := int64(1)
userID := identity.NewTypedID(identity.TypeUser, userId)
userID := identity.NewTypedID(claims.TypeUser, userId)
// withRole creates a test case for a user with a specific role.
withRole := func(role string) func(t *testing.T) {
+3 -2
View File
@@ -4,6 +4,7 @@ import (
"context"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/authn"
@@ -43,7 +44,7 @@ func (c *Render) Authenticate(ctx context.Context, r *authn.Request) (*authn.Ide
if renderUsr.UserID <= 0 {
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeRenderService, 0),
ID: identity.NewTypedID(claims.TypeRenderService, 0),
OrgID: renderUsr.OrgID,
OrgRoles: map[int64]org.RoleType{renderUsr.OrgID: org.RoleType(renderUsr.OrgRole)},
ClientParams: authn.ClientParams{SyncPermissions: true},
@@ -53,7 +54,7 @@ func (c *Render) Authenticate(ctx context.Context, r *authn.Request) (*authn.Ide
}
return &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, renderUsr.UserID),
ID: identity.NewTypedID(claims.TypeUser, renderUsr.UserID),
LastSeenAt: time.Now(),
AuthenticatedBy: login.RenderModule,
ClientParams: authn.ClientParams{FetchSyncedUser: true, SyncPermissions: true},
+2 -1
View File
@@ -6,6 +6,7 @@ import (
"net/url"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/auth"
@@ -58,7 +59,7 @@ func (s *Session) Authenticate(ctx context.Context, r *authn.Request) (*authn.Id
}
ident := &authn.Identity{
ID: identity.NewTypedID(identity.TypeUser, token.UserId),
ID: identity.NewTypedID(claims.TypeUser, token.UserId),
SessionToken: token,
ClientParams: authn.ClientParams{
FetchSyncedUser: true,
+7 -7
View File
@@ -99,7 +99,7 @@ func (i *Identity) GetInternalID() (int64, error) {
}
// GetIdentityType implements Requester.
func (i *Identity) GetIdentityType() identity.IdentityType {
func (i *Identity) GetIdentityType() claims.IdentityType {
return i.UID.Type()
}
@@ -243,9 +243,9 @@ func (i *Identity) HasRole(role org.RoleType) bool {
func (i *Identity) HasUniqueId() bool {
typ := i.GetID().Type()
return typ == identity.TypeUser ||
typ == identity.TypeServiceAccount ||
typ == identity.TypeAPIKey
return typ == claims.TypeUser ||
typ == claims.TypeServiceAccount ||
typ == claims.TypeAPIKey
}
func (i *Identity) IsAuthenticatedBy(providers ...string) bool {
@@ -273,7 +273,7 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
AuthID: i.AuthID,
AuthenticatedBy: i.AuthenticatedBy,
IsGrafanaAdmin: i.GetIsGrafanaAdmin(),
IsAnonymous: i.ID.IsType(identity.TypeAnonymous),
IsAnonymous: i.ID.IsType(claims.TypeAnonymous),
IsDisabled: i.IsDisabled,
HelpFlags1: i.HelpFlags1,
LastSeenAt: i.LastSeenAt,
@@ -283,14 +283,14 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
FallbackType: i.ID.Type(),
}
if i.ID.IsType(identity.TypeAPIKey) {
if i.ID.IsType(claims.TypeAPIKey) {
id, _ := i.ID.ParseInt()
u.ApiKeyID = id
} else {
id, _ := i.ID.UserID()
u.UserID = id
u.UserUID = i.UID.ID()
u.IsServiceAccount = i.ID.IsType(identity.TypeServiceAccount)
u.IsServiceAccount = i.ID.IsType(claims.TypeServiceAccount)
}
return u
@@ -9,6 +9,7 @@ import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/authlib/claims"
authnClients "github.com/grafana/grafana/pkg/services/authn/clients"
"github.com/grafana/grafana/pkg/api/response"
@@ -157,9 +158,9 @@ func (h *ContextHandler) addIDHeaderEndOfRequestFunc(ident identity.Requester) w
id := ident.GetID()
if !identity.IsIdentityType(
id,
identity.TypeUser,
identity.TypeServiceAccount,
identity.TypeAPIKey,
claims.TypeUser,
claims.TypeServiceAccount,
claims.TypeAPIKey,
) || id.ID() == "0" {
return
}
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/tracing"
@@ -43,7 +44,7 @@ func TestContextHandler(t *testing.T) {
})
t.Run("should set identity on successful authentication", func(t *testing.T) {
id := &authn.Identity{ID: identity.NewTypedID(identity.TypeUser, 1), OrgID: 1}
id := &authn.Identity{ID: identity.NewTypedID(claims.TypeUser, 1), OrgID: 1}
handler := contexthandler.ProvideService(
setting.NewCfg(),
tracing.InitializeTracerForTest(),
+2 -2
View File
@@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/metrics"
@@ -879,7 +879,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F
}
// only list k6 folders when requested by a service account - prevents showing k6 folders in the UI for users
if query.SignedInUser == nil || query.SignedInUser.GetID().Type() != identity.TypeServiceAccount {
if query.SignedInUser == nil || query.SignedInUser.GetID().Type() != claims.TypeServiceAccount {
filters = append(filters, searchstore.K6FolderFilter{})
}
@@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/exp/slices"
@@ -492,7 +493,7 @@ func (dr *DashboardServiceImpl) setDefaultPermissions(ctx context.Context, dto *
userID, err := identity.IntIdentifier(dto.User.GetID())
if err != nil {
dr.log.Error("Could not make user admin", "dashboard", dash.Title, "id", dto.User.GetID(), "error", err)
} else if identity.IsIdentityType(dto.User.GetID(), identity.TypeUser) {
} else if identity.IsIdentityType(dto.User.GetID(), claims.TypeUser) {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
})
@@ -528,7 +529,7 @@ func (dr *DashboardServiceImpl) setDefaultFolderPermissions(ctx context.Context,
userID, err := identity.IntIdentifier(cmd.SignedInUser.GetID())
if err != nil {
dr.log.Error("Could not make user admin", "folder", cmd.Title, "id", cmd.SignedInUser.GetID())
} else if identity.IsIdentityType(cmd.SignedInUser.GetID(), identity.TypeUser) {
} else if identity.IsIdentityType(cmd.SignedInUser.GetID(), claims.TypeUser) {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
})
@@ -4,6 +4,7 @@ import (
"context"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db"
@@ -123,7 +124,7 @@ func (d *DashboardSnapshotStore) SearchDashboardSnapshots(ctx context.Context, q
}
var userID int64
if identity.IsIdentityType(query.SignedInUser.GetID(), identity.TypeUser, identity.TypeServiceAccount) {
if identity.IsIdentityType(query.SignedInUser.GetID(), claims.TypeUser, claims.TypeServiceAccount) {
var err error
userID, err = identity.UserIdentifier(query.SignedInUser.GetID())
if err != nil {
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"strings"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/dskit/concurrency"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/metrics"
@@ -323,7 +323,7 @@ func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetChildrenQuery)
}
// only list k6 folders when requested by a service account - prevents showing k6 folders in the UI for users
if q.SignedInUser == nil || q.SignedInUser.GetID().Type() != identity.TypeServiceAccount {
if q.SignedInUser == nil || q.SignedInUser.GetID().Type() != claims.TypeServiceAccount {
sql.WriteString(" AND uid != ?")
args = append(args, accesscontrol.K6FolderUID)
}
@@ -484,7 +484,7 @@ func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folde
}
// only list k6 folders when requested by a service account - prevents showing k6 folders in the UI for users
if q.SignedInUser == nil || q.SignedInUser.GetID().Type() != identity.TypeServiceAccount {
if q.SignedInUser == nil || q.SignedInUser.GetID().Type() != claims.TypeServiceAccount {
s.WriteString(" AND f0.uid != ? AND (f0.parent_uid != ? OR f0.parent_uid IS NULL)")
args = append(args, accesscontrol.K6FolderUID, accesscontrol.K6FolderUID)
}
+3 -2
View File
@@ -12,6 +12,7 @@ import (
"golang.org/x/oauth2"
"golang.org/x/sync/singleflight"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
@@ -94,7 +95,7 @@ func (o *Service) HasOAuthEntry(ctx context.Context, usr identity.Requester) (*l
return nil, false, nil
}
if !identity.IsIdentityType(usr.GetID(), identity.TypeUser) {
if !identity.IsIdentityType(usr.GetID(), claims.TypeUser) {
return nil, false, nil
}
@@ -135,7 +136,7 @@ func (o *Service) TryTokenRefresh(ctx context.Context, usr identity.Requester) e
return nil
}
if !identity.IsIdentityType(usr.GetID(), identity.TypeUser) {
if !identity.IsIdentityType(usr.GetID(), claims.TypeUser) {
ctxLogger.Warn("Can only refresh OAuth tokens for users", "id", usr.GetID())
return nil
}
@@ -3,6 +3,7 @@ package clientmiddleware
import (
"context"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/apimachinery/identity"
@@ -35,7 +36,7 @@ func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.Fo
}
h.DeleteHTTPHeader(proxyutil.UserHeaderName)
if !identity.IsIdentityType(reqCtx.SignedInUser.GetID(), identity.TypeAnonymous) {
if !identity.IsIdentityType(reqCtx.SignedInUser.GetID(), claims.TypeAnonymous) {
h.SetHTTPHeader(proxyutil.UserHeaderName, reqCtx.SignedInUser.GetLogin())
}
}
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"net/http"
"strconv"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
@@ -99,7 +100,7 @@ func (api *ServiceAccountsAPI) CreateServiceAccount(c *contextmodel.ReqContext)
}
if api.cfg.RBAC.PermissionsOnCreation("service-account") {
if identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
if identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
userID, err := c.SignedInUser.GetID().ParseInt()
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to parse user id", err)
+2 -2
View File
@@ -5,9 +5,9 @@ import (
"net/http"
"strconv"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
@@ -51,7 +51,7 @@ func (tapi *TeamAPI) createTeam(c *contextmodel.ReqContext) response.Response {
// an additional check whether it is an actual user is required
namespace, identifier := c.SignedInUser.GetID().Type(), c.SignedInUser.GetID().ID()
switch namespace {
case identity.TypeUser:
case claims.TypeUser:
userID, err := strconv.ParseInt(identifier, 10, 64)
if err != nil {
c.Logger.Error("Could not add creator to team because user id is not a number", "error", err)
+13 -13
View File
@@ -50,7 +50,7 @@ type SignedInUser struct {
IDTokenClaims *authnlib.Claims[authnlib.IDTokenClaims] `json:"-" xorm:"-"`
// When other settings are not deterministic, this value is used
FallbackType identity.IdentityType
FallbackType claims.IdentityType
}
// Access implements claims.AuthInfo.
@@ -89,18 +89,18 @@ func (u *SignedInUser) GetInternalID() (int64, error) {
}
// GetIdentityType implements Requester.
func (u *SignedInUser) GetIdentityType() identity.IdentityType {
func (u *SignedInUser) GetIdentityType() claims.IdentityType {
switch {
case u.ApiKeyID != 0:
return identity.TypeAPIKey
return claims.TypeAPIKey
case u.IsServiceAccount:
return identity.TypeServiceAccount
return claims.TypeServiceAccount
case u.UserID > 0:
return identity.TypeUser
return claims.TypeUser
case u.IsAnonymous:
return identity.TypeAnonymous
return claims.TypeAnonymous
case u.AuthenticatedBy == "render" && u.UserID == 0:
return identity.TypeRenderService
return claims.TypeRenderService
}
return u.FallbackType
}
@@ -263,18 +263,18 @@ func (u *SignedInUser) GetID() identity.TypedID {
return identity.NewTypedIDString(ns, id)
}
func (u *SignedInUser) getTypeAndID() (identity.IdentityType, string) {
func (u *SignedInUser) getTypeAndID() (claims.IdentityType, string) {
switch {
case u.ApiKeyID != 0:
return identity.TypeAPIKey, strconv.FormatInt(u.ApiKeyID, 10)
return claims.TypeAPIKey, strconv.FormatInt(u.ApiKeyID, 10)
case u.IsServiceAccount:
return identity.TypeServiceAccount, strconv.FormatInt(u.UserID, 10)
return claims.TypeServiceAccount, strconv.FormatInt(u.UserID, 10)
case u.UserID > 0:
return identity.TypeUser, strconv.FormatInt(u.UserID, 10)
return claims.TypeUser, strconv.FormatInt(u.UserID, 10)
case u.IsAnonymous:
return identity.TypeAnonymous, "0"
return claims.TypeAnonymous, "0"
case u.AuthenticatedBy == "render" && u.UserID == 0:
return identity.TypeRenderService, "0"
return claims.TypeRenderService, "0"
}
return u.FallbackType, strconv.FormatInt(u.UserID, 10)
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"net/mail"
"time"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/auth"
@@ -153,6 +154,6 @@ func (s *Verifier) Complete(ctx context.Context, cmd user.CompleteEmailVerifyCom
// remove the current token, so a new one can be generated with correct values.
return s.is.RemoveIDToken(
ctx,
&authn.Identity{ID: identity.NewTypedID(identity.TypeUser, usr.ID), OrgID: usr.OrgID},
&authn.Identity{ID: identity.NewTypedID(claims.TypeUser, usr.ID), OrgID: usr.OrgID},
)
}