mirror of
https://github.com/grafana/grafana.git
synced 2025-01-09 23:53:25 -06:00
Auth: Decouple client and hook registration (#85084)
This commit is contained in:
parent
bdc492b96c
commit
504870f10a
@ -1,30 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
)
|
||||
|
||||
const (
|
||||
ActionRead = "server.usagestats.report:read"
|
||||
)
|
||||
|
||||
var (
|
||||
usagestatsReaderRole = accesscontrol.RoleDTO{
|
||||
Name: "fixed:usagestats:reader",
|
||||
DisplayName: "Usage stats report reader",
|
||||
Description: "View usage statistics report",
|
||||
Group: "Statistics",
|
||||
Permissions: []accesscontrol.Permission{
|
||||
{Action: ActionRead},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func declareFixedRoles(ac accesscontrol.Service) error {
|
||||
usagestatsReader := accesscontrol.RoleRegistration{
|
||||
Role: usagestatsReaderRole,
|
||||
Grants: []string{string(accesscontrol.RoleGrafanaAdmin)},
|
||||
}
|
||||
|
||||
return ac.DeclareFixedRoles(usagestatsReader)
|
||||
}
|
@ -15,7 +15,7 @@ func (uss *UsageStats) registerAPIEndpoints() {
|
||||
authorize := accesscontrol.Middleware(uss.accesscontrol)
|
||||
|
||||
uss.RouteRegister.Group(rootUrl, func(subrouter routing.RouteRegister) {
|
||||
subrouter.Get("/usage-report-preview", authorize(accesscontrol.EvalPermission(ActionRead)), routing.Wrap(uss.getUsageReportPreview))
|
||||
subrouter.Get("/usage-report-preview", authorize(accesscontrol.EvalPermission(accesscontrol.ActionUsageStatsRead)), routing.Wrap(uss.getUsageReportPreview))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/stats"
|
||||
@ -28,13 +29,13 @@ func TestApi_getUsageStats(t *testing.T) {
|
||||
{
|
||||
desc: "expect usage stats",
|
||||
enabled: true,
|
||||
permissions: map[string][]string{ActionRead: {}},
|
||||
permissions: map[string][]string{accesscontrol.ActionUsageStatsRead: {}},
|
||||
expectedStatus: 200,
|
||||
},
|
||||
{
|
||||
desc: "expect usage stat preview still there after disabling",
|
||||
enabled: false,
|
||||
permissions: map[string][]string{ActionRead: {}},
|
||||
permissions: map[string][]string{accesscontrol.ActionUsageStatsRead: {}},
|
||||
expectedStatus: 200,
|
||||
},
|
||||
{
|
||||
|
@ -35,7 +35,6 @@ func ProvideService(cfg *setting.Cfg,
|
||||
routeRegister routing.RouteRegister,
|
||||
tracer tracing.Tracer,
|
||||
accesscontrol ac.AccessControl,
|
||||
accesscontrolService ac.Service,
|
||||
bundleRegistry supportbundles.Service,
|
||||
) (*UsageStats, error) {
|
||||
s := &UsageStats{
|
||||
@ -47,10 +46,6 @@ func ProvideService(cfg *setting.Cfg,
|
||||
accesscontrol: accesscontrol,
|
||||
}
|
||||
|
||||
if err := declareFixedRoles(accesscontrolService); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.registerAPIEndpoints()
|
||||
bundleRegistry.RegisterSupportItemCollector(s.supportBundleCollector())
|
||||
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
@ -248,7 +247,6 @@ func createService(t *testing.T, sqlStore db.DB, withDB bool) *UsageStats {
|
||||
routing.NewRouteRegister(),
|
||||
tracing.InitializeTracerForTest(),
|
||||
acimpl.ProvideAccessControl(cfg),
|
||||
actest.FakeService{},
|
||||
supportbundlestest.NewFakeBundleService(),
|
||||
)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/anonymous/anonimpl"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/authn/authnimpl"
|
||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
||||
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
|
||||
@ -68,7 +69,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
_ *plugindashboardsservice.DashboardUpdater, _ *sanitizer.Provider,
|
||||
_ *grpcserver.HealthService, _ entity.EntityStoreServer, _ *grpcserver.ReflectionService, _ *ldapapi.Service,
|
||||
_ *apiregistry.Service, _ auth.IDService, _ *teamapi.TeamAPI, _ ssosettings.Service,
|
||||
_ cloudmigration.Service,
|
||||
_ cloudmigration.Service, _ authnimpl.Registration,
|
||||
) *BackgroundServiceRegistry {
|
||||
return NewBackgroundServiceRegistry(
|
||||
httpServer,
|
||||
|
@ -356,6 +356,7 @@ var wireBasicSet = wire.NewSet(
|
||||
authnimpl.ProvideService,
|
||||
authnimpl.ProvideIdentitySynchronizer,
|
||||
authnimpl.ProvideAuthnService,
|
||||
authnimpl.ProvideRegistration,
|
||||
supportbundlesimpl.ProvideService,
|
||||
extsvcaccounts.ProvideExtSvcAccountsService,
|
||||
wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)),
|
||||
|
@ -481,6 +481,9 @@ const (
|
||||
ActionLibraryPanelsRead = "library.panels:read"
|
||||
ActionLibraryPanelsWrite = "library.panels:write"
|
||||
ActionLibraryPanelsDelete = "library.panels:delete"
|
||||
|
||||
// Usage stats actions
|
||||
ActionUsageStatsRead = "server.usagestats.report:read"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -280,6 +280,16 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
usagestatsReaderRole = RoleDTO{
|
||||
Name: "fixed:usagestats:reader",
|
||||
DisplayName: "Usage stats report reader",
|
||||
Description: "View usage statistics report",
|
||||
Group: "Statistics",
|
||||
Permissions: []Permission{
|
||||
{Action: ActionUsageStatsRead},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Declare OSS roles to the accesscontrol service
|
||||
@ -320,15 +330,22 @@ func DeclareFixedRoles(service Service, cfg *setting.Cfg) error {
|
||||
Role: generalAuthConfigWriterRole,
|
||||
Grants: []string{RoleGrafanaAdmin},
|
||||
}
|
||||
|
||||
// TODO: Move to own service when implemented
|
||||
authenticationConfigWriter := RoleRegistration{
|
||||
Role: authenticationConfigWriterRole,
|
||||
Grants: []string{RoleGrafanaAdmin},
|
||||
}
|
||||
|
||||
return service.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
|
||||
settingsReader, statsReader, usersReader, usersWriter, authenticationConfigWriter, generalAuthConfigWriter)
|
||||
usageStatsReader := RoleRegistration{
|
||||
Role: usagestatsReaderRole,
|
||||
Grants: []string{RoleGrafanaAdmin},
|
||||
}
|
||||
|
||||
return service.DeclareFixedRoles(
|
||||
ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
|
||||
settingsReader, statsReader, usersReader, usersWriter,
|
||||
authenticationConfigWriter, generalAuthConfigWriter, usageStatsReader,
|
||||
)
|
||||
}
|
||||
|
||||
func ConcatPermissions(permissions ...[]Permission) []Permission {
|
||||
|
116
pkg/services/authn/authnimpl/registration.go
Normal file
116
pkg/services/authn/authnimpl/registration.go
Normal file
@ -0,0 +1,116 @@
|
||||
package authnimpl
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/authn/authnimpl/sync"
|
||||
"github.com/grafana/grafana/pkg/services/authn/clients"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/ldap/service"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/loginattempt"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/signingkeys"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type Registration struct{}
|
||||
|
||||
func ProvideRegistration(
|
||||
cfg *setting.Cfg, authnSvc authn.Service,
|
||||
orgService org.Service, sessionService auth.UserTokenService,
|
||||
accessControlService accesscontrol.Service,
|
||||
apikeyService apikey.Service, userService user.Service,
|
||||
jwtService auth.JWTVerifierService, userProtectionService login.UserProtectionService,
|
||||
loginAttempts loginattempt.Service, quotaService quota.Service,
|
||||
authInfoService login.AuthInfoService, renderService rendering.Service,
|
||||
features *featuremgmt.FeatureManager, oauthTokenService oauthtoken.OAuthTokenService,
|
||||
socialService social.Service, cache *remotecache.RemoteCache, signingKeysService signingkeys.Service,
|
||||
ldapService service.LDAP, settingsProviderService setting.Provider,
|
||||
) Registration {
|
||||
logger := log.New("authn.registration")
|
||||
|
||||
authnSvc.RegisterClient(clients.ProvideRender(renderService))
|
||||
authnSvc.RegisterClient(clients.ProvideAPIKey(apikeyService))
|
||||
|
||||
if cfg.LoginCookieName != "" {
|
||||
authnSvc.RegisterClient(clients.ProvideSession(cfg, sessionService))
|
||||
}
|
||||
|
||||
var proxyClients []authn.ProxyClient
|
||||
var passwordClients []authn.PasswordClient
|
||||
if cfg.LDAPAuthEnabled {
|
||||
ldap := clients.ProvideLDAP(cfg, ldapService, userService, authInfoService)
|
||||
proxyClients = append(proxyClients, ldap)
|
||||
passwordClients = append(passwordClients, ldap)
|
||||
}
|
||||
|
||||
if !cfg.DisableLogin {
|
||||
grafana := clients.ProvideGrafana(cfg, userService)
|
||||
proxyClients = append(proxyClients, grafana)
|
||||
passwordClients = append(passwordClients, grafana)
|
||||
}
|
||||
|
||||
// if we have password clients configure check if basic auth or form auth is enabled
|
||||
if len(passwordClients) > 0 {
|
||||
passwordClient := clients.ProvidePassword(loginAttempts, passwordClients...)
|
||||
if cfg.BasicAuthEnabled {
|
||||
authnSvc.RegisterClient(clients.ProvideBasic(passwordClient))
|
||||
}
|
||||
|
||||
if !cfg.DisableLoginForm {
|
||||
authnSvc.RegisterClient(clients.ProvideForm(passwordClient))
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.AuthProxy.Enabled && len(proxyClients) > 0 {
|
||||
proxy, err := clients.ProvideProxy(cfg, cache, proxyClients...)
|
||||
if err != nil {
|
||||
logger.Error("Failed to configure auth proxy", "err", err)
|
||||
} else {
|
||||
authnSvc.RegisterClient(proxy)
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.JWTAuth.Enabled {
|
||||
authnSvc.RegisterClient(clients.ProvideJWT(jwtService, cfg))
|
||||
}
|
||||
|
||||
if cfg.ExtJWTAuth.Enabled && features.IsEnabledGlobally(featuremgmt.FlagAuthAPIAccessTokenAuth) {
|
||||
authnSvc.RegisterClient(clients.ProvideExtendedJWT(userService, cfg, signingKeysService))
|
||||
}
|
||||
|
||||
for name := range socialService.GetOAuthProviders() {
|
||||
clientName := authn.ClientWithPrefix(name)
|
||||
authnSvc.RegisterClient(clients.ProvideOAuth(clientName, cfg, oauthTokenService, socialService, settingsProviderService, features))
|
||||
}
|
||||
|
||||
// FIXME (jguer): move to User package
|
||||
userSync := sync.ProvideUserSync(userService, userProtectionService, authInfoService, quotaService)
|
||||
orgSync := sync.ProvideOrgSync(userService, orgService, accessControlService, cfg)
|
||||
authnSvc.RegisterPostAuthHook(userSync.SyncUserHook, 10)
|
||||
authnSvc.RegisterPostAuthHook(userSync.EnableUserHook, 20)
|
||||
authnSvc.RegisterPostAuthHook(orgSync.SyncOrgRolesHook, 30)
|
||||
authnSvc.RegisterPostAuthHook(userSync.SyncLastSeenHook, 130)
|
||||
authnSvc.RegisterPostAuthHook(sync.ProvideOAuthTokenSync(oauthTokenService, sessionService, socialService).SyncOauthTokenHook, 60)
|
||||
authnSvc.RegisterPostAuthHook(userSync.FetchSyncedUserHook, 100)
|
||||
|
||||
rbacSync := sync.ProvideRBACSync(accessControlService)
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagCloudRBACRoles) {
|
||||
authnSvc.RegisterPostAuthHook(rbacSync.SyncCloudRoles, 110)
|
||||
}
|
||||
|
||||
authnSvc.RegisterPostAuthHook(rbacSync.SyncPermissionsHook, 120)
|
||||
authnSvc.RegisterPostAuthHook(orgSync.SetDefaultOrgHook, 130)
|
||||
|
||||
return Registration{}
|
||||
}
|
@ -13,26 +13,13 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/network"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/authn/authnimpl/sync"
|
||||
"github.com/grafana/grafana/pkg/services/authn/clients"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/ldap/service"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/loginattempt"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/signingkeys"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
@ -60,19 +47,8 @@ func ProvideIdentitySynchronizer(s *Service) authn.IdentitySynchronizer {
|
||||
|
||||
func ProvideService(
|
||||
cfg *setting.Cfg, tracer tracing.Tracer,
|
||||
orgService org.Service, sessionService auth.UserTokenService,
|
||||
accessControlService accesscontrol.Service,
|
||||
apikeyService apikey.Service, userService user.Service,
|
||||
jwtService auth.JWTVerifierService,
|
||||
usageStats usagestats.Service,
|
||||
userProtectionService login.UserProtectionService,
|
||||
loginAttempts loginattempt.Service, quotaService quota.Service,
|
||||
authInfoService login.AuthInfoService, renderService rendering.Service,
|
||||
features *featuremgmt.FeatureManager, oauthTokenService oauthtoken.OAuthTokenService,
|
||||
socialService social.Service, cache *remotecache.RemoteCache,
|
||||
ldapService service.LDAP, registerer prometheus.Registerer,
|
||||
signingKeysService signingkeys.Service,
|
||||
settingsProviderService setting.Provider,
|
||||
sessionService auth.UserTokenService, usageStats usagestats.Service,
|
||||
authInfoService login.AuthInfoService, registerer prometheus.Registerer,
|
||||
) *Service {
|
||||
s := &Service{
|
||||
log: log.New("authn.service"),
|
||||
@ -88,81 +64,6 @@ func ProvideService(
|
||||
}
|
||||
|
||||
usageStats.RegisterMetricsFunc(s.getUsageStats)
|
||||
|
||||
s.RegisterClient(clients.ProvideRender(renderService))
|
||||
s.RegisterClient(clients.ProvideAPIKey(apikeyService))
|
||||
|
||||
if cfg.LoginCookieName != "" {
|
||||
s.RegisterClient(clients.ProvideSession(cfg, sessionService))
|
||||
}
|
||||
|
||||
var proxyClients []authn.ProxyClient
|
||||
var passwordClients []authn.PasswordClient
|
||||
if s.cfg.LDAPAuthEnabled {
|
||||
ldap := clients.ProvideLDAP(cfg, ldapService, userService, authInfoService)
|
||||
proxyClients = append(proxyClients, ldap)
|
||||
passwordClients = append(passwordClients, ldap)
|
||||
}
|
||||
|
||||
if !s.cfg.DisableLogin {
|
||||
grafana := clients.ProvideGrafana(cfg, userService)
|
||||
proxyClients = append(proxyClients, grafana)
|
||||
passwordClients = append(passwordClients, grafana)
|
||||
}
|
||||
|
||||
// if we have password clients configure check if basic auth or form auth is enabled
|
||||
if len(passwordClients) > 0 {
|
||||
passwordClient := clients.ProvidePassword(loginAttempts, passwordClients...)
|
||||
if s.cfg.BasicAuthEnabled {
|
||||
s.RegisterClient(clients.ProvideBasic(passwordClient))
|
||||
}
|
||||
|
||||
if !s.cfg.DisableLoginForm {
|
||||
s.RegisterClient(clients.ProvideForm(passwordClient))
|
||||
}
|
||||
}
|
||||
|
||||
if s.cfg.AuthProxy.Enabled && len(proxyClients) > 0 {
|
||||
proxy, err := clients.ProvideProxy(cfg, cache, proxyClients...)
|
||||
if err != nil {
|
||||
s.log.Error("Failed to configure auth proxy", "err", err)
|
||||
} else {
|
||||
s.RegisterClient(proxy)
|
||||
}
|
||||
}
|
||||
|
||||
if s.cfg.JWTAuth.Enabled {
|
||||
s.RegisterClient(clients.ProvideJWT(jwtService, cfg))
|
||||
}
|
||||
|
||||
if s.cfg.ExtJWTAuth.Enabled && features.IsEnabledGlobally(featuremgmt.FlagAuthAPIAccessTokenAuth) {
|
||||
s.RegisterClient(clients.ProvideExtendedJWT(userService, cfg, signingKeysService))
|
||||
}
|
||||
|
||||
for name := range socialService.GetOAuthProviders() {
|
||||
clientName := authn.ClientWithPrefix(name)
|
||||
s.RegisterClient(clients.ProvideOAuth(clientName, cfg, oauthTokenService, socialService, settingsProviderService, features))
|
||||
}
|
||||
|
||||
// FIXME (jguer): move to User package
|
||||
userSyncService := sync.ProvideUserSync(userService, userProtectionService, authInfoService, quotaService)
|
||||
orgUserSyncService := sync.ProvideOrgSync(userService, orgService, accessControlService, cfg)
|
||||
s.RegisterPostAuthHook(userSyncService.SyncUserHook, 10)
|
||||
s.RegisterPostAuthHook(userSyncService.EnableUserHook, 20)
|
||||
s.RegisterPostAuthHook(orgUserSyncService.SyncOrgRolesHook, 30)
|
||||
s.RegisterPostAuthHook(userSyncService.SyncLastSeenHook, 130)
|
||||
s.RegisterPostAuthHook(sync.ProvideOAuthTokenSync(oauthTokenService, sessionService, socialService).SyncOauthTokenHook, 60)
|
||||
s.RegisterPostAuthHook(userSyncService.FetchSyncedUserHook, 100)
|
||||
|
||||
rbacSync := sync.ProvideRBACSync(accessControlService)
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagCloudRBACRoles) {
|
||||
s.RegisterPostAuthHook(rbacSync.SyncCloudRoles, 110)
|
||||
}
|
||||
|
||||
s.RegisterPostAuthHook(rbacSync.SyncPermissionsHook, 120)
|
||||
|
||||
s.RegisterPostAuthHook(orgUserSyncService.SetDefaultOrgHook, 130)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user