Backport: Revert changes to oauth behavior to v9.1.x (#55302)

* OAuth: Allow assigning Server Admin (#54780)

* extract errors to errors file

* implement oauth server admin assignment

* add server admin tests

* deduplicate autoAssignOrgRole

* deduplicate strict setting

* deduplicate strict setting

* add support for generic oauth

* add role attribute strict support for generic oauth

* add support for github/gitlab

* assignGrafanaAdmin option is here to stay

* unify similar errors

* add config option

* add okta server admin mapping

* remove never used Company attribute

* unify generic oauth role extract with other methods

* case insensitive role match as in azure

* add ini settings

* add server admin to devenv

* remove duplicate fields

* add documentation to oauth

* fix titlecase test

* implement doc feedback

(cherry picked from commit ef245874da)

* Auth: Restore legacy behavior and add deprecation notice for empty org role in oauth (#55118)

* Auth: Add deprecation notice for empty org role

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>

* fix recasts

* fix azure tests missing logger

* Adding test to gitlab oauth

* Covering more cases

* Cover more options

* Add role attributestrict check fail

* Adding one more edge case test

* Using legacy for gitlab

* Yet another edge case YAEC

* Reverting github oauth to legacy

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Not using token

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Nit.

* Adding warning in docs

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* add warning to generic oauth

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Be more precise

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Adding warning to github oauth

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Adding warning to gitlab oauth

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Adding warning to okta oauth

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Add docs about mapping to AzureAD

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Clarify oauth_skip_org_role_update_sync

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Nit.

* Nit on Azure AD

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Reorder docs index

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Fix typo

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
Co-authored-by: gamab <gabi.mabs@gmail.com>
(cherry picked from commit 00e7324bf6)

* Auth: Allow admins to manually change oauth user role if `oauth_skip_org_role_update_sync` is enabled  (#55182)

* Auth: Allow admins to change oauth user info it it's not synced.

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>

* Update public/app/features/admin/UserAdminPage.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Add missing import

* Simplify init

Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* SAML: Add option to skip org role sync (#55230)

* SAML: Add option to skip org role sync

* Modify frontend accordingly

* Remove update from config option name

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Remove update from config option name

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Fix typo

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
Co-authored-by: gamab <gabi.mabs@gmail.com>
Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
(cherry picked from commit 3e2e9f93b9)

* Update gitlab_oauth_test.go

* Update gitlab_oauth_test.go
This commit is contained in:
Jo
2022-09-19 09:33:47 +02:00
committed by GitHub
parent 93db981c89
commit 5f51a1425b
30 changed files with 886 additions and 370 deletions
@@ -792,8 +792,13 @@ Administrators can increase this if they experience OAuth login state mismatch e
### oauth_skip_org_role_update_sync
Skip forced assignment of OrgID `1` or `auto_assign_org_id` for external logins. Default is `false`.
Use this setting to distribute users with external login to multiple organizations.
Otherwise, the users' organization would get reset on every new login, for example, via AzureAD.
Use this setting to allow users with external login to be manually assigned to multiple organizations.
By default, the users' organization and role is reset on every new login.
> **Warning**: Currently if no organization role mapping is found for a user, Grafana doesn't update the user's organization role.
> With Grafana 10, if `oauth_skip_org_role_update_sync` option is set to `false`, users with no mapping will be
> reset to the default organization role on every login. [See `auto_assign_org_role` option]({{< relref ".#auto_assign_org_role" >}}).
### api_key_max_seconds_to_live
@@ -61,8 +61,8 @@ To enable the Azure AD OAuth2, register your application with Azure AD.
"allowedMemberTypes": [
"User"
],
"description": "Grafana admin Users",
"displayName": "Grafana Admin",
"description": "Grafana org admin Users",
"displayName": "Grafana Org Admin",
"id": "SOME_UNIQUE_ID",
"isEnabled": true,
"lang": null,
@@ -100,6 +100,46 @@ To enable the Azure AD OAuth2, register your application with Azure AD.
1. Click on **Users and Groups** and add Users/Groups to the Grafana roles by using **Add User**.
### Map roles
By default, Azure AD authentication will map users to organization roles based on the most privileged application role assigned to the user in AzureAD.
If no application role is found, the user is assigned the role specified by
[the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
It denies user access if no role or an invalid role is returned.
**On every login** the user organization role will be reset to match AzureAD's application role and
their organization membership will be reset to the default organization.
If Azure AD authentication is not intended to sync user roles and organization membership,
`oauth_skip_org_role_update_sync` should be enabled.
See [configure-grafana]({{< relref "../../configure-grafana#oauth_skip_org_role_update_sync" >}}) for more details.
### Assign server administrator privileges
> Available in Grafana v9.2 and later versions.
If the application role received by Grafana is `GrafanaAdmin`, Grafana grants the user server administrator privileges.
This is useful if you want to grant server administrator privileges to a subset of users.
Grafana also assigns the user the `Admin` role of the default organization.
The setting `allow_assign_grafana_admin` under `[auth.azuread]` must be set to `true` for this to work.
If the setting is set to `false`, the user is assigned the role of `Admin` of the default organization, but not server administrator privileges.
```json
{
"allowedMemberTypes": ["User"],
"description": "Grafana server admin Users",
"displayName": "Grafana Server Admin",
"id": "SOME_UNIQUE_ID",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "GrafanaAdmin"
}
```
## Enable Azure AD OAuth in Grafana
1. Add the following to the [Grafana configuration file]({{< relref "../../configure-grafana/#config-file-locations" >}}):
@@ -117,6 +157,7 @@ token_url = https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token
allowed_domains =
allowed_groups =
role_attribute_strict = false
allow_assign_grafana_admin = false
```
You can also use these environment variables to configure **client_id** and **client_secret**:
@@ -21,9 +21,8 @@ You can configure many different OAuth2 authentication services with Grafana usi
- [Set up OAuth2 with Bitbucket](#set-up-oauth2-with-bitbucket)
- [Set up OAuth2 with Centrify](#set-up-oauth2-with-centrify)
- [Set up OAuth2 with OneLogin](#set-up-oauth2-with-onelogin)
- [JMESPath examples](#jmespath-examples)
- [Role mapping](#role-mapping)
- [Groups mapping](#groups-mapping)
- [Role mapping](#role-mapping)
- [Team synchronization](#team-synchronization)
This callback URL must match the full HTTP address that you use in your browser to access Grafana, but with the suffixed path of `/login/generic_oauth`.
@@ -80,12 +79,6 @@ Grafana determines a user's email address by querying the OAuth provider until i
1. Query the `/emails` endpoint of the OAuth provider's API (configured with `api_url`), then check for the presence of an email address marked as a primary address.
1. If no email address is found in steps (1-4), then the email address of the user is set to an empty string.
### Roles
Grafana checks for the presence of a role using the [JMESPath](http://jmespath.org/examples.html) specified via the `role_attribute_path` configuration option. The JMESPath is applied to the `id_token` first. If there is no match, then the UserInfo endpoint specified via the `api_url` configuration option is tried next. The result after evaluation of the `role_attribute_path` JMESPath expression should be a valid Grafana role, for example, `Viewer`, `Editor` or `Admin`.
For more information, refer to the [JMESPath examples](#jmespath-examples).
### Groups / Teams
Similarly, group mappings are made using [JMESPath](http://jmespath.org/examples.html) with the `groups_attribute_path` configuration option. The `id_token` is attempted first, followed by the UserInfo from the `api_url`. The result of the JMESPath expression should be a string array of groups.
@@ -241,14 +234,32 @@ allowed_organizations =
allowed_organizations =
```
## JMESPath examples
## Role Mapping
Grafana checks for the presence of a role using the [JMESPath](http://jmespath.org/examples.html) specified via the `role_attribute_path` configuration option. The JMESPath is applied to the `id_token` first. If there is no match, then the UserInfo endpoint specified via the `api_url` configuration option is tried next. The result after evaluation of the `role_attribute_path` JMESPath expression should be a valid Grafana role, for example, `Viewer`, `Editor` or `Admin`.
For more information, refer to the [JMESPath examples](#jmespath-examples).
> **Warning**: Currently if no organization role mapping is found for a user, Grafana doesn't
> update the user's organization role. This is going to change in Grafana 10. To avoid overriding manually set roles,
> enable the `oauth_skip_org_role_update_sync` option.
> See [configure-grafana]({{< relref "../../configure-grafana#oauth_skip_org_role_update_sync" >}}) for more information.
On first login, if the`role_attribute_path` property does not return a role, then the user is assigned the role
specified by [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
It denies user access if no role or an invalid role is returned.
> **Warning**: With Grafana 10, **on every login**, if the`role_attribute_path` property does not return a role,
> then the user is assigned the role specified by
> [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
### JMESPath examples
#### Map user organization role
To ease configuration of a proper JMESPath expression, you can test/evaluate expressions with custom payloads at http://jmespath.org/.
### Role mapping
If  the`role_attribute_path` property does not return a role, then the user is assigned the `Viewer` role by default. You can disable the role assignment by setting `role_attribute_strict = true`. It denies user access if no role or an invalid role is returned.
**Basic example:**
In the following example user will get `Editor` as role when authenticating. The value of the property `role` will be the resulting role if the role is a proper Grafana role, i.e. `Viewer`, `Editor` or `Admin`.
@@ -296,7 +307,28 @@ Config:
role_attribute_path = contains(info.roles[*], 'admin') && 'Admin' || contains(info.roles[*], 'editor') && 'Editor' || 'Viewer'
```
### Groups mapping
#### Map server administrator privileges
> Available in Grafana v9.2 and later versions.
If the application role received by Grafana is `GrafanaAdmin`, Grafana grants the user server administrator privileges.
This is useful if you want to grant server administrator privileges to a subset of users.
Grafana also assigns the user the `Admin` role of the default organization.
The setting `allow_assign_grafana_admin` under `[auth.generic_oauth]` must be set to `true` for this to work.
If the setting is set to `false`, the user is assigned the role of `Admin` of the default organization, but not server administrator privileges.
```ini
allow_assign_grafana_admin = true
```
Example:
```ini
role_attribute_path = contains(info.roles[*], 'admin') && 'GrafanaAdmin' || contains(info.roles[*], 'editor') && 'Editor' || 'Viewer'
```
## Team synchronization
> Available in Grafana Enterprise v8.1 and later versions.
@@ -109,6 +109,20 @@ For the path lookup, Grafana uses JSON obtained from querying GitHub's API [`/ap
The result of evaluating the `role_attribute_path` JMESPath expression must be a valid Grafana role, for example, `Viewer`, `Editor` or `Admin`. For more information about roles and permissions in Grafana, refer to [Roles and permissions]({{< relref "../../../administration/roles-and-permissions/" >}}).
> **Warning**: Currently if no organization role mapping is found for a user, Grafana doesn't
> update the user's organization role. This is going to change in Grafana 10. To avoid overriding manually set roles,
> enable the `oauth_skip_org_role_update_sync` option.
> See [configure-grafana]({{< relref "../../configure-grafana#oauth_skip_org_role_update_sync" >}}) for more information.
On first login, if the`role_attribute_path` property does not return a role, then the user is assigned the role
specified by [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
It denies user access if no role or an invalid role is returned.
> **Warning**: With Grafana 10, **on every login**, if the`role_attribute_path` property does not return a role,
> then the user is assigned the role specified by
> [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
An example Query could look like the following:
```bash
@@ -130,6 +144,27 @@ role_attribute_path = contains(groups[*], '@github/example-group') && 'Editor' |
Note: If a match is found in other fields, teams will be ignored.
#### Map server administrator privileges
> Available in Grafana v9.2 and later versions.
If the application role received by Grafana is `GrafanaAdmin`, Grafana grants the user server administrator privileges.
This is useful if you want to grant server administrator privileges to a subset of users.
Grafana also assigns the user the `Admin` role of the default organization.
The setting `allow_assign_grafana_admin` under `[auth.github]` must be set to `true` for this to work.
If the setting is set to `false`, the user is assigned the role of `Admin` of the default organization, but not server administrator privileges.
```ini
allow_assign_grafana_admin = true
```
Example:
```ini
role_attribute_path = [login==octocat] && 'GrafanaAdmin' || 'Viewer'
```
### Team Sync (Enterprise only)
> Only available in Grafana Enterprise v6.3+
@@ -58,6 +58,9 @@ auth_url = https://gitlab.com/oauth/authorize
token_url = https://gitlab.com/oauth/token
api_url = https://gitlab.com/api/v4
allowed_groups =
role_attribute_path =
role_attribute_strict = false
allow_assign_grafana_admin = false
```
You may have to set the `root_url` option of `[server]` for the callback URL to be
@@ -102,7 +105,7 @@ characters. Make sure you always use the group or subgroup name as it appears
in the URL of the group or subgroup.
Here's a complete example with `allow_sign_up` enabled, with access limited to
the `example` and `foo/bar` groups. The example also promotes all GitLab Admins to Grafana Admins:
the `example` and `foo/bar` groups. The example also promotes all GitLab Admins to Grafana organization admins:
```ini
[auth.gitlab]
@@ -116,6 +119,8 @@ token_url = https://gitlab.com/oauth/token
api_url = https://gitlab.com/api/v4
allowed_groups = example, foo/bar
role_attribute_path = is_admin && 'Admin' || 'Viewer'
role_attribute_strict = true
allow_assign_grafana_admin = false
```
### Map roles
@@ -124,9 +129,23 @@ You can use GitLab OAuth to map roles. During mapping, Grafana checks for the pr
For the path lookup, Grafana uses JSON obtained from querying GitLab's API [`/api/v4/user`](https://docs.gitlab.com/ee/api/users.html#list-current-user-for-normal-users) endpoint and a `groups` key containing all of the user's teams. The result of evaluating the `role_attribute_path` JMESPath expression must be a valid Grafana role, for example, `Viewer`, `Editor` or `Admin`. For more information about roles and permissions in Grafana, refer to [Roles and permissions]({{< relref "../../../administration/roles-and-permissions/" >}}).
> **Warning**: Currently if no organization role mapping is found for a user, Grafana doesn't
> update the user's organization role. This is going to change in Grafana 10. To avoid overriding manually set roles,
> enable the `oauth_skip_org_role_update_sync` option.
> See [configure-grafana]({{< relref "../../configure-grafana#oauth_skip_org_role_update_sync" >}}) for more information.
On first login, if the`role_attribute_path` property does not return a role, then the user is assigned the role
specified by [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
It denies user access if no role or an invalid role is returned.
> **Warning**: With Grafana 10, **on every login**, if the`role_attribute_path` property does not return a role,
> then the user is assigned the role specified by
> [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
An example Query could look like the following:
```bash
```ini
role_attribute_path = is_admin && 'Admin' || 'Viewer'
```
@@ -139,12 +158,33 @@ Groups can also be used to map roles. Group name (lowercased and unique) is used
For instance, if you have a group with display name 'Example-Group' you can use the following snippet to
ensure those members inherit the role 'Editor'.
```bash
```ini
role_attribute_path = contains(groups[*], 'example-group') && 'Editor' || 'Viewer'
```
Note: If a match is found in other fields, groups will be ignored.
#### Map server administrator privileges
> Available in Grafana v9.2 and later versions.
If the application role received by Grafana is `GrafanaAdmin`, Grafana grants the user server administrator privileges.
This is useful if you want to grant server administrator privileges to a subset of users.
Grafana also assigns the user the `Admin` role of the default organization.
The setting `allow_assign_grafana_admin` under `[auth.gitlab]` must be set to `true` for this to work.
If the setting is set to `false`, the user is assigned the role of `Admin` of the default organization, but not server administrator privileges.
```ini
allow_assign_grafana_admin = true
```
Example:
```ini
role_attribute_path = is_admin && 'GrafanaAdmin' || 'Viewer'
```
### Team Sync (Enterprise only)
> Only available in Grafana Enterprise v6.4+
@@ -75,8 +75,43 @@ Grafana can attempt to do role mapping through Okta OAuth. In order to achieve t
Grafana uses JSON obtained from querying the `/userinfo` endpoint for the path lookup. The result after evaluating the `role_attribute_path` JMESPath expression needs to be a valid Grafana role, i.e. `Viewer`, `Editor` or `Admin`. For more information about roles and permissions in Grafana, refer to [Roles and permissions]({{< relref "../../../administration/roles-and-permissions/" >}}).
> **Warning**: Currently if no organization role mapping is found for a user, Grafana doesn't
> update the user's organization role. This is going to change in Grafana 10. To avoid overriding manually set roles,
> enable the `oauth_skip_org_role_update_sync` option.
> See [configure-grafana]({{< relref "../../configure-grafana#oauth_skip_org_role_update_sync" >}}) for more information.
On first login, if the`role_attribute_path` property does not return a role, then the user is assigned the role
specified by [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
It denies user access if no role or an invalid role is returned.
> **Warning**: With Grafana 10, **on every login**, if the`role_attribute_path` property does not return a role,
> then the user is assigned the role specified by
> [the `auto_assign_org_role` option]({{< relref "../../configure-grafana#auto_assign_org_role" >}}).
Read about how to [add custom claims](https://developer.okta.com/docs/guides/customize-tokens-returned-from-okta/add-custom-claim/) to the user info in Okta. Also, check Generic OAuth page for [JMESPath examples]({{< relref "generic-oauth/#jmespath-examples" >}}).
#### Map server administrator privileges
> Available in Grafana v9.2 and later versions.
If the application role received by Grafana is `GrafanaAdmin`, Grafana grants the user server administrator privileges.
This is useful if you want to grant server administrator privileges to a subset of users.
Grafana also assigns the user the `Admin` role of the default organization.
The setting `allow_assign_grafana_admin` under `[auth.okta]` must be set to `true` for this to work.
If the setting is set to `false`, the user is assigned the role of `Admin` of the default organization, but not server administrator privileges.
```ini
allow_assign_grafana_admin = true
```
Example:
```ini
role_attribute_path = contains(groups[*], 'admin') && 'GrafanaAdmin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'
```
### Team Sync (Enterprise only)
Map your Okta groups to teams in Grafana so that your users will automatically be added to
@@ -297,7 +297,7 @@ For more information about roles and permissions in Grafana, refer to [Roles and
Example configuration:
```bash
```ini
[auth.saml]
assertion_attribute_role = role
role_values_editor = editor, developer
@@ -307,6 +307,17 @@ role_values_grafana_admin = superadmin
**Important**: When role sync is configured, any changes of user roles and organization membership made manually in Grafana will be overwritten on next user login. Assign user organizations and roles in the IdP instead.
> **Note:** Available in Grafana version 9.2 and later.
If you don't want user organizations and roles to be synchronized with the IdP, you can use the `skip_org_role_sync` configuration option.
Example configuration:
```ini
[auth.saml]
skip_org_role_sync = true
```
### Configure organization mapping
> **Note:** Available in Grafana version 7.0 and later.