mirror of https://github.com/grafana/grafana.git
Auth: use IdentityType from authlib (#91763)
This commit is contained in:
parent
faf7cb9312
commit
21d4a4f49e
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"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"
|
||||
|
@ -366,7 +367,7 @@ func (hs *HTTPServer) AdminLogoutUser(c *contextmodel.ReqContext) response.Respo
|
|||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||
}
|
||||
|
||||
if c.SignedInUser.GetID() == identity.NewTypedID(identity.TypeUser, userID) {
|
||||
if c.SignedInUser.GetID() == identity.NewTypedID(claims.TypeUser, userID) {
|
||||
return response.Error(http.StatusBadRequest, "You cannot logout yourself", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
|
@ -43,7 +44,7 @@ func (hs *HTTPServer) isDashboardStarredByUser(c *contextmodel.ReqContext, dashI
|
|||
return false, nil
|
||||
}
|
||||
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
|
@ -194,7 +195,7 @@ func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int
|
|||
|
||||
var permissions []accesscontrol.SetResourcePermissionCommand
|
||||
|
||||
if identity.IsIdentityType(user.GetID(), identity.TypeUser) {
|
||||
if identity.IsIdentityType(user.GetID(), claims.TypeUser) {
|
||||
userID, err := identity.UserIdentifier(user.GetID())
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/webassets"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
|
@ -170,7 +171,7 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
|
|||
|
||||
func (hs *HTTPServer) buildUserAnalyticsSettings(c *contextmodel.ReqContext) dtos.AnalyticsSettings {
|
||||
// Anonymous users do not have an email or auth info
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return dtos.AnalyticsSettings{Identifier: "@" + hs.Cfg.AppURL}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,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/apimachinery/identity"
|
||||
|
@ -132,7 +133,7 @@ func (hs *HTTPServer) CreateOrg(c *contextmodel.ReqContext) response.Response {
|
|||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return response.Error(http.StatusForbidden, "Only users can create organizations", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/api/datasource"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
|
@ -586,7 +587,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
|||
&contextmodel.ReqContext{
|
||||
SignedInUser: &user.SignedInUser{
|
||||
Login: "test_user",
|
||||
FallbackType: identity.TypeUser,
|
||||
FallbackType: claims.TypeUser,
|
||||
UserID: 1,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
|
@ -79,7 +79,7 @@ func TestPluginProxy(t *testing.T) {
|
|||
&contextmodel.ReqContext{
|
||||
SignedInUser: &user.SignedInUser{
|
||||
Login: "test_user",
|
||||
FallbackType: identity.TypeUser,
|
||||
FallbackType: claims.TypeUser,
|
||||
UserID: 1,
|
||||
},
|
||||
Context: &web.Context{
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
|
@ -31,7 +32,7 @@ import (
|
|||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetSignedInUser(c *contextmodel.ReqContext) response.Response {
|
||||
if !identity.IsIdentityType(c.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.GetID(), claims.TypeUser) {
|
||||
return response.JSON(http.StatusOK, user.UserProfileDTO{
|
||||
IsGrafanaAdmin: c.SignedInUser.GetIsGrafanaAdmin(),
|
||||
OrgID: c.SignedInUser.GetOrgID(),
|
||||
|
@ -277,7 +278,7 @@ func (hs *HTTPServer) handleUpdateUser(ctx context.Context, cmd user.UpdateUserC
|
|||
}
|
||||
|
||||
func (hs *HTTPServer) StartEmailVerificaton(c *contextmodel.ReqContext) response.Response {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return response.Error(http.StatusBadRequest, "Only users can verify their email", nil)
|
||||
}
|
||||
|
||||
|
@ -504,7 +505,7 @@ func (hs *HTTPServer) ChangeActiveOrgAndRedirectToHome(c *contextmodel.ReqContex
|
|||
return
|
||||
}
|
||||
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
c.JsonApiErr(http.StatusForbidden, "Endpoint only available for users", nil)
|
||||
return
|
||||
}
|
||||
|
@ -629,7 +630,7 @@ func (hs *HTTPServer) ClearHelpFlags(c *contextmodel.ReqContext) response.Respon
|
|||
}
|
||||
|
||||
func getUserID(c *contextmodel.ReqContext) (int64, *response.NormalResponse) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return 0, response.Error(http.StatusForbidden, "Endpoint only available for users", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/ua-parser/uap-go/uaparser"
|
||||
|
||||
"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"
|
||||
|
@ -32,7 +33,7 @@ import (
|
|||
// 403: forbiddenError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetUserAuthTokens(c *contextmodel.ReqContext) response.Response {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return response.Error(http.StatusForbidden, "entity not allowed to get tokens", nil)
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ func (hs *HTTPServer) RevokeUserAuthToken(c *contextmodel.ReqContext) response.R
|
|||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), identity.TypeUser) {
|
||||
if !identity.IsIdentityType(c.SignedInUser.GetID(), claims.TypeUser) {
|
||||
return response.Error(http.StatusForbidden, "entity not allowed to revoke tokens", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ type Requester interface {
|
|||
claims.AuthInfo
|
||||
|
||||
// GetIdentityType returns the type for the requester
|
||||
GetIdentityType() IdentityType
|
||||
GetIdentityType() claims.IdentityType
|
||||
// GetRawIdentifier returns only the identifier part of the UID, excluding the type
|
||||
GetRawIdentifier() string
|
||||
// Deprecated: use GetUID instead
|
||||
|
@ -82,7 +82,7 @@ type Requester interface {
|
|||
// Applicable for users, service accounts, api keys and renderer service.
|
||||
// Errors if the identifier is not initialized or if type is not recognized.
|
||||
func IntIdentifier(typedID TypedID) (int64, error) {
|
||||
if IsIdentityType(typedID, TypeUser, TypeAPIKey, TypeServiceAccount, TypeRenderService) {
|
||||
if claims.IsIdentityType(typedID.t, claims.TypeUser, claims.TypeAPIKey, claims.TypeServiceAccount, claims.TypeRenderService) {
|
||||
id, err := strconv.ParseInt(typedID.ID(), 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unrecognized format for valid type %s: %w", typedID.Type(), err)
|
||||
|
@ -107,7 +107,7 @@ func UserIdentifier(typedID TypedID) (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
if IsIdentityType(typedID, TypeUser, TypeServiceAccount) {
|
||||
if claims.IsIdentityType(typedID.t, claims.TypeUser, claims.TypeServiceAccount) {
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ var _ Requester = &StaticRequester{}
|
|||
// This is mostly copied from:
|
||||
// https://github.com/grafana/grafana/blob/v11.0.0/pkg/services/user/identity.go#L16
|
||||
type StaticRequester struct {
|
||||
Type IdentityType
|
||||
Type claims.IdentityType
|
||||
UserID int64
|
||||
UserUID string
|
||||
OrgID int64
|
||||
|
@ -65,7 +65,7 @@ func (u *StaticRequester) GetInternalID() (int64, error) {
|
|||
}
|
||||
|
||||
// GetIdentityType implements Requester.
|
||||
func (u *StaticRequester) GetIdentityType() IdentityType {
|
||||
func (u *StaticRequester) GetIdentityType() claims.IdentityType {
|
||||
return u.Type
|
||||
}
|
||||
|
||||
|
|
|
@ -4,46 +4,12 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
)
|
||||
|
||||
type IdentityType string
|
||||
|
||||
const (
|
||||
TypeUser IdentityType = "user"
|
||||
TypeAPIKey IdentityType = "api-key"
|
||||
TypeServiceAccount IdentityType = "service-account"
|
||||
TypeAnonymous IdentityType = "anonymous"
|
||||
TypeRenderService IdentityType = "render"
|
||||
TypeAccessPolicy IdentityType = "access-policy"
|
||||
TypeProvisioning IdentityType = "provisioning"
|
||||
TypeEmpty IdentityType = ""
|
||||
)
|
||||
|
||||
func (n IdentityType) String() string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
func ParseType(str string) (IdentityType, error) {
|
||||
switch str {
|
||||
case string(TypeUser):
|
||||
return TypeUser, nil
|
||||
case string(TypeAPIKey):
|
||||
return TypeAPIKey, nil
|
||||
case string(TypeServiceAccount):
|
||||
return TypeServiceAccount, nil
|
||||
case string(TypeAnonymous):
|
||||
return TypeAnonymous, nil
|
||||
case string(TypeRenderService):
|
||||
return TypeRenderService, nil
|
||||
case string(TypeAccessPolicy):
|
||||
return TypeAccessPolicy, nil
|
||||
default:
|
||||
return "", ErrInvalidTypedID.Errorf("got invalid identity type %s", str)
|
||||
}
|
||||
}
|
||||
|
||||
// IsIdentityType returns true if typedID matches any expected identity type
|
||||
func IsIdentityType(typedID TypedID, expected ...IdentityType) bool {
|
||||
func IsIdentityType(typedID TypedID, expected ...claims.IdentityType) bool {
|
||||
for _, e := range expected {
|
||||
if typedID.Type() == e {
|
||||
return true
|
||||
|
@ -53,7 +19,7 @@ func IsIdentityType(typedID TypedID, expected ...IdentityType) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
var AnonymousTypedID = NewTypedID(TypeAnonymous, 0)
|
||||
var AnonymousTypedID = NewTypedID(claims.TypeAnonymous, 0)
|
||||
|
||||
func ParseTypedID(str string) (TypedID, error) {
|
||||
var typeID TypedID
|
||||
|
@ -63,7 +29,7 @@ func ParseTypedID(str string) (TypedID, error) {
|
|||
return typeID, ErrInvalidTypedID.Errorf("expected typed id to have 2 parts")
|
||||
}
|
||||
|
||||
t, err := ParseType(parts[0])
|
||||
t, err := claims.ParseType(parts[0])
|
||||
if err != nil {
|
||||
return typeID, err
|
||||
}
|
||||
|
@ -84,7 +50,7 @@ func MustParseTypedID(str string) TypedID {
|
|||
return typeID
|
||||
}
|
||||
|
||||
func NewTypedID(t IdentityType, id int64) TypedID {
|
||||
func NewTypedID(t claims.IdentityType, id int64) TypedID {
|
||||
return TypedID{
|
||||
id: strconv.FormatInt(id, 10),
|
||||
t: t,
|
||||
|
@ -92,7 +58,7 @@ func NewTypedID(t IdentityType, id int64) TypedID {
|
|||
}
|
||||
|
||||
// NewTypedIDString creates a new TypedID with a string id
|
||||
func NewTypedIDString(t IdentityType, id string) TypedID {
|
||||
func NewTypedIDString(t claims.IdentityType, id string) TypedID {
|
||||
return TypedID{
|
||||
id: id,
|
||||
t: t,
|
||||
|
@ -102,7 +68,7 @@ func NewTypedIDString(t IdentityType, id string) TypedID {
|
|||
// FIXME: use this instead of encoded string through the codebase
|
||||
type TypedID struct {
|
||||
id string
|
||||
t IdentityType
|
||||
t claims.IdentityType
|
||||
}
|
||||
|
||||
func (ni TypedID) ID() string {
|
||||
|
@ -112,7 +78,7 @@ func (ni TypedID) ID() string {
|
|||
// UserID will try to parse and int64 identifier if namespace is either user or service-account.
|
||||
// For all other namespaces '0' will be returned.
|
||||
func (ni TypedID) UserID() (int64, error) {
|
||||
if ni.IsType(TypeUser, TypeServiceAccount) {
|
||||
if ni.IsType(claims.TypeUser, claims.TypeServiceAccount) {
|
||||
return ni.ParseInt()
|
||||
}
|
||||
return 0, nil
|
||||
|
@ -123,11 +89,11 @@ func (ni TypedID) ParseInt() (int64, error) {
|
|||
return strconv.ParseInt(ni.id, 10, 64)
|
||||
}
|
||||
|
||||
func (ni TypedID) Type() IdentityType {
|
||||
func (ni TypedID) Type() claims.IdentityType {
|
||||
return ni.t
|
||||
}
|
||||
|
||||
func (ni TypedID) IsType(expected ...IdentityType) bool {
|
||||
func (ni TypedID) IsType(expected ...claims.IdentityType) bool {
|
||||
return IsIdentityType(ni, expected...)
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ func (i *IDClaimsWrapper) EmailVerified() bool {
|
|||
|
||||
// GetIdentityType implements claims.IdentityClaims.
|
||||
func (i *IDClaimsWrapper) IdentityType() claims.IdentityType {
|
||||
return claims.IdentityType(i.Source.GetIdentityType())
|
||||
return i.Source.GetIdentityType()
|
||||
}
|
||||
|
||||
// GetInternalID implements claims.IdentityClaims.
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
)
|
||||
|
||||
|
@ -26,7 +27,7 @@ func WithRequester(handler http.Handler) http.Handler {
|
|||
if ok {
|
||||
if info.GetName() == user.Anonymous {
|
||||
requester = &identity.StaticRequester{
|
||||
Type: identity.TypeAnonymous,
|
||||
Type: claims.TypeAnonymous,
|
||||
Name: info.GetName(),
|
||||
Login: info.GetName(),
|
||||
Permissions: map[int64]map[string][]string{},
|
||||
|
@ -37,7 +38,7 @@ func WithRequester(handler http.Handler) http.Handler {
|
|||
slices.Contains(info.GetGroups(), user.SystemPrivilegedGroup) {
|
||||
orgId := int64(1)
|
||||
requester = &identity.StaticRequester{
|
||||
Type: identity.TypeServiceAccount, // system:apiserver
|
||||
Type: claims.TypeServiceAccount, // system:apiserver
|
||||
UserID: 1,
|
||||
OrgID: orgId,
|
||||
Name: info.GetName(),
|
||||
|
|
|
@ -4,6 +4,7 @@ go 1.22.4
|
|||
|
||||
require (
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
|
|
|
@ -77,6 +77,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06 h1:uD1LcKwvEAqzDsgVChBudPqo5BhPxkj9AgylT5QCReo=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1 h1:ItDcDxUjVLPKja+hogpqgW/kj8LxUL2qscelXIsN1Bs=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1/go.mod h1:DkxMin+qOh1Fgkxfbt+CUfBqqsCQJMG9op8Os/irBPA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
dashboardsV0 "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
||||
|
@ -338,10 +339,10 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows) (*dashboardRow, error) {
|
|||
|
||||
func getUserID(v sql.NullString, id sql.NullInt64) string {
|
||||
if v.Valid && v.String != "" {
|
||||
return identity.NewTypedIDString(identity.TypeUser, v.String).String()
|
||||
return identity.NewTypedIDString(claims.TypeUser, v.String).String()
|
||||
}
|
||||
if id.Valid && id.Int64 == -1 {
|
||||
return identity.NewTypedIDString(identity.TypeProvisioning, "").String()
|
||||
return identity.NewTypedIDString(claims.TypeProvisioning, "").String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
||||
|
@ -86,7 +87,7 @@ func (r *DTOConnector) Connect(ctx context.Context, name string, opts runtime.Ob
|
|||
access.CanSave, _ = guardian.CanSave()
|
||||
access.CanAdmin, _ = guardian.CanAdmin()
|
||||
access.CanDelete, _ = guardian.CanDelete()
|
||||
access.CanStar = user.GetID().Type() == identity.TypeUser // not anon
|
||||
access.CanStar = user.GetID().Type() == claims.TypeUser // not anon
|
||||
|
||||
access.AnnotationsPermissions = &dashboard.AnnotationPermission{}
|
||||
r.getAnnotationPermissionsByScope(ctx, user, &access.AnnotationsPermissions.Dashboard, accesscontrol.ScopeAnnotationsTypeDashboard)
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
},
|
||||
|
|
|
@ -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},
|
||||
},
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
storagetesting "github.com/grafana/grafana/pkg/apiserver/storage/testing"
|
||||
)
|
||||
|
@ -32,7 +33,7 @@ func init() {
|
|||
// Make sure there is a user in every context
|
||||
storagetesting.NewContext = func() context.Context {
|
||||
testUserA := &identity.StaticRequester{
|
||||
Type: identity.TypeUser,
|
||||
Type: claims.TypeUser,
|
||||
Login: "testuser",
|
||||
UserID: 123,
|
||||
UserUID: "u123",
|
||||
|
|
|
@ -5,6 +5,7 @@ go 1.22.4
|
|||
require (
|
||||
github.com/fullstorydev/grpchan v1.1.1
|
||||
github.com/grafana/authlib v0.0.0-20240730122259-a0d13672efb1
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808164224-787abccfbc9e
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
|
|
|
@ -349,6 +349,8 @@ github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBH
|
|||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/authlib v0.0.0-20240730122259-a0d13672efb1 h1:EiaupmOnt6XF/LPxvagjTofWmByzYaf5VyMIF+w/71M=
|
||||
github.com/grafana/authlib v0.0.0-20240730122259-a0d13672efb1/go.mod h1:YA9We4kTafu7mlMnUh3In6Q2wpg8fYN3ycgCKOK1TB8=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06 h1:uD1LcKwvEAqzDsgVChBudPqo5BhPxkj9AgylT5QCReo=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240809101159-74eaccc31a06/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808164224-787abccfbc9e h1:3vNpomyzv714Hgls5vn+fC0vgv8wUOSHepUl7PB5nUs=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808164224-787abccfbc9e/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/grafana/authlib/authn"
|
||||
"github.com/grafana/authlib/claims"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
|
@ -76,7 +77,7 @@ func (f *Authenticator) decodeMetadata(ctx context.Context, meta metadata.MD) (i
|
|||
// TODO, remove after this has been deployed to unified storage
|
||||
if getter(mdUserID) == "" {
|
||||
var err error
|
||||
user.Type = identity.TypeUser
|
||||
user.Type = claims.TypeUser
|
||||
user.UserID, err = strconv.ParseInt(getter("grafana-userid"), 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid user id: %w", err)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
)
|
||||
|
||||
|
@ -14,7 +15,7 @@ func TestBasicEncodeDecode(t *testing.T) {
|
|||
UserID: 123,
|
||||
UserUID: "abc",
|
||||
Login: "test",
|
||||
Type: identity.TypeUser,
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 456,
|
||||
OrgName: "org",
|
||||
OrgRole: identity.RoleAdmin,
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
)
|
||||
|
@ -122,7 +123,7 @@ func NewResourceServer(opts ResourceServerOptions) (ResourceServer, error) {
|
|||
// Make this cancelable
|
||||
ctx, cancel := context.WithCancel(identity.WithRequester(context.Background(),
|
||||
&identity.StaticRequester{
|
||||
Type: identity.TypeServiceAccount,
|
||||
Type: claims.TypeServiceAccount,
|
||||
Login: "watcher", // admin user for watch
|
||||
UserID: 1,
|
||||
IsGrafanaAdmin: true,
|
||||
|
|
|
@ -13,13 +13,14 @@ import (
|
|||
"gocloud.dev/blob/memblob"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
)
|
||||
|
||||
func TestSimpleServer(t *testing.T) {
|
||||
testUserA := &identity.StaticRequester{
|
||||
Type: identity.TypeUser,
|
||||
Type: claims.TypeUser,
|
||||
Login: "testuser",
|
||||
UserID: 123,
|
||||
UserUID: "u123",
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/dskit/services"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
infraDB "github.com/grafana/grafana/pkg/infra/db"
|
||||
|
@ -66,7 +67,7 @@ func TestIntegrationBackendHappyPath(t *testing.T) {
|
|||
}
|
||||
|
||||
testUserA := &identity.StaticRequester{
|
||||
Type: identity.TypeUser,
|
||||
Type: claims.TypeUser,
|
||||
Login: "testuser",
|
||||
UserID: 123,
|
||||
UserUID: "u123",
|
||||
|
@ -341,7 +342,7 @@ func TestClientServer(t *testing.T) {
|
|||
|
||||
// Test with an admin identity
|
||||
clientCtx := identity.WithRequester(ctx, &identity.StaticRequester{
|
||||
Type: identity.TypeUser,
|
||||
Type: claims.TypeUser,
|
||||
Login: "testuser",
|
||||
UserID: 123,
|
||||
UserUID: "u123",
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
)
|
||||
|
||||
|
@ -114,7 +115,7 @@ func ApplyUserHeader(sendUserHeader bool, req *http.Request, user identity.Reque
|
|||
return
|
||||
}
|
||||
|
||||
if identity.IsIdentityType(user.GetID(), identity.TypeUser) {
|
||||
if identity.IsIdentityType(user.GetID(), claims.TypeUser) {
|
||||
req.Header.Set(UserHeaderName, user.GetLogin())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
|
@ -175,7 +175,7 @@ func TestApplyUserHeader(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
req.Header.Set("X-Grafana-User", "admin")
|
||||
|
||||
ApplyUserHeader(false, req, &user.SignedInUser{Login: "admin", UserID: 1, FallbackType: identity.TypeUser})
|
||||
ApplyUserHeader(false, req, &user.SignedInUser{Login: "admin", UserID: 1, FallbackType: claims.TypeUser})
|
||||
require.NotContains(t, req.Header, "X-Grafana-User")
|
||||
})
|
||||
|
||||
|
@ -192,7 +192,7 @@ func TestApplyUserHeader(t *testing.T) {
|
|||
req, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
ApplyUserHeader(true, req, &user.SignedInUser{IsAnonymous: true, FallbackType: identity.TypeAnonymous})
|
||||
ApplyUserHeader(true, req, &user.SignedInUser{IsAnonymous: true, FallbackType: claims.TypeAnonymous})
|
||||
require.NotContains(t, req.Header, "X-Grafana-User")
|
||||
})
|
||||
|
||||
|
@ -200,7 +200,7 @@ func TestApplyUserHeader(t *testing.T) {
|
|||
req, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
ApplyUserHeader(true, req, &user.SignedInUser{Login: "admin", UserID: 1, FallbackType: identity.TypeUser})
|
||||
ApplyUserHeader(true, req, &user.SignedInUser{Login: "admin", UserID: 1, FallbackType: claims.TypeUser})
|
||||
require.Equal(t, "admin", req.Header.Get("X-Grafana-User"))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue