diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 002bbbfd54c..d9fe3b73822 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -157,7 +157,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro } } - hideVersion := hs.Cfg.AnonymousHideVersion && !c.IsSignedIn + hideVersion := hs.Cfg.Anonymous.HideVersion && !c.IsSignedIn version := setting.BuildVersion commit := setting.BuildCommit commitShort := getShortCommitHash(setting.BuildCommit, 10) @@ -266,8 +266,8 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro }, FeatureToggles: featureToggles, - AnonymousEnabled: hs.Cfg.AnonymousEnabled, - AnonymousDeviceLimit: hs.Cfg.AnonymousDeviceLimit, + AnonymousEnabled: hs.Cfg.Anonymous.Enabled, + AnonymousDeviceLimit: hs.Cfg.Anonymous.DeviceLimit, RendererAvailable: hs.RenderService.IsAvailable(c.Req.Context()), RendererVersion: hs.RenderService.Version(), RendererDefaultImageWidth: hs.Cfg.RendererDefaultImageWidth, diff --git a/pkg/api/frontendsettings_test.go b/pkg/api/frontendsettings_test.go index 9edb77235f4..6a9663fe77f 100644 --- a/pkg/api/frontendsettings_test.go +++ b/pkg/api/frontendsettings_test.go @@ -160,7 +160,7 @@ func TestHTTPServer_GetFrontendSettings_hideVersionAnonymous(t *testing.T) { for _, test := range tests { t.Run(test.desc, func(t *testing.T) { - hs.Cfg.AnonymousHideVersion = test.hideVersion + hs.Cfg.Anonymous.HideVersion = test.hideVersion expected := test.expected recorder := httptest.NewRecorder() diff --git a/pkg/api/health_test.go b/pkg/api/health_test.go index bd4ee27b044..0d22c2e6c34 100644 --- a/pkg/api/health_test.go +++ b/pkg/api/health_test.go @@ -61,7 +61,7 @@ func TestHealthAPI_VersionEnterprise(t *testing.T) { func TestHealthAPI_AnonymousHideVersion(t *testing.T) { m, hs := setupHealthAPITestEnvironment(t) - hs.Cfg.AnonymousHideVersion = true + hs.Cfg.Anonymous.HideVersion = true req := httptest.NewRequest(http.MethodGet, "/api/health", nil) rec := httptest.NewRecorder() @@ -80,7 +80,7 @@ func TestHealthAPI_DatabaseHealthy(t *testing.T) { const cacheKey = "db-healthy" m, hs := setupHealthAPITestEnvironment(t) - hs.Cfg.AnonymousHideVersion = true + hs.Cfg.Anonymous.HideVersion = true healthy, found := hs.CacheService.Get(cacheKey) require.False(t, found) @@ -107,7 +107,7 @@ func TestHealthAPI_DatabaseUnhealthy(t *testing.T) { const cacheKey = "db-healthy" m, hs := setupHealthAPITestEnvironment(t) - hs.Cfg.AnonymousHideVersion = true + hs.Cfg.Anonymous.HideVersion = true hs.SQLStore.(*dbtest.FakeDB).ExpectedError = errors.New("bad") healthy, found := hs.CacheService.Get(cacheKey) @@ -135,7 +135,7 @@ func TestHealthAPI_DatabaseHealthCached(t *testing.T) { const cacheKey = "db-healthy" m, hs := setupHealthAPITestEnvironment(t) - hs.Cfg.AnonymousHideVersion = true + hs.Cfg.Anonymous.HideVersion = true // Mock unhealthy database in cache. hs.CacheService.Set(cacheKey, false, 5*time.Minute) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 13596dab25b..041fe72e0e0 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -716,7 +716,7 @@ func (hs *HTTPServer) apiHealthHandler(ctx *web.Context) { data := healthResponse{ Database: "ok", } - if !hs.Cfg.AnonymousHideVersion { + if !hs.Cfg.Anonymous.HideVersion { data.Version = hs.Cfg.BuildVersion data.Commit = hs.Cfg.BuildCommit if hs.Cfg.EnterpriseBuildCommit != "NA" && hs.Cfg.EnterpriseBuildCommit != "" { diff --git a/pkg/infra/usagestats/service/usage_stats_test.go b/pkg/infra/usagestats/service/usage_stats_test.go index b85c9fd3eef..c405c681329 100644 --- a/pkg/infra/usagestats/service/usage_stats_test.go +++ b/pkg/infra/usagestats/service/usage_stats_test.go @@ -84,7 +84,7 @@ func TestMetrics(t *testing.T) { uss.Cfg = &setting.Cfg{ ReportingEnabled: true, BuildVersion: "5.0.0", - AnonymousEnabled: true, + Anonymous: setting.AnonymousSettings{Enabled: true}, BasicAuthEnabled: true, LDAPAuthEnabled: true, AuthProxy: setting.AuthProxySettings{Enabled: true}, diff --git a/pkg/infra/usagestats/statscollector/service_test.go b/pkg/infra/usagestats/statscollector/service_test.go index 00d6ad621d0..0d5f955ce47 100644 --- a/pkg/infra/usagestats/statscollector/service_test.go +++ b/pkg/infra/usagestats/statscollector/service_test.go @@ -139,7 +139,7 @@ func TestCollectingUsageStats(t *testing.T) { s := createService(t, &setting.Cfg{ ReportingEnabled: true, BuildVersion: "5.0.0", - AnonymousEnabled: true, + Anonymous: setting.AnonymousSettings{Enabled: true}, BasicAuthEnabled: true, LDAPAuthEnabled: true, AuthProxy: setting.AuthProxySettings{Enabled: true}, diff --git a/pkg/middleware/quota_test.go b/pkg/middleware/quota_test.go index 8a1f15a4118..a714b7cb23c 100644 --- a/pkg/middleware/quota_test.go +++ b/pkg/middleware/quota_test.go @@ -182,5 +182,5 @@ func getQuotaHandler(reached bool, target string) web.Handler { } func configure(cfg *setting.Cfg) { - cfg.AnonymousEnabled = false + cfg.Anonymous.Enabled = false } diff --git a/pkg/services/accesscontrol/dualwrite/collectors.go b/pkg/services/accesscontrol/dualwrite/collectors.go index 3d6b9b3e974..c38803eebfd 100644 --- a/pkg/services/accesscontrol/dualwrite/collectors.go +++ b/pkg/services/accesscontrol/dualwrite/collectors.go @@ -399,11 +399,11 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector { func anonymousRoleBindingsCollector(cfg *setting.Cfg, store db.DB) legacyTupleCollector { return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) { tuples := make(map[string]map[string]*openfgav1.TupleKey) - object := zanzana.NewTupleEntry(zanzana.TypeRole, zanzana.TranslateBasicRole(cfg.AnonymousOrgRole), "") + object := zanzana.NewTupleEntry(zanzana.TypeRole, zanzana.TranslateBasicRole(cfg.Anonymous.OrgRole), "") // Object should be set to delete obsolete permissions tuples[object] = make(map[string]*openfgav1.TupleKey) - o, err := getOrgByName(ctx, store, cfg.AnonymousOrgName) + o, err := getOrgByName(ctx, store, cfg.Anonymous.OrgName) if err != nil { return tuples, nil } diff --git a/pkg/services/accesscontrol/dualwrite/reconciler.go b/pkg/services/accesscontrol/dualwrite/reconciler.go index 9a72f848cba..e5cbecfa1fc 100644 --- a/pkg/services/accesscontrol/dualwrite/reconciler.go +++ b/pkg/services/accesscontrol/dualwrite/reconciler.go @@ -93,7 +93,7 @@ func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, }, } - if cfg.AnonymousEnabled { + if cfg.Anonymous.Enabled { zanzanaReconciler.reconcilers = append(zanzanaReconciler.reconcilers, newResourceReconciler( "anonymous role binding", diff --git a/pkg/services/anonymous/anonimpl/client.go b/pkg/services/anonymous/anonimpl/client.go index b2d0ca6ddce..8209f0a43ac 100644 --- a/pkg/services/anonymous/anonimpl/client.go +++ b/pkg/services/anonymous/anonimpl/client.go @@ -39,9 +39,9 @@ func (a *Anonymous) Name() string { } func (a *Anonymous) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identity, error) { - o, err := a.orgService.GetByName(ctx, &org.GetOrgByNameQuery{Name: a.cfg.AnonymousOrgName}) + o, err := a.orgService.GetByName(ctx, &org.GetOrgByNameQuery{Name: a.cfg.Anonymous.OrgName}) if err != nil { - a.log.FromContext(ctx).Error("Failed to find organization", "name", a.cfg.AnonymousOrgName, "error", err) + a.log.FromContext(ctx).Error("Failed to find organization", "name", a.cfg.Anonymous.OrgName, "error", err) return nil, err } @@ -64,7 +64,7 @@ func (a *Anonymous) Authenticate(ctx context.Context, r *authn.Request) (*authn. } func (a *Anonymous) IsEnabled() bool { - return a.cfg.AnonymousEnabled + return a.cfg.Anonymous.Enabled } func (a *Anonymous) Test(ctx context.Context, r *authn.Request) bool { @@ -77,7 +77,7 @@ func (a *Anonymous) IdentityType() claims.IdentityType { } func (a *Anonymous) ResolveIdentity(ctx context.Context, orgID int64, typ claims.IdentityType, id string) (*authn.Identity, error) { - o, err := a.orgService.GetByName(ctx, &org.GetOrgByNameQuery{Name: a.cfg.AnonymousOrgName}) + o, err := a.orgService.GetByName(ctx, &org.GetOrgByNameQuery{Name: a.cfg.Anonymous.OrgName}) if err != nil { return nil, err } @@ -99,7 +99,7 @@ func (a *Anonymous) UsageStatFn(ctx context.Context) (map[string]any, error) { // Add stats about anonymous auth m["stats.anonymous.customized_role.count"] = 0 - if !strings.EqualFold(a.cfg.AnonymousOrgRole, "Viewer") { + if !strings.EqualFold(a.cfg.Anonymous.OrgRole, "Viewer") { m["stats.anonymous.customized_role.count"] = 1 } @@ -116,7 +116,7 @@ func (a *Anonymous) newAnonymousIdentity(o *org.Org) *authn.Identity { Type: claims.TypeAnonymous, OrgID: o.ID, OrgName: o.Name, - OrgRoles: map[int64]org.RoleType{o.ID: org.RoleType(a.cfg.AnonymousOrgRole)}, + OrgRoles: map[int64]org.RoleType{o.ID: org.RoleType(a.cfg.Anonymous.OrgRole)}, ClientParams: authn.ClientParams{SyncPermissions: true}, } } diff --git a/pkg/services/anonymous/anonimpl/client_test.go b/pkg/services/anonymous/anonimpl/client_test.go index 1cff62e6a25..aed455a54de 100644 --- a/pkg/services/anonymous/anonimpl/client_test.go +++ b/pkg/services/anonymous/anonimpl/client_test.go @@ -30,16 +30,20 @@ func TestAnonymous_Authenticate(t *testing.T) { desc: "should success with valid org configured", org: &org.Org{ID: 1, Name: "some org"}, cfg: &setting.Cfg{ - AnonymousOrgName: "some org", - AnonymousOrgRole: "Viewer", + Anonymous: setting.AnonymousSettings{ + OrgRole: "Viewer", + OrgName: "some org", + }, }, }, { desc: "should return error if any error occurs during org lookup", err: fmt.Errorf("some error"), cfg: &setting.Cfg{ - AnonymousOrgName: "some org", - AnonymousOrgRole: "Viewer", + Anonymous: setting.AnonymousSettings{ + OrgRole: "Viewer", + OrgName: "some org", + }, }, }, } @@ -63,7 +67,7 @@ func TestAnonymous_Authenticate(t *testing.T) { assert.Equal(t, "anonymous:0", user.GetID()) assert.Equal(t, tt.org.ID, user.OrgID) assert.Equal(t, tt.org.Name, user.OrgName) - assert.Equal(t, tt.cfg.AnonymousOrgRole, string(user.GetOrgRole())) + assert.Equal(t, tt.cfg.Anonymous.OrgRole, string(user.GetOrgRole())) } }) } @@ -86,7 +90,9 @@ func TestAnonymous_ResolveIdentity(t *testing.T) { desc: "should return error when org id is not the configured one", org: &org.Org{ID: 2, Name: "some org"}, cfg: &setting.Cfg{ - AnonymousOrgName: "some org", + Anonymous: setting.AnonymousSettings{ + OrgName: "some org", + }, }, orgID: 1, typ: claims.TypeAnonymous, @@ -97,7 +103,9 @@ func TestAnonymous_ResolveIdentity(t *testing.T) { desc: "should return error when namespace id does not match anonymous namespace id", org: &org.Org{ID: 1, Name: "some org"}, cfg: &setting.Cfg{ - AnonymousOrgName: "some org", + Anonymous: setting.AnonymousSettings{ + OrgName: "some org", + }, }, orgID: 1, typ: claims.TypeAnonymous, @@ -108,7 +116,9 @@ func TestAnonymous_ResolveIdentity(t *testing.T) { desc: "should resolve identity", org: &org.Org{ID: 1, Name: "some org"}, cfg: &setting.Cfg{ - AnonymousOrgName: "some org", + Anonymous: setting.AnonymousSettings{ + OrgName: "some org", + }, }, orgID: 1, typ: claims.TypeAnonymous, diff --git a/pkg/services/anonymous/anonimpl/impl.go b/pkg/services/anonymous/anonimpl/impl.go index 1ddc6b19942..d913ca0ec65 100644 --- a/pkg/services/anonymous/anonimpl/impl.go +++ b/pkg/services/anonymous/anonimpl/impl.go @@ -45,7 +45,7 @@ func ProvideAnonymousDeviceService(usageStats usagestats.Service, authBroker aut a := &AnonDeviceService{ log: log.New("anonymous-session-service"), localCache: localcache.New(29*time.Minute, 15*time.Minute), - anonStore: anonstore.ProvideAnonDBStore(sqlStore, cfg.AnonymousDeviceLimit), + anonStore: anonstore.ProvideAnonDBStore(sqlStore, cfg.Anonymous.DeviceLimit), serverLock: serverLockService, cfg: cfg, limitValidator: validator, @@ -60,7 +60,7 @@ func ProvideAnonymousDeviceService(usageStats usagestats.Service, authBroker aut anonDeviceService: a, } - if cfg.AnonymousEnabled { + if cfg.Anonymous.Enabled { authBroker.RegisterClient(anonClient) authBroker.RegisterPostLoginHook(a.untagDevice, 100) } @@ -171,7 +171,7 @@ func (a *AnonDeviceService) TagDevice(ctx context.Context, httpReq *http.Request // ListDevices returns all devices that have been updated between the given times. func (a *AnonDeviceService) ListDevices(ctx context.Context, from *time.Time, to *time.Time) ([]*anonstore.Device, error) { - if !a.cfg.AnonymousEnabled { + if !a.cfg.Anonymous.Enabled { a.log.Debug("Anonymous access is disabled, returning empty result") return []*anonstore.Device{}, nil } @@ -181,7 +181,7 @@ func (a *AnonDeviceService) ListDevices(ctx context.Context, from *time.Time, to // CountDevices returns the number of devices that have been updated between the given times. func (a *AnonDeviceService) CountDevices(ctx context.Context, from time.Time, to time.Time) (int64, error) { - if !a.cfg.AnonymousEnabled { + if !a.cfg.Anonymous.Enabled { a.log.Debug("Anonymous access is disabled, returning empty result") return 0, nil } @@ -190,7 +190,7 @@ func (a *AnonDeviceService) CountDevices(ctx context.Context, from time.Time, to } func (a *AnonDeviceService) SearchDevices(ctx context.Context, query *anonstore.SearchDeviceQuery) (*anonstore.SearchDeviceQueryResult, error) { - if !a.cfg.AnonymousEnabled { + if !a.cfg.Anonymous.Enabled { a.log.Debug("Anonymous access is disabled, returning empty result") return nil, nil } diff --git a/pkg/services/anonymous/anonimpl/impl_test.go b/pkg/services/anonymous/anonimpl/impl_test.go index d60a9345874..0ca7cb2cf78 100644 --- a/pkg/services/anonymous/anonimpl/impl_test.go +++ b/pkg/services/anonymous/anonimpl/impl_test.go @@ -259,7 +259,7 @@ func TestIntegrationDeviceService_SearchDevice(t *testing.T) { } store := db.InitTestDB(t) cfg := setting.NewCfg() - cfg.AnonymousEnabled = true + cfg.Anonymous.Enabled = true anonService := ProvideAnonymousDeviceService(&usagestats.UsageStatsMock{}, &authntest.FakeService{}, store, cfg, orgtest.NewOrgServiceFake(), nil, actest.FakeAccessControl{}, &routing.RouteRegisterImpl{}, validator.FakeAnonUserLimitValidator{}) for _, tc := range testCases { @@ -291,7 +291,7 @@ func TestIntegrationAnonDeviceService_DeviceLimitWithCache(t *testing.T) { // Setup test environment store := db.InitTestDB(t) cfg := setting.NewCfg() - cfg.AnonymousDeviceLimit = 1 // Set device limit to 1 for testing + cfg.Anonymous.DeviceLimit = 1 // Set device limit to 1 for testing anonService := ProvideAnonymousDeviceService( &usagestats.UsageStatsMock{}, &authntest.FakeService{}, diff --git a/pkg/services/authn/authnimpl/usage_stats.go b/pkg/services/authn/authnimpl/usage_stats.go index 52f224c7326..d17e3d9ea70 100644 --- a/pkg/services/authn/authnimpl/usage_stats.go +++ b/pkg/services/authn/authnimpl/usage_stats.go @@ -14,7 +14,7 @@ func (s *Service) getUsageStats(ctx context.Context) (map[string]any, error) { authTypes["basic_auth"] = s.cfg.BasicAuthEnabled authTypes["ldap"] = s.cfg.LDAPAuthEnabled authTypes["auth_proxy"] = s.cfg.AuthProxy.Enabled - authTypes["anonymous"] = s.cfg.AnonymousEnabled + authTypes["anonymous"] = s.cfg.Anonymous.Enabled authTypes["jwt"] = s.cfg.JWTAuth.Enabled authTypes["grafana_password"] = !s.cfg.DisableLogin authTypes["login_form"] = !s.cfg.DisableLoginForm diff --git a/pkg/services/navtree/navtreeimpl/navtree.go b/pkg/services/navtree/navtreeimpl/navtree.go index 9d4f7ac98f2..c67ee1bbfe8 100644 --- a/pkg/services/navtree/navtreeimpl/navtree.go +++ b/pkg/services/navtree/navtreeimpl/navtree.go @@ -189,7 +189,7 @@ func (s *ServiceImpl) GetNavTree(c *contextmodel.ReqContext, prefs *pref.Prefere func (s *ServiceImpl) getHomeNode(c *contextmodel.ReqContext, prefs *pref.Preference) *navtree.NavLink { homeUrl := s.cfg.AppSubURL + "/" - if !c.IsSignedIn && !s.cfg.AnonymousEnabled { + if !c.IsSignedIn && !s.cfg.Anonymous.Enabled { homeUrl = s.cfg.AppSubURL + "/login" } else { homePage := s.cfg.HomePage diff --git a/pkg/services/searchV2/service.go b/pkg/services/searchV2/service.go index b0fbcfe72ca..11c70332c72 100644 --- a/pkg/services/searchV2/service.go +++ b/pkg/services/searchV2/service.go @@ -155,18 +155,18 @@ func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backen // TODO: get user & user's permissions from the request context var usr *user.SignedInUser - if s.cfg.AnonymousEnabled && backendUser.Email == "" && backendUser.Login == "" { - getOrg := org.GetOrgByNameQuery{Name: s.cfg.AnonymousOrgName} + if s.cfg.Anonymous.Enabled && backendUser.Email == "" && backendUser.Login == "" { + getOrg := org.GetOrgByNameQuery{Name: s.cfg.Anonymous.OrgName} orga, err := s.orgService.GetByName(ctx, &getOrg) if err != nil { - s.logger.Error("Anonymous access organization error.", "org_name", s.cfg.AnonymousOrgName, "error", err) + s.logger.Error("Anonymous access organization error.", "org_name", s.cfg.Anonymous.OrgName, "error", err) return nil, err } usr = &user.SignedInUser{ OrgID: orga.ID, OrgName: orga.Name, - OrgRole: org.RoleType(s.cfg.AnonymousOrgRole), + OrgRole: org.RoleType(s.cfg.Anonymous.OrgRole), IsAnonymous: true, } } else { diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index eb139492ba5..092f03e8094 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -302,11 +302,7 @@ type Cfg struct { // Deprecated: use featuremgmt.FeatureFlags IsFeatureToggleEnabled func(key string) bool // filled in dynamically - AnonymousEnabled bool - AnonymousOrgName string - AnonymousOrgRole string - AnonymousHideVersion bool - AnonymousDeviceLimit int64 + Anonymous AnonymousSettings DateFormats DateFormats @@ -1654,12 +1650,7 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) { } // anonymous access - anonSection := iniFile.Section("auth.anonymous") - cfg.AnonymousEnabled = anonSection.Key("enabled").MustBool(false) - cfg.AnonymousOrgName = valueAsString(anonSection, "org_name", "") - cfg.AnonymousOrgRole = valueAsString(anonSection, "org_role", "") - cfg.AnonymousHideVersion = anonSection.Key("hide_version").MustBool(false) - cfg.AnonymousDeviceLimit = anonSection.Key("device_limit").MustInt64(0) + cfg.readAnonymousSettings() // basic auth authBasic := iniFile.Section("auth.basic") diff --git a/pkg/setting/setting_anonymous.go b/pkg/setting/setting_anonymous.go new file mode 100644 index 00000000000..057b82e73a4 --- /dev/null +++ b/pkg/setting/setting_anonymous.go @@ -0,0 +1,21 @@ +package setting + +type AnonymousSettings struct { + Enabled bool + OrgName string + OrgRole string + HideVersion bool + DeviceLimit int64 +} + +func (cfg *Cfg) readAnonymousSettings() { + anonSection := cfg.Raw.Section("auth.anonymous") + + anonSettings := AnonymousSettings{} + anonSettings.Enabled = anonSection.Key("enabled").MustBool(false) + anonSettings.OrgName = valueAsString(anonSection, "org_name", "") + anonSettings.OrgRole = valueAsString(anonSection, "org_role", "") + anonSettings.HideVersion = anonSection.Key("hide_version").MustBool(false) + anonSettings.DeviceLimit = anonSection.Key("device_limit").MustInt64(0) + cfg.Anonymous = anonSettings +}