mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AuthN: Implement requester interface for identity (#75618)
* AuthN: Implement identity.Requester interface for authn.Identity * AuthN: Replace OrgRole with GetOrgRole * IDForwarding: skip converting to SignedInUser * Pass identity directly in permission sync hook
This commit is contained in:
parent
2fe4ecde19
commit
fd2235b5ad
@ -62,7 +62,7 @@ func TestAnonymous_Authenticate(t *testing.T) {
|
|||||||
assert.Equal(t, true, identity.ID == "")
|
assert.Equal(t, true, identity.ID == "")
|
||||||
assert.Equal(t, tt.org.ID, identity.OrgID)
|
assert.Equal(t, tt.org.ID, identity.OrgID)
|
||||||
assert.Equal(t, tt.org.Name, identity.OrgName)
|
assert.Equal(t, tt.org.Name, identity.OrgName)
|
||||||
assert.Equal(t, tt.cfg.AnonymousOrgRole, string(identity.Role()))
|
assert.Equal(t, tt.cfg.AnonymousOrgRole, string(identity.GetOrgRole()))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -80,9 +80,8 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
||||||
// FIXME(kalleep): implement identity.Requester for authn.Identity
|
|
||||||
// FIXME(kalleep): we should probably lazy load this
|
// FIXME(kalleep): we should probably lazy load this
|
||||||
token, err := s.SignIdentity(ctx, identity.SignedInUser())
|
token, err := s.SignIdentity(ctx, identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
namespace, id := identity.NamespacedID()
|
namespace, id := identity.NamespacedID()
|
||||||
s.logger.Error("Failed to sign id token", "err", err, "namespace", namespace, "id", id)
|
s.logger.Error("Failed to sign id token", "err", err, "namespace", namespace, "id", id)
|
||||||
|
@ -30,8 +30,7 @@ func (s *PermissionsSync) SyncPermissionsHook(ctx context.Context, identity *aut
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions, err := s.ac.GetUserPermissions(ctx, identity.SignedInUser(),
|
permissions, err := s.ac.GetUserPermissions(ctx, identity, accesscontrol.Options{ReloadCache: false})
|
||||||
accesscontrol.Options{ReloadCache: false})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.FromContext(ctx).Error("Failed to fetch permissions from db", "error", err, "user_id", identity.ID)
|
s.log.FromContext(ctx).Error("Failed to fetch permissions from db", "error", err, "user_id", identity.ID)
|
||||||
return errSyncPermissionsForbidden
|
return errSyncPermissionsForbidden
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/models/roletype"
|
||||||
"github.com/grafana/grafana/pkg/models/usertoken"
|
"github.com/grafana/grafana/pkg/models/usertoken"
|
||||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||||
"github.com/grafana/grafana/pkg/services/login"
|
"github.com/grafana/grafana/pkg/services/login"
|
||||||
@ -28,6 +29,8 @@ const (
|
|||||||
NamespaceRenderService = identity.NamespaceRenderService
|
NamespaceRenderService = identity.NamespaceRenderService
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ identity.Requester = (*Identity)(nil)
|
||||||
|
|
||||||
type Identity struct {
|
type Identity struct {
|
||||||
// OrgID is the active organization for the entity.
|
// OrgID is the active organization for the entity.
|
||||||
OrgID int64
|
OrgID int64
|
||||||
@ -81,12 +84,107 @@ type Identity struct {
|
|||||||
IDToken string
|
IDToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Role returns the role of the identity in the active organization.
|
func (i *Identity) GetAuthenticatedBy() string {
|
||||||
func (i *Identity) Role() org.RoleType {
|
return i.AuthenticatedBy
|
||||||
return i.OrgRoles[i.OrgID]
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetCacheKey() string {
|
||||||
|
namespace, id := i.GetNamespacedID()
|
||||||
|
if !i.HasUniqueId() {
|
||||||
|
// Hack use the org role as id for identities that do not have a unique id
|
||||||
|
// e.g. anonymous and render key.
|
||||||
|
id = string(i.GetOrgRole())
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d-%s-%s", i.GetOrgID(), namespace, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetDisplayName() string {
|
||||||
|
return i.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetEmail() string {
|
||||||
|
return i.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetIDToken() string {
|
||||||
|
return i.IDToken
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetIsGrafanaAdmin() bool {
|
||||||
|
return i.IsGrafanaAdmin != nil && *i.IsGrafanaAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetLogin() string {
|
||||||
|
return i.Login
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetNamespacedID() (namespace string, identifier string) {
|
||||||
|
split := strings.Split(i.ID, ":")
|
||||||
|
|
||||||
|
if len(split) != 2 {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return split[0], split[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgID implements identity.Requester.
|
||||||
|
func (i *Identity) GetOrgID() int64 {
|
||||||
|
return i.OrgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetOrgName() string {
|
||||||
|
return i.OrgName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetOrgRole() roletype.RoleType {
|
||||||
|
if i.OrgRoles == nil {
|
||||||
|
return roletype.RoleNone
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.OrgRoles[i.GetOrgID()] == "" {
|
||||||
|
return roletype.RoleNone
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.OrgRoles[i.GetOrgID()]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetPermissions() map[string][]string {
|
||||||
|
if i.Permissions == nil {
|
||||||
|
return make(map[string][]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Permissions[i.GetOrgID()] == nil {
|
||||||
|
return make(map[string][]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.Permissions[i.GetOrgID()]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) GetTeams() []int64 {
|
||||||
|
return i.Teams
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) HasRole(role roletype.RoleType) bool {
|
||||||
|
if i.GetIsGrafanaAdmin() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.GetOrgRole().Includes(role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) HasUniqueId() bool {
|
||||||
|
namespace, _ := i.GetNamespacedID()
|
||||||
|
return namespace == NamespaceUser || namespace == NamespaceServiceAccount || namespace == NamespaceAPIKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Identity) IsNil() bool {
|
||||||
|
return i == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespacedID returns the namespace, e.g. "user" and the id for that namespace
|
// NamespacedID returns the namespace, e.g. "user" and the id for that namespace
|
||||||
|
// FIXME(kalleep): Replace with GetNamespacedID
|
||||||
func (i *Identity) NamespacedID() (string, int64) {
|
func (i *Identity) NamespacedID() (string, int64) {
|
||||||
split := strings.Split(i.ID, ":")
|
split := strings.Split(i.ID, ":")
|
||||||
if len(split) != 2 {
|
if len(split) != 2 {
|
||||||
@ -104,21 +202,15 @@ func (i *Identity) NamespacedID() (string, int64) {
|
|||||||
|
|
||||||
// SignedInUser returns a SignedInUser from the identity.
|
// SignedInUser returns a SignedInUser from the identity.
|
||||||
func (i *Identity) SignedInUser() *user.SignedInUser {
|
func (i *Identity) SignedInUser() *user.SignedInUser {
|
||||||
var isGrafanaAdmin bool
|
|
||||||
if i.IsGrafanaAdmin != nil {
|
|
||||||
isGrafanaAdmin = *i.IsGrafanaAdmin
|
|
||||||
}
|
|
||||||
|
|
||||||
u := &user.SignedInUser{
|
u := &user.SignedInUser{
|
||||||
UserID: 0,
|
|
||||||
OrgID: i.OrgID,
|
OrgID: i.OrgID,
|
||||||
OrgName: i.OrgName,
|
OrgName: i.OrgName,
|
||||||
OrgRole: i.Role(),
|
OrgRole: i.GetOrgRole(),
|
||||||
Login: i.Login,
|
Login: i.Login,
|
||||||
Name: i.Name,
|
Name: i.Name,
|
||||||
Email: i.Email,
|
Email: i.Email,
|
||||||
AuthenticatedBy: i.AuthenticatedBy,
|
AuthenticatedBy: i.AuthenticatedBy,
|
||||||
IsGrafanaAdmin: isGrafanaAdmin,
|
IsGrafanaAdmin: i.GetIsGrafanaAdmin(),
|
||||||
IsAnonymous: i.IsAnonymous,
|
IsAnonymous: i.IsAnonymous,
|
||||||
IsDisabled: i.IsDisabled,
|
IsDisabled: i.IsDisabled,
|
||||||
HelpFlags1: i.HelpFlags1,
|
HelpFlags1: i.HelpFlags1,
|
||||||
@ -128,24 +220,34 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
|
|||||||
IDToken: i.IDToken,
|
IDToken: i.IDToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, id := i.NamespacedID()
|
namespace, id := i.GetNamespacedID()
|
||||||
if namespace == NamespaceAPIKey {
|
if namespace == NamespaceAPIKey {
|
||||||
u.ApiKeyID = id
|
u.ApiKeyID = intIdentifier(id)
|
||||||
} else {
|
} else {
|
||||||
u.UserID = id
|
u.UserID = intIdentifier(id)
|
||||||
u.IsServiceAccount = namespace == NamespaceServiceAccount
|
u.IsServiceAccount = namespace == NamespaceServiceAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func intIdentifier(identifier string) int64 {
|
||||||
|
id, err := strconv.ParseInt(identifier, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
// FIXME (kalleep): Improve error handling
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Identity) ExternalUserInfo() login.ExternalUserInfo {
|
func (i *Identity) ExternalUserInfo() login.ExternalUserInfo {
|
||||||
_, id := i.NamespacedID()
|
_, id := i.GetNamespacedID()
|
||||||
return login.ExternalUserInfo{
|
return login.ExternalUserInfo{
|
||||||
OAuthToken: i.OAuthToken,
|
OAuthToken: i.OAuthToken,
|
||||||
AuthModule: i.AuthenticatedBy,
|
AuthModule: i.AuthenticatedBy,
|
||||||
AuthId: i.AuthID,
|
AuthId: i.AuthID,
|
||||||
UserId: id,
|
UserId: intIdentifier(id),
|
||||||
Email: i.Email,
|
Email: i.Email,
|
||||||
Login: i.Login,
|
Login: i.Login,
|
||||||
Name: i.Name,
|
Name: i.Name,
|
||||||
|
Loading…
Reference in New Issue
Block a user