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>
This commit is contained in:
Jo 2022-09-15 18:06:09 +02:00 committed by GitHub
parent ebcbb66548
commit 3e2e9f93b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 6 deletions

View File

@ -1028,9 +1028,8 @@ exports[`better eslint`] = {
],
"packages/grafana-runtime/src/config.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"packages/grafana-runtime/src/services/AngularLoader.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],

View File

@ -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.

View File

@ -153,6 +153,7 @@ export interface GrafanaConfig {
isPublicDashboardView: boolean;
datasources: { [str: string]: DataSourceInstanceSettings };
panels: { [key: string]: PanelPluginMeta };
auth: AuthSettings;
minRefreshInterval: string;
appSubUrl: string;
windowTitlePrefix: string;
@ -214,3 +215,8 @@ export interface GrafanaConfig {
rudderstackSdkUrl: string | undefined;
rudderstackConfigUrl: string | undefined;
}
export interface AuthSettings {
OAuthSkipOrgRoleUpdateSync?: boolean;
SAMLSkipOrgRoleSync?: boolean;
}

View File

@ -41,6 +41,7 @@ export type {
BootData,
OAuth,
OAuthSettings,
AuthSettings,
GrafanaConfig,
BuildInfo,
LicenseInfo,

View File

@ -1,6 +1,7 @@
import { merge } from 'lodash';
import {
AuthSettings,
BootData,
BuildInfo,
createTheme,
@ -27,6 +28,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
isPublicDashboardView: boolean;
datasources: { [str: string]: DataSourceInstanceSettings } = {};
panels: { [key: string]: PanelPluginMeta } = {};
auth: AuthSettings = {};
minRefreshInterval = '';
appUrl = '';
appSubUrl = '';
@ -107,7 +109,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
pluginAdminExternalManageEnabled = false;
pluginCatalogHiddenPlugins: string[] = [];
expressionsEnabled = false;
customTheme?: any;
customTheme?: undefined;
awsAllowedAuthProviders: string[] = [];
awsAssumeRoleEnabled = false;
azure: AzureSettings = {

View File

@ -136,6 +136,10 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
"editorsCanAdmin": hs.Cfg.EditorsCanAdmin,
"disableSanitizeHtml": hs.Cfg.DisableSanitizeHtml,
"pluginsToPreload": pluginsToPreload,
"auth": map[string]interface{}{
"OAuthSkipOrgRoleUpdateSync": hs.Cfg.OAuthSkipOrgRoleUpdateSync,
"SAMLSkipOrgRoleSync": hs.Cfg.SectionWithEnvOverrides("auth.saml").Key("skip_org_role_sync").MustBool(false),
},
"buildInfo": map[string]interface{}{
"hideVersion": hideVersion,
"version": version,

View File

@ -4,6 +4,7 @@ import { connect, ConnectedProps } from 'react-redux';
import { NavModelItem } from '@grafana/data';
import { featureEnabled } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page';
import config from 'app/core/config';
import { contextSrv } from 'app/core/core';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { StoreState, UserDTO, UserOrg, UserSession, SyncInfo, UserAdminError, AccessControlAction } from 'app/types';
@ -38,6 +39,8 @@ interface OwnProps extends GrafanaRouteComponentProps<{ id: string }> {
error?: UserAdminError;
}
const SyncedOAuthLabels: string[] = ['GitHub', 'GitLab', 'AzureAD', 'OAuth'];
export class UserAdminPage extends PureComponent<Props> {
async componentDidMount() {
const { match, loadAdminUserPage } = this.props;
@ -105,6 +108,13 @@ export class UserAdminPage extends PureComponent<Props> {
const isLDAPUser = user && user.isExternal && user.authLabels && user.authLabels.includes('LDAP');
const canReadSessions = contextSrv.hasPermission(AccessControlAction.UsersAuthTokenList);
const canReadLDAPStatus = contextSrv.hasPermission(AccessControlAction.LDAPStatusRead);
const isOAuthUserWithSkippableSync =
user?.isExternal && user?.authLabels?.some((r) => SyncedOAuthLabels.includes(r));
const isSAMLUser = user?.isExternal && user?.authLabels?.includes('SAML');
const isUserSynced =
(user?.isExternal && !(isOAuthUserWithSkippableSync || isSAMLUser)) ||
(!config.auth.OAuthSkipOrgRoleUpdateSync && isOAuthUserWithSkippableSync) ||
(!config.auth.SAMLSkipOrgRoleSync && isSAMLUser);
const pageNav: NavModelItem = {
text: user?.login ?? '',
@ -137,7 +147,7 @@ export class UserAdminPage extends PureComponent<Props> {
<UserOrgs
user={user}
orgs={orgs}
isExternalUser={user?.isExternal}
isExternalUser={isUserSynced}
onOrgRemove={this.onOrgRemove}
onOrgRoleChange={this.onOrgRoleChange}
onOrgAdd={this.onOrgAdd}