Alerting: modify DB table, accessors and migration to restrict org access (#37414)
* Alerting: modify table and accessors to limit org access appropriately * Update migration to create multiple Alertmanager configs * Apply suggestions from code review Co-authored-by: gotjosh <josue@grafana.com> * replace mg.ClearMigrationEntry() mg.ClearMigrationEntry() would create a new session. This commit introduces a new migration for clearing an entry from migration log for replacing mg.ClearMigrationEntry() so that all dashboard alert migration operations will run inside the same transaction. It adds also `SkipMigrationLog()` in Migrator interface for skipping adding an entry in the migration_log. Co-authored-by: gotjosh <josue@grafana.com>
This commit is contained in:
co-authored by
gotjosh
parent
4a9fdb8b76
commit
04d5dcb7c8
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -72,6 +73,8 @@ const (
|
||||
}
|
||||
}
|
||||
`
|
||||
//TODO: temporary until fix org isolation
|
||||
mainOrgID = 1
|
||||
)
|
||||
|
||||
type Alertmanager struct {
|
||||
@@ -168,7 +171,7 @@ func (am *Alertmanager) Ready() bool {
|
||||
|
||||
func (am *Alertmanager) Run(ctx context.Context) error {
|
||||
// Make sure dispatcher starts. We can tolerate future reload failures.
|
||||
if err := am.SyncAndApplyConfigFromDatabase(); err != nil {
|
||||
if err := am.SyncAndApplyConfigFromDatabase(mainOrgID); err != nil {
|
||||
am.logger.Error("unable to sync configuration", "err", err)
|
||||
}
|
||||
|
||||
@@ -177,7 +180,7 @@ func (am *Alertmanager) Run(ctx context.Context) error {
|
||||
case <-ctx.Done():
|
||||
return am.StopAndWait()
|
||||
case <-time.After(pollInterval):
|
||||
if err := am.SyncAndApplyConfigFromDatabase(); err != nil {
|
||||
if err := am.SyncAndApplyConfigFromDatabase(mainOrgID); err != nil {
|
||||
am.logger.Error("unable to sync configuration", "err", err)
|
||||
}
|
||||
}
|
||||
@@ -203,7 +206,7 @@ func (am *Alertmanager) StopAndWait() error {
|
||||
|
||||
// SaveAndApplyDefaultConfig saves the default configuration the database and applies the configuration to the Alertmanager.
|
||||
// It rollbacks the save if we fail to apply the configuration.
|
||||
func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
|
||||
func (am *Alertmanager) SaveAndApplyDefaultConfig(orgID int64) error {
|
||||
am.reloadConfigMtx.Lock()
|
||||
defer am.reloadConfigMtx.Unlock()
|
||||
|
||||
@@ -211,6 +214,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
|
||||
AlertmanagerConfiguration: alertmanagerDefaultConfiguration,
|
||||
Default: true,
|
||||
ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
cfg, err := Load([]byte(alertmanagerDefaultConfiguration))
|
||||
@@ -234,7 +238,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
|
||||
|
||||
// SaveAndApplyConfig saves the configuration the database and applies the configuration to the Alertmanager.
|
||||
// It rollbacks the save if we fail to apply the configuration.
|
||||
func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) error {
|
||||
func (am *Alertmanager) SaveAndApplyConfig(orgID int64, cfg *apimodels.PostableUserConfig) error {
|
||||
rawConfig, err := json.Marshal(&cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize to the Alertmanager configuration: %w", err)
|
||||
@@ -246,6 +250,7 @@ func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) er
|
||||
cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{
|
||||
AlertmanagerConfiguration: string(rawConfig),
|
||||
ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
err = am.Store.SaveAlertmanagerConfigurationWithCallback(cmd, func() error {
|
||||
@@ -264,12 +269,12 @@ func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) er
|
||||
|
||||
// SyncAndApplyConfigFromDatabase picks the latest config from database and restarts
|
||||
// the components with the new config.
|
||||
func (am *Alertmanager) SyncAndApplyConfigFromDatabase() error {
|
||||
func (am *Alertmanager) SyncAndApplyConfigFromDatabase(orgID int64) error {
|
||||
am.reloadConfigMtx.Lock()
|
||||
defer am.reloadConfigMtx.Unlock()
|
||||
|
||||
// First, let's get the configuration we need from the database.
|
||||
q := &ngmodels.GetLatestAlertmanagerConfigurationQuery{}
|
||||
q := &ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: mainOrgID}
|
||||
if err := am.Store.GetLatestAlertmanagerConfiguration(q); err != nil {
|
||||
// If there's no configuration in the database, let's use the default configuration.
|
||||
if errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
@@ -279,6 +284,7 @@ func (am *Alertmanager) SyncAndApplyConfigFromDatabase() error {
|
||||
AlertmanagerConfiguration: alertmanagerDefaultConfiguration,
|
||||
Default: true,
|
||||
ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
|
||||
OrgID: orgID,
|
||||
}
|
||||
if err := am.Store.SaveAlertmanagerConfiguration(savecmd); err != nil {
|
||||
return err
|
||||
@@ -399,7 +405,7 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
||||
}
|
||||
|
||||
func (am *Alertmanager) WorkingDirPath() string {
|
||||
return filepath.Join(am.Settings.DataPath, workingDir)
|
||||
return filepath.Join(am.Settings.DataPath, workingDir, strconv.Itoa(mainOrgID))
|
||||
}
|
||||
|
||||
// buildIntegrationsMap builds a map of name to the list of Grafana integration notifiers off of a list of receiver config.
|
||||
|
||||
@@ -54,7 +54,7 @@ func setupAMTest(t *testing.T) *Alertmanager {
|
||||
|
||||
func TestAlertmanager_ShouldUseDefaultConfigurationWhenNoConfiguration(t *testing.T) {
|
||||
am := setupAMTest(t)
|
||||
require.NoError(t, am.SyncAndApplyConfigFromDatabase())
|
||||
require.NoError(t, am.SyncAndApplyConfigFromDatabase(mainOrgID))
|
||||
require.NotNil(t, am.config)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user