Auth: Load ini/env vars settings in the fallback strategy (#78495)
* Return data in camelCase from the OAuth fb strategy * changes * wip * Add defaults for oauth fb strategy * revert other changes * Add tests * Add Defaults to cfg and use it in OAuthStrategy * Return *OAuthInfo from OAuthStrategy * lint * Remove unnecessary Defaults * Introduce const for fields, fix import order * Align failing tests * clean up * Changes requested by @gamab * Update pkg/services/ssosettings/strategies/oauth_strategy_test.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> * Load data on startup * Rename + simplify --------- Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
@@ -37,13 +37,13 @@ type SSOSettings struct {
|
||||
}
|
||||
|
||||
type SSOSettingsDTO struct {
|
||||
ID string `xorm:"id pk" json:"id"`
|
||||
Provider string `xorm:"provider" json:"provider"`
|
||||
Settings map[string]interface{} `xorm:"settings" json:"settings"`
|
||||
Created time.Time `xorm:"created" json:"-"`
|
||||
Updated time.Time `xorm:"updated" json:"-"`
|
||||
IsDeleted bool `xorm:"is_deleted" json:"-"`
|
||||
Source SettingsSource `xorm:"-" json:"source"`
|
||||
ID string `xorm:"id pk" json:"id"`
|
||||
Provider string `xorm:"provider" json:"provider"`
|
||||
Settings map[string]any `xorm:"settings" json:"settings"`
|
||||
Created time.Time `xorm:"created" json:"-"`
|
||||
Updated time.Time `xorm:"updated" json:"-"`
|
||||
IsDeleted bool `xorm:"is_deleted" json:"-"`
|
||||
Source SettingsSource `xorm:"-" json:"source"`
|
||||
}
|
||||
|
||||
// TableName returns the table name (needed for Xorm)
|
||||
@@ -79,7 +79,7 @@ func (s SSOSettings) ToSSOSettingsDTO() (*SSOSettingsDTO, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var settings map[string]interface{}
|
||||
var settings map[string]any
|
||||
err = json.Unmarshal(settingsEncoded, &settings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -3,6 +3,7 @@ package ssosettings
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/ssosettings/models"
|
||||
)
|
||||
@@ -12,7 +13,7 @@ var (
|
||||
// TODO: make it configurable
|
||||
ConfigurableOAuthProviders = []string{"github", "gitlab", "google", "generic_oauth", "azuread", "okta"}
|
||||
|
||||
AllOAuthProviders = []string{"github", "gitlab", "google", "generic_oauth", "grafana_com", "azuread", "okta"}
|
||||
AllOAuthProviders = []string{social.GitHubProviderName, social.GitlabProviderName, social.GoogleProviderName, social.GenericOAuthProviderName, social.GrafanaComProviderName, social.AzureADProviderName, social.OktaProviderName}
|
||||
)
|
||||
|
||||
// Service is a SSO settings service
|
||||
@@ -28,7 +29,7 @@ type Service interface {
|
||||
// Delete deletes the SSO settings for a given provider (soft delete)
|
||||
Delete(ctx context.Context, provider string) error
|
||||
// Patch updates the specified SSO settings (key-value pairs) for a given provider
|
||||
Patch(ctx context.Context, provider string, data map[string]interface{}) error
|
||||
Patch(ctx context.Context, provider string, data map[string]any) error
|
||||
// RegisterReloadable registers a reloadable provider
|
||||
RegisterReloadable(ctx context.Context, provider string, reloadable Reloadable)
|
||||
// Reload implements ssosettings.Reloadable interface
|
||||
@@ -45,7 +46,7 @@ type Reloadable interface {
|
||||
// using the config file and/or environment variables. Used mostly for backwards compatibility.
|
||||
type FallbackStrategy interface {
|
||||
IsMatch(provider string) bool
|
||||
ParseConfigFromSystem(ctx context.Context) (map[string]interface{}, error)
|
||||
GetProviderConfig(ctx context.Context, provider string) (any, error)
|
||||
}
|
||||
|
||||
// Store is a SSO settings store
|
||||
@@ -55,6 +56,6 @@ type Store interface {
|
||||
Get(ctx context.Context, provider string) (*models.SSOSettings, error)
|
||||
List(ctx context.Context) ([]*models.SSOSettings, error)
|
||||
Upsert(ctx context.Context, settings models.SSOSettings) error
|
||||
Patch(ctx context.Context, provider string, data map[string]interface{}) error
|
||||
Patch(ctx context.Context, provider string, data map[string]any) error
|
||||
Delete(ctx context.Context, provider string) error
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func (s *SSOSettingsService) Upsert(ctx context.Context, settings models.SSOSett
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SSOSettingsService) Patch(ctx context.Context, provider string, data map[string]interface{}) error {
|
||||
func (s *SSOSettingsService) Patch(ctx context.Context, provider string, data map[string]any) error {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
@@ -147,21 +147,21 @@ func (s *SSOSettingsService) loadSettingsUsingFallbackStrategy(ctx context.Conte
|
||||
return nil, errors.New("no fallback strategy found for provider: " + provider)
|
||||
}
|
||||
|
||||
settingsFromSystem, err := loadStrategy.ParseConfigFromSystem(ctx)
|
||||
settingsFromSystem, err := loadStrategy.GetProviderConfig(ctx, provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oAuthInfo, err := social.CreateOAuthInfoFromKeyValues(settingsFromSystem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
switch settingsFromSystem := settingsFromSystem.(type) {
|
||||
case *social.OAuthInfo:
|
||||
return &models.SSOSettings{
|
||||
Provider: provider,
|
||||
Source: models.System,
|
||||
OAuthSettings: settingsFromSystem,
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.New("could not parse settings from system")
|
||||
}
|
||||
|
||||
return &models.SSOSettings{
|
||||
Provider: provider,
|
||||
Source: models.System,
|
||||
OAuthSettings: oAuthInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getSettingsByProvider(provider string, settings []*models.SSOSettings) []*models.SSOSettings {
|
||||
|
||||
@@ -52,9 +52,7 @@ func TestSSOSettingsService_GetForProvider(t *testing.T) {
|
||||
setup: func(env testEnv) {
|
||||
env.store.ExpectedError = ssosettings.ErrNotFound
|
||||
env.fallbackStrategy.ExpectedIsMatch = true
|
||||
env.fallbackStrategy.ExpectedConfig = map[string]interface{}{
|
||||
"enabled": true,
|
||||
}
|
||||
env.fallbackStrategy.ExpectedConfig = &social.OAuthInfo{Enabled: true}
|
||||
},
|
||||
want: &models.SSOSettings{
|
||||
Provider: "github",
|
||||
@@ -150,9 +148,7 @@ func TestSSOSettingsService_List(t *testing.T) {
|
||||
},
|
||||
}
|
||||
env.fallbackStrategy.ExpectedIsMatch = true
|
||||
env.fallbackStrategy.ExpectedConfig = map[string]interface{}{
|
||||
"enabled": false,
|
||||
}
|
||||
env.fallbackStrategy.ExpectedConfig = &social.OAuthInfo{Enabled: false}
|
||||
},
|
||||
identity: defaultIdentity,
|
||||
want: []*models.SSOSettings{
|
||||
@@ -210,9 +206,7 @@ func TestSSOSettingsService_List(t *testing.T) {
|
||||
},
|
||||
}
|
||||
env.fallbackStrategy.ExpectedIsMatch = true
|
||||
env.fallbackStrategy.ExpectedConfig = map[string]interface{}{
|
||||
"enabled": false,
|
||||
}
|
||||
env.fallbackStrategy.ExpectedConfig = &social.OAuthInfo{Enabled: false}
|
||||
},
|
||||
identity: scopedIdentity,
|
||||
want: []*models.SSOSettings{
|
||||
@@ -241,9 +235,7 @@ func TestSSOSettingsService_List(t *testing.T) {
|
||||
setup: func(env testEnv) {
|
||||
env.store.ExpectedSSOSettings = []*models.SSOSettings{}
|
||||
env.fallbackStrategy.ExpectedIsMatch = true
|
||||
env.fallbackStrategy.ExpectedConfig = map[string]interface{}{
|
||||
"enabled": false,
|
||||
}
|
||||
env.fallbackStrategy.ExpectedConfig = &social.OAuthInfo{Enabled: false}
|
||||
},
|
||||
identity: defaultIdentity,
|
||||
want: []*models.SSOSettings{
|
||||
|
||||
@@ -4,7 +4,7 @@ import context "context"
|
||||
|
||||
type FakeFallbackStrategy struct {
|
||||
ExpectedIsMatch bool
|
||||
ExpectedConfig map[string]interface{}
|
||||
ExpectedConfig any
|
||||
|
||||
ExpectedError error
|
||||
}
|
||||
@@ -17,6 +17,6 @@ func (f *FakeFallbackStrategy) IsMatch(provider string) bool {
|
||||
return f.ExpectedIsMatch
|
||||
}
|
||||
|
||||
func (f *FakeFallbackStrategy) ParseConfigFromSystem(ctx context.Context) (map[string]interface{}, error) {
|
||||
func (f *FakeFallbackStrategy) GetProviderConfig(ctx context.Context, provider string) (any, error) {
|
||||
return f.ExpectedConfig, f.ExpectedError
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (f *FakeStore) Upsert(ctx context.Context, settings models.SSOSettings) err
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
func (f *FakeStore) Patch(ctx context.Context, provider string, data map[string]interface{}) error {
|
||||
func (f *FakeStore) Patch(ctx context.Context, provider string, data map[string]any) error {
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
|
||||
@@ -2,73 +2,101 @@ package strategies
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/ssosettings"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type OAuthStrategy struct {
|
||||
provider string
|
||||
cfg *setting.Cfg
|
||||
supportedProvidersRegex *regexp.Regexp
|
||||
cfg *setting.Cfg
|
||||
settingsByProvider map[string]*social.OAuthInfo
|
||||
}
|
||||
|
||||
var extraKeysByProvider = map[string][]string{
|
||||
social.AzureADProviderName: social.ExtraAzureADSettingKeys,
|
||||
social.GenericOAuthProviderName: social.ExtraGenericOAuthSettingKeys,
|
||||
social.GitHubProviderName: social.ExtraGithubSettingKeys,
|
||||
social.GrafanaComProviderName: social.ExtraGrafanaComSettingKeys,
|
||||
social.GrafanaNetProviderName: social.ExtraGrafanaComSettingKeys,
|
||||
}
|
||||
|
||||
var _ ssosettings.FallbackStrategy = (*OAuthStrategy)(nil)
|
||||
|
||||
func NewOAuthStrategy(cfg *setting.Cfg) *OAuthStrategy {
|
||||
compiledRegex := regexp.MustCompile(`^` + strings.Join(ssosettings.AllOAuthProviders, "|") + `$`)
|
||||
return &OAuthStrategy{
|
||||
cfg: cfg,
|
||||
supportedProvidersRegex: compiledRegex,
|
||||
oauthStrategy := &OAuthStrategy{
|
||||
cfg: cfg,
|
||||
settingsByProvider: make(map[string]*social.OAuthInfo),
|
||||
}
|
||||
|
||||
oauthStrategy.loadAllSettings()
|
||||
return oauthStrategy
|
||||
}
|
||||
|
||||
func (s *OAuthStrategy) IsMatch(provider string) bool {
|
||||
return s.supportedProvidersRegex.MatchString(provider)
|
||||
_, ok := s.settingsByProvider[provider]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (s *OAuthStrategy) ParseConfigFromSystem(_ context.Context) (map[string]any, error) {
|
||||
section := s.cfg.SectionWithEnvOverrides("auth." + s.provider)
|
||||
func (s *OAuthStrategy) GetProviderConfig(_ context.Context, provider string) (any, error) {
|
||||
return s.settingsByProvider[provider], nil
|
||||
}
|
||||
|
||||
// TODO: load the provider specific keys separately
|
||||
result := map[string]any{
|
||||
"client_id": section.Key("client_id").Value(),
|
||||
"client_secret": section.Key("client_secret").Value(),
|
||||
"scopes": section.Key("scopes").Value(),
|
||||
"auth_url": section.Key("auth_url").Value(),
|
||||
"token_url": section.Key("token_url").Value(),
|
||||
"api_url": section.Key("api_url").Value(),
|
||||
"teams_url": section.Key("teams_url").Value(),
|
||||
"enabled": section.Key("enabled").MustBool(false),
|
||||
"email_attribute_name": section.Key("email_attribute_name").Value(),
|
||||
"email_attribute_path": section.Key("email_attribute_path").Value(),
|
||||
"role_attribute_path": section.Key("role_attribute_path").Value(),
|
||||
"role_attribute_strict": section.Key("role_attribute_strict").MustBool(false),
|
||||
"groups_attribute_path": section.Key("groups_attribute_path").Value(),
|
||||
"team_ids_attribute_path": section.Key("team_ids_attribute_path").Value(),
|
||||
"allowed_domains": section.Key("allowed_domains").Value(),
|
||||
"hosted_domain": section.Key("hosted_domain").Value(),
|
||||
"allow_sign_up": section.Key("allow_sign_up").MustBool(true),
|
||||
"name": section.Key("name").MustString("default name"), // TODO: change this default value
|
||||
"icon": section.Key("icon").Value(),
|
||||
// TODO: @mgyongyosi move skipOrgRoleSync here in a separate PR
|
||||
// "skip_org_role_sync": section.Key("skip_org_role_sync").MustBool(false),
|
||||
"tls_client_cert": section.Key("tls_client_cert").Value(),
|
||||
"tls_client_key": section.Key("tls_client_key").Value(),
|
||||
"tls_client_ca": section.Key("tls_client_ca").Value(),
|
||||
"tls_skip_verify_insecure": section.Key("tls_skip_verify_insecure").MustBool(false),
|
||||
"use_pkce": section.Key("use_pkce").MustBool(true),
|
||||
"use_refresh_token": section.Key("use_refresh_token").MustBool(false),
|
||||
"allow_assign_grafana_admin": section.Key("allow_assign_grafana_admin").MustBool(false),
|
||||
"auto_login": section.Key("auto_login").MustBool(false),
|
||||
"allowed_groups": section.Key("allowed_groups").Value(),
|
||||
func (s *OAuthStrategy) loadAllSettings() {
|
||||
allProviders := append(ssosettings.AllOAuthProviders, social.GrafanaNetProviderName)
|
||||
for _, provider := range allProviders {
|
||||
settings := s.loadSettingsForProvider(provider)
|
||||
if provider == social.GrafanaNetProviderName {
|
||||
provider = social.GrafanaComProviderName
|
||||
}
|
||||
s.settingsByProvider[provider] = settings
|
||||
}
|
||||
}
|
||||
|
||||
// when empty_scopes parameter exists and is true, overwrite scope with empty value
|
||||
if section.Key("empty_scopes").MustBool(false) {
|
||||
result["scopes"] = []string{}
|
||||
func (s *OAuthStrategy) loadSettingsForProvider(provider string) *social.OAuthInfo {
|
||||
section := s.cfg.SectionWithEnvOverrides("auth." + provider)
|
||||
|
||||
result := &social.OAuthInfo{
|
||||
AllowAssignGrafanaAdmin: section.Key("allow_assign_grafana_admin").MustBool(false),
|
||||
AllowSignup: section.Key("allow_sign_up").MustBool(false),
|
||||
AllowedDomains: util.SplitString(section.Key("allowed_domains").Value()),
|
||||
AllowedGroups: util.SplitString(section.Key("allowed_groups").Value()),
|
||||
ApiUrl: section.Key("api_url").Value(),
|
||||
AuthStyle: section.Key("auth_style").Value(),
|
||||
AuthUrl: section.Key("auth_url").Value(),
|
||||
AutoLogin: section.Key("auto_login").MustBool(false),
|
||||
ClientId: section.Key("client_id").Value(),
|
||||
ClientSecret: section.Key("client_secret").Value(),
|
||||
EmailAttributeName: section.Key("email_attribute_name").Value(),
|
||||
EmailAttributePath: section.Key("email_attribute_path").Value(),
|
||||
EmptyScopes: section.Key("empty_scopes").MustBool(false),
|
||||
Enabled: section.Key("enabled").MustBool(false),
|
||||
GroupsAttributePath: section.Key("groups_attribute_path").Value(),
|
||||
HostedDomain: section.Key("hosted_domain").Value(),
|
||||
Icon: section.Key("icon").Value(),
|
||||
Name: section.Key("name").Value(),
|
||||
RoleAttributePath: section.Key("role_attribute_path").Value(),
|
||||
RoleAttributeStrict: section.Key("role_attribute_strict").MustBool(false),
|
||||
Scopes: util.SplitString(section.Key("scopes").Value()),
|
||||
SignoutRedirectUrl: section.Key("signout_redirect_url").Value(),
|
||||
SkipOrgRoleSync: section.Key("skip_org_role_sync").MustBool(false),
|
||||
TeamIdsAttributePath: section.Key("team_ids_attribute_path").Value(),
|
||||
TeamsUrl: section.Key("teams_url").Value(),
|
||||
TlsClientCa: section.Key("tls_client_ca").Value(),
|
||||
TlsClientCert: section.Key("tls_client_cert").Value(),
|
||||
TlsClientKey: section.Key("tls_client_key").Value(),
|
||||
TlsSkipVerify: section.Key("tls_skip_verify_insecure").MustBool(false),
|
||||
TokenUrl: section.Key("token_url").Value(),
|
||||
UsePKCE: section.Key("use_pkce").MustBool(false),
|
||||
UseRefreshToken: section.Key("use_refresh_token").MustBool(false),
|
||||
Extra: map[string]string{},
|
||||
}
|
||||
|
||||
extraFields := extraKeysByProvider[provider]
|
||||
for _, key := range extraFields {
|
||||
result.Extra[key] = section.Key(key).Value()
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package strategies
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
iniContent = `
|
||||
[auth.generic_oauth]
|
||||
name = OAuth
|
||||
icon = signin
|
||||
enabled = true
|
||||
allow_sign_up = false
|
||||
auto_login = true
|
||||
client_id = test_client_id
|
||||
client_secret = test_client_secret
|
||||
scopes = ["openid", "profile", "email"]
|
||||
empty_scopes = false
|
||||
email_attribute_name = email:primary
|
||||
email_attribute_path = email
|
||||
login_attribute_path = login
|
||||
name_attribute_path = name
|
||||
role_attribute_path = role
|
||||
role_attribute_strict = true
|
||||
groups_attribute_path = groups
|
||||
id_token_attribute_name = id_token
|
||||
team_ids_attribute_path = team_ids
|
||||
auth_style = inheader
|
||||
auth_url = test_auth_url
|
||||
token_url = test_token_url
|
||||
api_url = test_api_url
|
||||
teams_url = test_teams_url
|
||||
allowed_domains = domain1.com
|
||||
allowed_groups =
|
||||
team_ids = first, second
|
||||
allowed_organizations = org1, org2
|
||||
tls_skip_verify_insecure = true
|
||||
tls_client_cert =
|
||||
tls_client_key =
|
||||
tls_client_ca =
|
||||
use_pkce = false
|
||||
allow_assign_grafana_admin = true
|
||||
skip_org_role_sync = true
|
||||
use_refresh_token = true
|
||||
empty_scopes =
|
||||
hosted_domain = test_hosted_domain
|
||||
signout_redirect_url = test_signout_redirect_url
|
||||
`
|
||||
|
||||
expectedOAuthInfo = &social.OAuthInfo{
|
||||
Name: "OAuth",
|
||||
Icon: "signin",
|
||||
Enabled: true,
|
||||
AllowSignup: false,
|
||||
AutoLogin: true,
|
||||
ClientId: "test_client_id",
|
||||
ClientSecret: "test_client_secret",
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
EmptyScopes: false,
|
||||
EmailAttributeName: "email:primary",
|
||||
EmailAttributePath: "email",
|
||||
RoleAttributePath: "role",
|
||||
RoleAttributeStrict: true,
|
||||
GroupsAttributePath: "groups",
|
||||
TeamIdsAttributePath: "team_ids",
|
||||
AuthUrl: "test_auth_url",
|
||||
TokenUrl: "test_token_url",
|
||||
ApiUrl: "test_api_url",
|
||||
TeamsUrl: "test_teams_url",
|
||||
AllowedDomains: []string{"domain1.com"},
|
||||
AllowedGroups: []string{},
|
||||
TlsSkipVerify: true,
|
||||
TlsClientCert: "",
|
||||
TlsClientKey: "",
|
||||
TlsClientCa: "",
|
||||
UsePKCE: false,
|
||||
AuthStyle: "inheader",
|
||||
AllowAssignGrafanaAdmin: true,
|
||||
UseRefreshToken: true,
|
||||
HostedDomain: "test_hosted_domain",
|
||||
SkipOrgRoleSync: true,
|
||||
SignoutRedirectUrl: "test_signout_redirect_url",
|
||||
Extra: map[string]string{
|
||||
"allowed_organizations": "org1, org2",
|
||||
"id_token_attribute_name": "id_token",
|
||||
"login_attribute_path": "login",
|
||||
"name_attribute_path": "name",
|
||||
"team_ids": "first, second",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestGetProviderConfig_EnvVarsOnly(t *testing.T) {
|
||||
setupEnvVars(t)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
strategy := NewOAuthStrategy(cfg)
|
||||
|
||||
result, err := strategy.GetProviderConfig(context.Background(), "generic_oauth")
|
||||
require.NoError(t, err)
|
||||
|
||||
oauthInfo, ok := result.(*social.OAuthInfo)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, expectedOAuthInfo, oauthInfo)
|
||||
}
|
||||
|
||||
func TestGetProviderConfig_IniFileOnly(t *testing.T) {
|
||||
iniFile, err := ini.Load([]byte(iniContent))
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.Raw = iniFile
|
||||
|
||||
strategy := NewOAuthStrategy(cfg)
|
||||
|
||||
result, err := strategy.GetProviderConfig(context.Background(), "generic_oauth")
|
||||
require.NoError(t, err)
|
||||
|
||||
oauthInfo, ok := result.(*social.OAuthInfo)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, expectedOAuthInfo, oauthInfo)
|
||||
}
|
||||
|
||||
func TestGetProviderConfig_EnvVarsOverrideIniFileSettings(t *testing.T) {
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ENABLED", "false")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_SKIP_ORG_ROLE_SYNC", "false")
|
||||
|
||||
iniFile, err := ini.Load([]byte(iniContent))
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.Raw = iniFile
|
||||
|
||||
strategy := NewOAuthStrategy(cfg)
|
||||
|
||||
result, err := strategy.GetProviderConfig(context.Background(), "generic_oauth")
|
||||
require.NoError(t, err)
|
||||
|
||||
oauthInfo, ok := result.(*social.OAuthInfo)
|
||||
require.True(t, ok)
|
||||
|
||||
expectedOAuthInfoWithOverrides := *expectedOAuthInfo
|
||||
expectedOAuthInfoWithOverrides.Enabled = false
|
||||
expectedOAuthInfoWithOverrides.SkipOrgRoleSync = false
|
||||
|
||||
require.Equal(t, expectedOAuthInfoWithOverrides, *oauthInfo)
|
||||
}
|
||||
|
||||
func setupEnvVars(t *testing.T) {
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_NAME", "OAuth")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ICON", "signin")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ENABLED", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP", "false")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_CLIENT_ID", "test_client_id")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET", "test_client_secret")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_SCOPES", `["openid", "profile", "email"]`)
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES", "")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_NAME", "email:primary")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH", "email")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH", "role")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_STRICT", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_GROUPS_ATTRIBUTE_PATH", "groups")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TEAM_IDS_ATTRIBUTE_PATH", "team_ids")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_AUTH_URL", "test_auth_url")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TOKEN_URL", "test_token_url")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_API_URL", "test_api_url")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TEAMS_URL", "test_teams_url")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ALLOWED_DOMAINS", "domain1.com")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ALLOWED_GROUPS", "")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TLS_SKIP_VERIFY_INSECURE", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TLS_CLIENT_CERT", "")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TLS_CLIENT_KEY", "")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TLS_CLIENT_CA", "")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_USE_PKCE", "false")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_AUTH_STYLE", "inheader")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_SKIP_ORG_ROLE_SYNC", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_USE_REFRESH_TOKEN", "true")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_HOSTED_DOMAIN", "test_hosted_domain")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ALLOWED_ORGANIZATIONS", "org1, org2")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_ID_TOKEN_ATTRIBUTE_NAME", "id_token")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH", "login")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH", "name")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_TEAM_IDS", "first, second")
|
||||
t.Setenv("GF_AUTH_GENERIC_OAUTH_SIGNOUT_REDIRECT_URL", "test_signout_redirect_url")
|
||||
}
|
||||
Reference in New Issue
Block a user