mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SAMLSettings: implement settings strategy (#84191)
* add strategy and tests * use settings provider service and remove multiple providers strategy * update codeowners file * reload from settings provider
This commit is contained in:
parent
9b2058f814
commit
66fa310fba
@ -9,10 +9,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ConfigurableOAuthProviders is a list of OAuth providers that can be configured from the API
|
||||
// TODO: make it configurable
|
||||
ConfigurableOAuthProviders = []string{"github", "gitlab", "google", "generic_oauth", "azuread", "okta"}
|
||||
|
||||
AllOAuthProviders = []string{social.GitHubProviderName, social.GitlabProviderName, social.GoogleProviderName, social.GenericOAuthProviderName, social.GrafanaComProviderName, social.AzureADProviderName, social.OktaProviderName}
|
||||
)
|
||||
|
||||
|
66
pkg/services/ssosettings/strategies/saml_strategy.go
Normal file
66
pkg/services/ssosettings/strategies/saml_strategy.go
Normal file
@ -0,0 +1,66 @@
|
||||
package strategies
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ssosettings"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type SAMLStrategy struct {
|
||||
settingsProvider setting.Provider
|
||||
}
|
||||
|
||||
var _ ssosettings.FallbackStrategy = (*SAMLStrategy)(nil)
|
||||
|
||||
func NewSAMLStrategy(settingsProvider setting.Provider) *SAMLStrategy {
|
||||
return &SAMLStrategy{
|
||||
settingsProvider: settingsProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SAMLStrategy) IsMatch(provider string) bool {
|
||||
return provider == "saml"
|
||||
}
|
||||
|
||||
func (s *SAMLStrategy) GetProviderConfig(_ context.Context, provider string) (map[string]any, error) {
|
||||
return s.loadSAMLSettings(), nil
|
||||
}
|
||||
|
||||
func (s *SAMLStrategy) loadSAMLSettings() map[string]any {
|
||||
section := s.settingsProvider.Section("auth.saml")
|
||||
result := map[string]any{
|
||||
"enabled": section.KeyValue("enabled").MustBool(false),
|
||||
"single_logout": section.KeyValue("single_logout").MustBool(false),
|
||||
"allow_sign_up": section.KeyValue("allow_sign_up").MustBool(false),
|
||||
"auto_login": section.KeyValue("auto_login").MustBool(false),
|
||||
"certificate": section.KeyValue("certificate").MustString(""),
|
||||
"certificate_path": section.KeyValue("certificate_path").MustString(""),
|
||||
"private_key": section.KeyValue("private_key").MustString(""),
|
||||
"private_key_path": section.KeyValue("private_key_path").MustString(""),
|
||||
"signature_algorithm": section.KeyValue("signature_algorithm").MustString(""),
|
||||
"idp_metadata": section.KeyValue("idp_metadata").MustString(""),
|
||||
"idp_metadata_path": section.KeyValue("idp_metadata_path").MustString(""),
|
||||
"idp_metadata_url": section.KeyValue("idp_metadata_url").MustString(""),
|
||||
"max_issue_delay": section.KeyValue("max_issue_delay").MustDuration(90 * time.Second),
|
||||
"metadata_valid_duration": section.KeyValue("metadata_valid_duration").MustDuration(48 * time.Hour),
|
||||
"allow_idp_initiated": section.KeyValue("allow_idp_initiated").MustBool(false),
|
||||
"relay_state": section.KeyValue("relay_state").MustString(""),
|
||||
"assertion_attribute_name": section.KeyValue("assertion_attribute_name").MustString(""),
|
||||
"assertion_attribute_login": section.KeyValue("assertion_attribute_login").MustString(""),
|
||||
"assertion_attribute_email": section.KeyValue("assertion_attribute_email").MustString(""),
|
||||
"assertion_attribute_groups": section.KeyValue("assertion_attribute_groups").MustString(""),
|
||||
"assertion_attribute_role": section.KeyValue("assertion_attribute_role").MustString(""),
|
||||
"assertion_attribute_org": section.KeyValue("assertion_attribute_org").MustString(""),
|
||||
"allowed_organizations": section.KeyValue("allowed_organizations").MustString(""),
|
||||
"org_mapping": section.KeyValue("org_mapping").MustString(""),
|
||||
"role_values_editor": section.KeyValue("role_values_editor").MustString(""),
|
||||
"role_values_admin": section.KeyValue("role_values_admin").MustString(""),
|
||||
"role_values_grafana_admin": section.KeyValue("role_values_grafana_admin").MustString(""),
|
||||
"name_id_format": section.KeyValue("name_id_format").MustString(""),
|
||||
"skip_org_role_sync": section.KeyValue("skip_org_role_sync").MustBool(false),
|
||||
"role_values_none": section.KeyValue("role_values_none").MustString(""),
|
||||
}
|
||||
return result
|
||||
}
|
103
pkg/services/ssosettings/strategies/saml_strategy_test.go
Normal file
103
pkg/services/ssosettings/strategies/saml_strategy_test.go
Normal file
@ -0,0 +1,103 @@
|
||||
package strategies
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
iniSAMLContent = `
|
||||
[auth.saml]
|
||||
enabled = true
|
||||
single_logout = true
|
||||
allow_sign_up = true
|
||||
auto_login = false
|
||||
certificate = devenv/docker/blocks/auth/saml-enterprise/cert.crt
|
||||
certificate_path = /path/to/cert
|
||||
private_key = dGhpcyBpcyBteSBwcml2YXRlIGtleSB0aGF0IEkgd2FudCB0byBnZXQgZW5jb2RlZCBpbiBiYXNlIDY0
|
||||
private_key_path = devenv/docker/blocks/auth/saml-enterprise/key.pem
|
||||
signature_algorithm = rsa-sha256
|
||||
idp_metadata = dGhpcyBpcyBteSBwcml2YXRlIGtleSB0aGF0IEkgd2FudCB0byBnZXQgZW5jb2RlZCBpbiBiYXNlIDY0
|
||||
idp_metadata_path = /path/to/metadata
|
||||
idp_metadata_url = http://localhost:8086/realms/grafana/protocol/saml/descriptor
|
||||
max_issue_delay = 90s
|
||||
metadata_valid_duration = 48h
|
||||
allow_idp_initiated = false
|
||||
relay_state = relay_state
|
||||
assertion_attribute_name = name
|
||||
assertion_attribute_login = login
|
||||
assertion_attribute_email = email
|
||||
assertion_attribute_groups = groups
|
||||
assertion_attribute_role = roles
|
||||
assertion_attribute_org = orgs
|
||||
allowed_organizations = org1 org2
|
||||
org_mapping = org1:1:editor, *:2:viewer
|
||||
role_values_editor = editor
|
||||
role_values_admin = admin
|
||||
role_values_grafana_admin = serveradmin
|
||||
name_id_format = urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
|
||||
skip_org_role_sync = false
|
||||
role_values_none = guest disabled
|
||||
`
|
||||
|
||||
expectedSAMLInfo = map[string]any{
|
||||
"enabled": true,
|
||||
"single_logout": true,
|
||||
"allow_sign_up": true,
|
||||
"auto_login": false,
|
||||
"certificate": "devenv/docker/blocks/auth/saml-enterprise/cert.crt",
|
||||
"certificate_path": "/path/to/cert",
|
||||
"private_key": "dGhpcyBpcyBteSBwcml2YXRlIGtleSB0aGF0IEkgd2FudCB0byBnZXQgZW5jb2RlZCBpbiBiYXNlIDY0",
|
||||
"private_key_path": "devenv/docker/blocks/auth/saml-enterprise/key.pem",
|
||||
"signature_algorithm": "rsa-sha256",
|
||||
"idp_metadata": "dGhpcyBpcyBteSBwcml2YXRlIGtleSB0aGF0IEkgd2FudCB0byBnZXQgZW5jb2RlZCBpbiBiYXNlIDY0",
|
||||
"idp_metadata_path": "/path/to/metadata",
|
||||
"idp_metadata_url": "http://localhost:8086/realms/grafana/protocol/saml/descriptor",
|
||||
"max_issue_delay": 90 * time.Second,
|
||||
"metadata_valid_duration": 48 * time.Hour,
|
||||
"allow_idp_initiated": false,
|
||||
"relay_state": "relay_state",
|
||||
"assertion_attribute_name": "name",
|
||||
"assertion_attribute_login": "login",
|
||||
"assertion_attribute_email": "email",
|
||||
"assertion_attribute_groups": "groups",
|
||||
"assertion_attribute_role": "roles",
|
||||
"assertion_attribute_org": "orgs",
|
||||
"allowed_organizations": "org1 org2",
|
||||
"org_mapping": "org1:1:editor, *:2:viewer",
|
||||
"role_values_editor": "editor",
|
||||
"role_values_admin": "admin",
|
||||
"role_values_grafana_admin": "serveradmin",
|
||||
"name_id_format": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
||||
"skip_org_role_sync": false,
|
||||
"role_values_none": "guest disabled",
|
||||
}
|
||||
)
|
||||
|
||||
func TestSAMLIsMatch(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
strategy := NewSAMLStrategy(&setting.OSSImpl{Cfg: cfg})
|
||||
require.True(t, strategy.IsMatch("saml"))
|
||||
require.False(t, strategy.IsMatch("oauth"))
|
||||
}
|
||||
|
||||
func TestSAMLGetProviderConfig(t *testing.T) {
|
||||
configurationFile, err := ini.Load([]byte(iniSAMLContent))
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.Raw = configurationFile
|
||||
|
||||
strategy := NewSAMLStrategy(&setting.OSSImpl{Cfg: cfg})
|
||||
|
||||
result, err := strategy.GetProviderConfig(context.Background(), "saml")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedSAMLInfo, result)
|
||||
}
|
Loading…
Reference in New Issue
Block a user