grafana/pkg/services/ssosettings/strategies/oauth_strategy_test.go
Mathieu Parent b8c9ae0eb7
OIDC: Support Generic OAuth org to role mappings (#87394)
* Social: link to OrgRoleMapper

* OIDC: support Generic Oauth org to role mappings

Fixes: #73448
Signed-off-by: Mathieu Parent <math.parent@gmail.com>

* Handle when getAllOrgs fails in the org_role_mapper

* Add more tests

* OIDC: ensure orgs are evaluated from API when not from token

Signed-off-by: Mathieu Parent <math.parent@gmail.com>

* OIDC: ensure AutoAssignOrg is applied with OrgMapping without RoleAttributeStrict

Signed-off-by: Mathieu Parent <math.parent@gmail.com>

* Extend docs

* Fix test, lint

---------

Signed-off-by: Mathieu Parent <math.parent@gmail.com>
Co-authored-by: Mihaly Gyongyosi <mgyongyosi@users.noreply.github.com>
2024-05-23 09:55:45 +02:00

282 lines
8.2 KiB
Go

package strategies
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/setting"
)
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
org_attribute_path = groups
org_mapping = Group1:*:Editor
`
expectedOAuthInfo = map[string]any{
"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",
"role_attribute_path": "role",
"role_attribute_strict": true,
"groups_attribute_path": "groups",
"team_ids_attribute_path": "team_ids",
"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": "",
"tls_skip_verify_insecure": true,
"tls_client_cert": "",
"tls_client_key": "",
"tls_client_ca": "",
"use_pkce": false,
"auth_style": "inheader",
"allow_assign_grafana_admin": true,
"use_refresh_token": true,
"hosted_domain": "test_hosted_domain",
"skip_org_role_sync": true,
"signout_redirect_url": "test_signout_redirect_url",
"allowed_organizations": "org1, org2",
"id_token_attribute_name": "id_token",
"login_attribute_path": "login",
"name_attribute_path": "name",
"team_ids": "first, second",
"org_attribute_path": "groups",
"org_mapping": "Group1:*:Editor",
}
)
func TestGetProviderConfig(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)
require.Equal(t, expectedOAuthInfo, result)
}
func TestGetProviderConfig_ExtraFields(t *testing.T) {
iniWithExtraFields := `
[auth.azuread]
force_use_graph_api = true
allowed_organizations = org1, org2
[auth.github]
team_ids = first, second
allowed_organizations = org1, org2
[auth.generic_oauth]
name_attribute_path = name
login_attribute_path = login
id_token_attribute_name = id_token
team_ids = first, second
allowed_organizations = org1, org2
[auth.grafana_com]
enabled = true
allowed_organizations = org1, org2
[auth.google]
validate_hd = true
`
iniFile, err := ini.Load([]byte(iniWithExtraFields))
require.NoError(t, err)
cfg := setting.NewCfg()
cfg.Raw = iniFile
strategy := NewOAuthStrategy(cfg)
t.Run(social.AzureADProviderName, func(t *testing.T) {
result, err := strategy.GetProviderConfig(context.Background(), social.AzureADProviderName)
require.NoError(t, err)
require.Equal(t, true, result["force_use_graph_api"])
require.Equal(t, "org1, org2", result["allowed_organizations"])
})
t.Run(social.GitHubProviderName, func(t *testing.T) {
result, err := strategy.GetProviderConfig(context.Background(), social.GitHubProviderName)
require.NoError(t, err)
require.Equal(t, "first, second", result["team_ids"])
require.Equal(t, "org1, org2", result["allowed_organizations"])
})
t.Run(social.GenericOAuthProviderName, func(t *testing.T) {
result, err := strategy.GetProviderConfig(context.Background(), social.GenericOAuthProviderName)
require.NoError(t, err)
require.Equal(t, "first, second", result["team_ids"])
require.Equal(t, "org1, org2", result["allowed_organizations"])
require.Equal(t, "name", result["name_attribute_path"])
require.Equal(t, "login", result["login_attribute_path"])
require.Equal(t, "id_token", result["id_token_attribute_name"])
})
t.Run(social.GrafanaComProviderName, func(t *testing.T) {
result, err := strategy.GetProviderConfig(context.Background(), social.GrafanaComProviderName)
require.NoError(t, err)
require.Equal(t, "org1, org2", result["allowed_organizations"])
})
t.Run(social.GoogleProviderName, func(t *testing.T) {
result, err := strategy.GetProviderConfig(context.Background(), social.GoogleProviderName)
require.NoError(t, err)
require.Equal(t, true, result["validate_hd"])
})
}
// TestGetProviderConfig_GrafanaComGrafanaNet tests that the connector is setup using the correct section and it supports
// the legacy settings for the provider (auth.grafananet section). The test cases are based on the current behavior of the
// SocialService's ProvideService method (TestSocialService_ProvideService_GrafanaComGrafanaNet).
func TestGetProviderConfig_GrafanaComGrafanaNet(t *testing.T) {
testCases := []struct {
name string
rawIniContent string
expectedGrafanaComSettings map[string]any
}{
{
name: "should setup the connector using auth.grafana_com section if it is enabled",
rawIniContent: `
[auth.grafana_com]
enabled = true
client_id = grafanaComClientId
[auth.grafananet]
enabled = false
client_id = grafanaNetClientId`,
expectedGrafanaComSettings: map[string]any{
"enabled": true,
"client_id": "grafanaComClientId",
},
},
{
name: "should setup the connector using auth.grafananet section if it is enabled",
rawIniContent: `
[auth.grafana_com]
enabled = false
client_id = grafanaComClientId
[auth.grafananet]
enabled = true
client_id = grafanaNetClientId`,
expectedGrafanaComSettings: map[string]any{
"enabled": true,
"client_id": "grafanaNetClientId",
},
},
{
name: "should setup the connector using auth.grafana_com section if both are enabled",
rawIniContent: `
[auth.grafana_com]
enabled = true
client_id = grafanaComClientId
[auth.grafananet]
enabled = true
client_id = grafanaNetClientId`,
expectedGrafanaComSettings: map[string]any{
"enabled": true,
"client_id": "grafanaComClientId",
},
},
{
name: "should not setup the connector when both are disabled",
rawIniContent: `
[auth.grafana_com]
enabled = false
client_id = grafanaComClientId
[auth.grafananet]
enabled = false
client_id = grafanaNetClientId`,
expectedGrafanaComSettings: map[string]any{
"enabled": false,
"client_id": "grafanaComClientId",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
iniFile, err := ini.Load([]byte(tc.rawIniContent))
require.NoError(t, err)
cfg := setting.NewCfg()
cfg.Raw = iniFile
strategy := NewOAuthStrategy(cfg)
actualConfig, err := strategy.GetProviderConfig(context.Background(), "grafana_com")
require.NoError(t, err)
for key, value := range tc.expectedGrafanaComSettings {
require.Equal(t, value, actualConfig[key], "Difference in key: %s. Expected: %v, got: %v", key, value, actualConfig[key])
}
})
}
}