mirror of
https://github.com/grafana/grafana.git
synced 2025-01-11 16:42:15 -06:00
Authn: Always set namespace (#96230)
* Rename from AllowedKubernetesNamespace to Namespace * Use a sync hook to always set namespace for Identity. * format * Don't set uid when authenticating as user
This commit is contained in:
parent
7eb4b974e0
commit
8d74296b6c
@ -52,9 +52,9 @@ type Requester interface {
|
||||
GetOrgName() string
|
||||
// GetAuthID returns external id for entity.
|
||||
GetAuthID() string
|
||||
// GetAllowedKubernetesNamespace returns either "*" or the single namespace this requester has access to
|
||||
// GetNamespace returns either "*" or the single namespace this requester has access to
|
||||
// An empty value means the implementation has not specified a kubernetes namespace.
|
||||
GetAllowedKubernetesNamespace() string
|
||||
GetNamespace() string
|
||||
// GetAuthenticatedBy returns the authentication method used to authenticate the entity.
|
||||
GetAuthenticatedBy() string
|
||||
// IsAuthenticatedBy returns true if entity was authenticated by any of supplied providers.
|
||||
|
@ -14,21 +14,21 @@ 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 claims.IdentityType
|
||||
UserID int64
|
||||
UserUID string
|
||||
OrgID int64
|
||||
OrgName string
|
||||
OrgRole RoleType
|
||||
Login string
|
||||
Name string
|
||||
DisplayName string
|
||||
Email string
|
||||
EmailVerified bool
|
||||
AuthID string
|
||||
AuthenticatedBy string
|
||||
AllowedKubernetesNamespace string
|
||||
IsGrafanaAdmin bool
|
||||
Type claims.IdentityType
|
||||
UserID int64
|
||||
UserUID string
|
||||
OrgID int64
|
||||
OrgName string
|
||||
OrgRole RoleType
|
||||
Login string
|
||||
Name string
|
||||
DisplayName string
|
||||
Email string
|
||||
EmailVerified bool
|
||||
AuthID string
|
||||
AuthenticatedBy string
|
||||
Namespace string
|
||||
IsGrafanaAdmin bool
|
||||
// Permissions grouped by orgID and actions
|
||||
Permissions map[int64]map[string][]string
|
||||
IDToken string
|
||||
@ -175,8 +175,8 @@ func (u *StaticRequester) GetAuthID() string {
|
||||
return u.AuthID
|
||||
}
|
||||
|
||||
func (u *StaticRequester) GetAllowedKubernetesNamespace() string {
|
||||
return u.AllowedKubernetesNamespace
|
||||
func (u *StaticRequester) GetNamespace() string {
|
||||
return u.Namespace
|
||||
}
|
||||
|
||||
func (u *StaticRequester) GetAuthenticatedBy() string {
|
||||
|
@ -85,7 +85,7 @@ func (i *IDClaimsWrapper) JTI() string {
|
||||
|
||||
// GetNamespace implements claims.AccessClaims.
|
||||
func (i *IDClaimsWrapper) Namespace() string {
|
||||
return i.Source.GetAllowedKubernetesNamespace()
|
||||
return i.Source.GetNamespace()
|
||||
}
|
||||
|
||||
// GetNotBefore implements claims.AccessClaims.
|
||||
|
@ -45,8 +45,8 @@ func WithRequester(handler http.Handler) http.Handler {
|
||||
Login: info.GetName(),
|
||||
OrgRole: identity.RoleAdmin,
|
||||
|
||||
IsGrafanaAdmin: true,
|
||||
AllowedKubernetesNamespace: "default",
|
||||
IsGrafanaAdmin: true,
|
||||
Namespace: "default",
|
||||
|
||||
Permissions: map[int64]map[string][]string{
|
||||
orgId: {
|
||||
|
@ -119,5 +119,7 @@ func ProvideRegistration(
|
||||
authnSvc.RegisterPostAuthHook(rbacSync.SyncPermissionsHook, 120)
|
||||
authnSvc.RegisterPostLoginHook(orgSync.SetDefaultOrgHook, 140)
|
||||
|
||||
nsSync := sync.ProvideNamespaceSync(cfg)
|
||||
authnSvc.RegisterPostAuthHook(nsSync.SyncNamespace, 150)
|
||||
return Registration{}
|
||||
}
|
||||
|
28
pkg/services/authn/authnimpl/sync/namespace.go
Normal file
28
pkg/services/authn/authnimpl/sync/namespace.go
Normal file
@ -0,0 +1,28 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func ProvideNamespaceSync(cfg *setting.Cfg) *NamespaceSync {
|
||||
return &NamespaceSync{
|
||||
mapper: request.GetNamespaceMapper(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
type NamespaceSync struct {
|
||||
mapper request.NamespaceMapper
|
||||
}
|
||||
|
||||
func (s *NamespaceSync) SyncNamespace(ctx context.Context, id *authn.Identity, _ *authn.Request) error {
|
||||
if id.Namespace != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
id.Namespace = s.mapper(id.OrgID)
|
||||
return nil
|
||||
}
|
@ -129,21 +129,21 @@ func (s *ExtendedJWT) authenticateAsUser(
|
||||
}
|
||||
|
||||
// For use in service layer, allow higher privilege
|
||||
allowedKubernetesNamespace := accessTokenClaims.Rest.Namespace
|
||||
namespace := accessTokenClaims.Rest.Namespace
|
||||
if len(s.cfg.StackID) > 0 {
|
||||
// For single-tenant cloud use, choose the lower of the two (id token will always have the specific namespace)
|
||||
allowedKubernetesNamespace = idTokenClaims.Rest.Namespace
|
||||
namespace = idTokenClaims.Rest.Namespace
|
||||
}
|
||||
|
||||
return &authn.Identity{
|
||||
ID: id,
|
||||
Type: t,
|
||||
OrgID: s.cfg.DefaultOrgID(),
|
||||
AccessTokenClaims: &accessTokenClaims,
|
||||
IDTokenClaims: &idTokenClaims,
|
||||
AuthenticatedBy: login.ExtendedJWTModule,
|
||||
AuthID: accessTokenClaims.Subject,
|
||||
AllowedKubernetesNamespace: allowedKubernetesNamespace,
|
||||
ID: id,
|
||||
Type: t,
|
||||
OrgID: s.cfg.DefaultOrgID(),
|
||||
AccessTokenClaims: &accessTokenClaims,
|
||||
IDTokenClaims: &idTokenClaims,
|
||||
AuthenticatedBy: login.ExtendedJWTModule,
|
||||
AuthID: accessTokenClaims.Subject,
|
||||
Namespace: namespace,
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
FetchPermissionsParams: authn.FetchPermissionsParams{
|
||||
@ -184,15 +184,15 @@ func (s *ExtendedJWT) authenticateAsService(accessTokenClaims authlib.Claims[aut
|
||||
}
|
||||
|
||||
return &authn.Identity{
|
||||
ID: id,
|
||||
UID: id,
|
||||
Name: id,
|
||||
Type: t,
|
||||
OrgID: s.cfg.DefaultOrgID(),
|
||||
AccessTokenClaims: &accessTokenClaims,
|
||||
AuthenticatedBy: login.ExtendedJWTModule,
|
||||
AuthID: accessTokenClaims.Subject,
|
||||
AllowedKubernetesNamespace: accessTokenClaims.Rest.Namespace,
|
||||
ID: id,
|
||||
UID: id,
|
||||
Name: id,
|
||||
Type: t,
|
||||
OrgID: s.cfg.DefaultOrgID(),
|
||||
AccessTokenClaims: &accessTokenClaims,
|
||||
AuthenticatedBy: login.ExtendedJWTModule,
|
||||
AuthID: accessTokenClaims.Subject,
|
||||
Namespace: accessTokenClaims.Rest.Namespace,
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
FetchPermissionsParams: fetchPermissionsParams,
|
||||
|
@ -226,15 +226,15 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
accessToken: &validAccessTokenClaims,
|
||||
orgID: 1,
|
||||
want: &authn.Identity{
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaims,
|
||||
AllowedKubernetesNamespace: "default",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaims,
|
||||
Namespace: "default",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
FetchPermissionsParams: authn.FetchPermissionsParams{Roles: []string{"fixed:folders:reader"}, AllowedActions: []string{"folders:read"}}},
|
||||
@ -245,15 +245,15 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
accessToken: &validAccessTokenClaimsWildcard,
|
||||
orgID: 1,
|
||||
want: &authn.Identity{
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
AllowedKubernetesNamespace: "*",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
Namespace: "*",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
},
|
||||
@ -265,14 +265,14 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
idToken: &validIDTokenClaims,
|
||||
orgID: 1,
|
||||
want: &authn.Identity{
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaims,
|
||||
IDTokenClaims: &validIDTokenClaims,
|
||||
AllowedKubernetesNamespace: "default",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaims,
|
||||
IDTokenClaims: &validIDTokenClaims,
|
||||
Namespace: "default",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
FetchSyncedUser: true,
|
||||
SyncPermissions: true,
|
||||
@ -288,14 +288,14 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
idToken: &validIDTokenClaims,
|
||||
orgID: 1,
|
||||
want: &authn.Identity{
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaims,
|
||||
AllowedKubernetesNamespace: "*",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaims,
|
||||
Namespace: "*",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
FetchSyncedUser: true,
|
||||
SyncPermissions: true,
|
||||
@ -316,14 +316,14 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: &authn.Identity{
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaimsWithStackSet,
|
||||
AllowedKubernetesNamespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaimsWithStackSet,
|
||||
Namespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
FetchSyncedUser: true,
|
||||
SyncPermissions: true,
|
||||
@ -343,15 +343,15 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: &authn.Identity{
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithStackSet,
|
||||
AllowedKubernetesNamespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithStackSet,
|
||||
Namespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
},
|
||||
@ -370,15 +370,15 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: &authn.Identity{
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithDeprecatedStackClaimSet,
|
||||
AllowedKubernetesNamespace: "stack-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "this-uid",
|
||||
UID: "this-uid",
|
||||
Name: "this-uid",
|
||||
Type: claims.TypeAccessPolicy,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithDeprecatedStackClaimSet,
|
||||
Namespace: "stack-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
},
|
||||
@ -398,14 +398,14 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: &authn.Identity{
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithDeprecatedStackClaimSet,
|
||||
IDTokenClaims: &validIDTokenClaimsWithDeprecatedStackClaimSet,
|
||||
AllowedKubernetesNamespace: "stack-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWithDeprecatedStackClaimSet,
|
||||
IDTokenClaims: &validIDTokenClaimsWithDeprecatedStackClaimSet,
|
||||
Namespace: "stack-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
SyncPermissions: true,
|
||||
FetchSyncedUser: true,
|
||||
@ -426,14 +426,14 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: &authn.Identity{
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaimsWithStackSet,
|
||||
AllowedKubernetesNamespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ID: "2",
|
||||
Type: claims.TypeUser,
|
||||
OrgID: 1,
|
||||
AccessTokenClaims: &validAccessTokenClaimsWildcard,
|
||||
IDTokenClaims: &validIDTokenClaimsWithStackSet,
|
||||
Namespace: "stacks-1234",
|
||||
AuthenticatedBy: "extendedjwt",
|
||||
AuthID: "access-policy:this-uid",
|
||||
ClientParams: authn.ClientParams{
|
||||
FetchSyncedUser: true,
|
||||
SyncPermissions: true,
|
||||
|
@ -49,8 +49,8 @@ type Identity struct {
|
||||
// AuthId is the unique identifier for the entity in the external system.
|
||||
// Empty if the identity is provided by Grafana.
|
||||
AuthID string
|
||||
// AllowedKubernetesNamespace
|
||||
AllowedKubernetesNamespace string
|
||||
// Namespace
|
||||
Namespace string
|
||||
// IsDisabled is true if the entity is disabled.
|
||||
IsDisabled bool
|
||||
// HelpFlags1 is the help flags for the entity.
|
||||
@ -189,8 +189,8 @@ func (i *Identity) GetLogin() string {
|
||||
return i.Login
|
||||
}
|
||||
|
||||
func (i *Identity) GetAllowedKubernetesNamespace() string {
|
||||
return i.AllowedKubernetesNamespace
|
||||
func (i *Identity) GetNamespace() string {
|
||||
return i.Namespace
|
||||
}
|
||||
|
||||
func (i *Identity) GetOrgID() int64 {
|
||||
@ -287,6 +287,7 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
|
||||
Permissions: i.Permissions,
|
||||
IDToken: i.IDToken,
|
||||
FallbackType: i.Type,
|
||||
Namespace: i.Namespace,
|
||||
}
|
||||
|
||||
if i.IsIdentityType(claims.TypeAPIKey) {
|
||||
|
@ -30,8 +30,8 @@ type SignedInUser struct {
|
||||
// AuthID will be set if user signed in using external method
|
||||
AuthID string
|
||||
// AuthenticatedBy be set if user signed in using external method
|
||||
AuthenticatedBy string
|
||||
AllowedKubernetesNamespace string
|
||||
AuthenticatedBy string
|
||||
Namespace string
|
||||
|
||||
ApiKeyID int64 `xorm:"api_key_id"`
|
||||
IsServiceAccount bool `xorm:"is_service_account"`
|
||||
@ -173,8 +173,8 @@ func (u *SignedInUser) HasUniqueId() bool {
|
||||
return u.IsRealUser() || u.IsApiKeyUser() || u.IsServiceAccountUser()
|
||||
}
|
||||
|
||||
func (u *SignedInUser) GetAllowedKubernetesNamespace() string {
|
||||
return u.AllowedKubernetesNamespace
|
||||
func (u *SignedInUser) GetNamespace() string {
|
||||
return u.Namespace
|
||||
}
|
||||
|
||||
// GetCacheKey returns a unique key for the entity.
|
||||
|
Loading…
Reference in New Issue
Block a user