mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
ebcbb66548
commit
3e2e9f93b9
@ -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"],
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ export type {
|
||||
BootData,
|
||||
OAuth,
|
||||
OAuthSettings,
|
||||
AuthSettings,
|
||||
GrafanaConfig,
|
||||
BuildInfo,
|
||||
LicenseInfo,
|
||||
|
@ -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 = {
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user