mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Auth: reload SSO settings for HA setups (#80231)
* reload SSO settings for HA setups * remove check for grafana HA * add unit tests * fetch all sso settings with one sql query * register background service
This commit is contained in:
parent
02136e5a2f
commit
772e5993b6
@ -36,6 +36,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
samanager "github.com/grafana/grafana/pkg/services/serviceaccounts/manager"
|
||||
"github.com/grafana/grafana/pkg/services/ssosettings"
|
||||
"github.com/grafana/grafana/pkg/services/ssosettings/ssosettingsimpl"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/sanitizer"
|
||||
@ -58,6 +59,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
keyRetriever *dynamic.KeyRetriever, dynamicAngularDetectorsProvider *angulardetectorsprovider.Dynamic,
|
||||
grafanaAPIServer grafanaapiserver.Service,
|
||||
anon *anonimpl.AnonDeviceService,
|
||||
ssoSettings *ssosettingsimpl.SSOSettingsService,
|
||||
// Need to make sure these are initialized, is there a better place to put them?
|
||||
_ dashboardsnapshots.Service, _ *alerting.AlertNotificationService,
|
||||
_ serviceaccounts.Service, _ *guardian.Provider,
|
||||
@ -98,6 +100,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
dynamicAngularDetectorsProvider,
|
||||
grafanaAPIServer,
|
||||
anon,
|
||||
ssoSettings,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
@ -250,6 +251,44 @@ func (s *SSOSettingsService) encryptSecrets(ctx context.Context, settings map[st
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *SSOSettingsService) Run(ctx context.Context) error {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
|
||||
// start a background process for reloading the SSO settings for all providers at a fixed interval
|
||||
// it is useful for high availability setups running multiple Grafana instances
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
s.doReload(ctx)
|
||||
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SSOSettingsService) doReload(ctx context.Context) {
|
||||
s.log.Debug("reloading SSO Settings for all providers")
|
||||
|
||||
settingsList, err := s.List(ctx)
|
||||
if err != nil {
|
||||
s.log.Error("failed to fetch SSO Settings for all providers", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
for provider, connector := range s.reloadables {
|
||||
settings := getSettingsByProvider(provider, settingsList)
|
||||
|
||||
if len(settings) > 0 {
|
||||
err = connector.Reload(ctx, *settings[0])
|
||||
if err != nil {
|
||||
s.log.Error("failed to reload SSO Settings", "provider", provider, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isSecret(fieldName string) bool {
|
||||
secretFieldPatterns := []string{"secret"}
|
||||
|
||||
|
@ -634,6 +634,59 @@ func TestSSOSettingsService_Delete(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSOSettingsService_DoReload(t *testing.T) {
|
||||
t.Run("successfully reload settings", func(t *testing.T) {
|
||||
env := setupTestEnv(t)
|
||||
|
||||
settingsList := []*models.SSOSettings{
|
||||
{
|
||||
Provider: "github",
|
||||
Settings: map[string]any{
|
||||
"enabled": true,
|
||||
"client_id": "github_client_id",
|
||||
},
|
||||
},
|
||||
{
|
||||
Provider: "google",
|
||||
Settings: map[string]any{
|
||||
"enabled": true,
|
||||
"client_id": "google_client_id",
|
||||
},
|
||||
},
|
||||
{
|
||||
Provider: "azuread",
|
||||
Settings: map[string]any{
|
||||
"enabled": true,
|
||||
"client_id": "azuread_client_id",
|
||||
},
|
||||
},
|
||||
}
|
||||
env.store.ExpectedSSOSettings = settingsList
|
||||
|
||||
reloadable := ssosettingstests.NewMockReloadable(t)
|
||||
|
||||
for _, settings := range settingsList {
|
||||
reloadable.On("Reload", mock.Anything, *settings).Return(nil).Once()
|
||||
env.reloadables[settings.Provider] = reloadable
|
||||
}
|
||||
|
||||
env.service.doReload(context.Background())
|
||||
})
|
||||
|
||||
t.Run("failed fetching the SSO settings", func(t *testing.T) {
|
||||
env := setupTestEnv(t)
|
||||
|
||||
provider := "github"
|
||||
|
||||
env.store.ExpectedError = errors.New("failed fetching the settings")
|
||||
|
||||
reloadable := ssosettingstests.NewMockReloadable(t)
|
||||
env.reloadables[provider] = reloadable
|
||||
|
||||
env.service.doReload(context.Background())
|
||||
})
|
||||
}
|
||||
|
||||
func setupTestEnv(t *testing.T) testEnv {
|
||||
store := ssosettingstests.NewFakeStore()
|
||||
fallbackStrategy := ssosettingstests.NewFakeFallbackStrategy()
|
||||
|
Loading…
Reference in New Issue
Block a user