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, tt.org.ID, identity.OrgID)
|
||||
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 {
|
||||
// FIXME(kalleep): implement identity.Requester for authn.Identity
|
||||
// FIXME(kalleep): we should probably lazy load this
|
||||
token, err := s.SignIdentity(ctx, identity.SignedInUser())
|
||||
token, err := s.SignIdentity(ctx, identity)
|
||||
if err != nil {
|
||||
namespace, id := identity.NamespacedID()
|
||||
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
|
||||
}
|
||||
|
||||
permissions, err := s.ac.GetUserPermissions(ctx, identity.SignedInUser(),
|
||||
accesscontrol.Options{ReloadCache: false})
|
||||
permissions, err := s.ac.GetUserPermissions(ctx, identity, accesscontrol.Options{ReloadCache: false})
|
||||
if err != nil {
|
||||
s.log.FromContext(ctx).Error("Failed to fetch permissions from db", "error", err, "user_id", identity.ID)
|
||||
return errSyncPermissionsForbidden
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models/roletype"
|
||||
"github.com/grafana/grafana/pkg/models/usertoken"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
@ -28,6 +29,8 @@ const (
|
||||
NamespaceRenderService = identity.NamespaceRenderService
|
||||
)
|
||||
|
||||
var _ identity.Requester = (*Identity)(nil)
|
||||
|
||||
type Identity struct {
|
||||
// OrgID is the active organization for the entity.
|
||||
OrgID int64
|
||||
@ -81,12 +84,107 @@ type Identity struct {
|
||||
IDToken string
|
||||
}
|
||||
|
||||
// Role returns the role of the identity in the active organization.
|
||||
func (i *Identity) Role() org.RoleType {
|
||||
return i.OrgRoles[i.OrgID]
|
||||
func (i *Identity) GetAuthenticatedBy() string {
|
||||
return i.AuthenticatedBy
|
||||
}
|
||||
|
||||
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
|
||||
// FIXME(kalleep): Replace with GetNamespacedID
|
||||
func (i *Identity) NamespacedID() (string, int64) {
|
||||
split := strings.Split(i.ID, ":")
|
||||
if len(split) != 2 {
|
||||
@ -104,21 +202,15 @@ func (i *Identity) NamespacedID() (string, int64) {
|
||||
|
||||
// SignedInUser returns a SignedInUser from the identity.
|
||||
func (i *Identity) SignedInUser() *user.SignedInUser {
|
||||
var isGrafanaAdmin bool
|
||||
if i.IsGrafanaAdmin != nil {
|
||||
isGrafanaAdmin = *i.IsGrafanaAdmin
|
||||
}
|
||||
|
||||
u := &user.SignedInUser{
|
||||
UserID: 0,
|
||||
OrgID: i.OrgID,
|
||||
OrgName: i.OrgName,
|
||||
OrgRole: i.Role(),
|
||||
OrgRole: i.GetOrgRole(),
|
||||
Login: i.Login,
|
||||
Name: i.Name,
|
||||
Email: i.Email,
|
||||
AuthenticatedBy: i.AuthenticatedBy,
|
||||
IsGrafanaAdmin: isGrafanaAdmin,
|
||||
IsGrafanaAdmin: i.GetIsGrafanaAdmin(),
|
||||
IsAnonymous: i.IsAnonymous,
|
||||
IsDisabled: i.IsDisabled,
|
||||
HelpFlags1: i.HelpFlags1,
|
||||
@ -128,24 +220,34 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
|
||||
IDToken: i.IDToken,
|
||||
}
|
||||
|
||||
namespace, id := i.NamespacedID()
|
||||
namespace, id := i.GetNamespacedID()
|
||||
if namespace == NamespaceAPIKey {
|
||||
u.ApiKeyID = id
|
||||
u.ApiKeyID = intIdentifier(id)
|
||||
} else {
|
||||
u.UserID = id
|
||||
u.UserID = intIdentifier(id)
|
||||
u.IsServiceAccount = namespace == NamespaceServiceAccount
|
||||
}
|
||||
|
||||
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 {
|
||||
_, id := i.NamespacedID()
|
||||
_, id := i.GetNamespacedID()
|
||||
return login.ExternalUserInfo{
|
||||
OAuthToken: i.OAuthToken,
|
||||
AuthModule: i.AuthenticatedBy,
|
||||
AuthId: i.AuthID,
|
||||
UserId: id,
|
||||
UserId: intIdentifier(id),
|
||||
Email: i.Email,
|
||||
Login: i.Login,
|
||||
Name: i.Name,
|
||||
|
Loading…
Reference in New Issue
Block a user