Add verbose settings (#65469)

* Add `settings.CurrentVerbose` function

* Add function to retrieve verbose settings

* Add `/settings-verbose` endpoint

* Restrict the verbose source types
This commit is contained in:
linoman 2023-04-20 10:43:28 +02:00 committed by GitHub
parent 3a013cbe48
commit 4e10118c3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 3 deletions

View File

@ -33,6 +33,19 @@ func (hs *HTTPServer) AdminGetSettings(c *contextmodel.ReqContext) response.Resp
return response.JSON(http.StatusOK, settings)
}
func (hs *HTTPServer) AdminGetVerboseSettings(c *contextmodel.ReqContext) response.Response {
bag := hs.SettingsProvider.CurrentVerbose()
if bag == nil {
return response.JSON(http.StatusNotImplemented, make(map[string]string))
}
verboseSettings, err := hs.getAuthorizedVerboseSettings(c.Req.Context(), c.SignedInUser, bag)
if err != nil {
return response.Error(http.StatusForbidden, "Failed to authorize settings", err)
}
return response.JSON(http.StatusOK, verboseSettings)
}
// swagger:route GET /admin/stats admin adminGetStats
//
// Fetch Grafana Stats.
@ -99,6 +112,55 @@ func (hs *HTTPServer) getAuthorizedSettings(ctx context.Context, user *user.Sign
return authorizedBag, nil
}
func (hs *HTTPServer) getAuthorizedVerboseSettings(ctx context.Context, user *user.SignedInUser, bag setting.VerboseSettingsBag) (setting.VerboseSettingsBag, error) {
if hs.AccessControl.IsDisabled() {
return bag, nil
}
eval := func(scope string) (bool, error) {
return hs.AccessControl.Evaluate(ctx, user, ac.EvalPermission(ac.ActionSettingsRead, scope))
}
ok, err := eval(ac.ScopeSettingsAll)
if err != nil {
return nil, err
}
if ok {
return bag, nil
}
authorizedBag := make(setting.VerboseSettingsBag)
for section, keys := range bag {
ok, err := eval(ac.Scope("settings", section, "*"))
if err != nil {
return nil, err
}
if ok {
authorizedBag[section] = keys
continue
}
for key := range keys {
ok, err := eval(ac.Scope("settings", section, key))
if err != nil {
return nil, err
}
if !ok {
continue
}
if _, exists := authorizedBag[section]; !exists {
authorizedBag[section] = make(map[string]map[setting.VerboseSourceType]string)
}
authorizedBag[section][key] = bag[section][key]
}
}
return authorizedBag, nil
}
// swagger:response adminGetSettingsResponse
type GetSettingsResponse struct {
// in:body

View File

@ -594,6 +594,7 @@ func (hs *HTTPServer) registerRoutes() {
// admin api
r.Group("/api/admin", func(adminRoute routing.RouteRegister) {
adminRoute.Get("/settings", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetSettings))
adminRoute.Get("/settings-verbose", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetVerboseSettings))
adminRoute.Get("/stats", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)), routing.Wrap(hs.AdminGetStats))
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(hs.PauseAllAlerts(setting.AlertingEnabled)))

View File

@ -36,6 +36,9 @@ type Provider interface {
// the current configured pairs of key/values for each
// configuration section.
Current() SettingsBag
CurrentVerbose() VerboseSettingsBag
// Update receives a SettingsBag with the pairs of key/values
// to be updated per section and a SettingsRemovals with the
// section keys to be removed.
@ -92,6 +95,14 @@ type ReloadHandler interface {
type SettingsBag map[string]map[string]string
type SettingsRemovals map[string][]string
type VerboseSourceType string
type VerboseSettingsBag map[string]map[string]map[VerboseSourceType]string
const (
DB VerboseSourceType = "db"
System VerboseSourceType = "system"
)
func ProvideProvider(cfg *Cfg) *OSSImpl {
return &OSSImpl{
Cfg: cfg,
@ -102,7 +113,7 @@ type OSSImpl struct {
Cfg *Cfg
}
func (o OSSImpl) Current() SettingsBag {
func (o *OSSImpl) Current() SettingsBag {
settingsCopy := make(SettingsBag)
for _, section := range o.Cfg.Raw.Sections() {
@ -115,6 +126,10 @@ func (o OSSImpl) Current() SettingsBag {
return settingsCopy
}
func (o *OSSImpl) CurrentVerbose() VerboseSettingsBag {
return nil
}
func (OSSImpl) Update(SettingsBag, SettingsRemovals) error {
return errors.New("oss settings provider do not have support for settings updates")
}
@ -127,9 +142,9 @@ func (o *OSSImpl) Section(section string) Section {
return &sectionImpl{section: o.Cfg.Raw.Section(section)}
}
func (OSSImpl) RegisterReloadHandler(string, ReloadHandler) {}
func (*OSSImpl) RegisterReloadHandler(string, ReloadHandler) {}
func (o OSSImpl) IsFeatureToggleEnabled(name string) bool {
func (o *OSSImpl) IsFeatureToggleEnabled(name string) bool {
return o.Cfg.IsFeatureToggleEnabled(name)
}