Describe the problem
The Overview page of the DB Console will crash despite the user having the permissions required to view the page.
This occurs when the logged-in SQL user has MODIFYSQLCLUSTERSETTING but lacks
VIEWCLUSTERSETTING or MODIFYCLUSTERSETTING. The Settings API returns a filtered set of
cluster settings that excludes "version", and the UI crashes trying to access it as it never expects the value to be null.
To Reproduce
- Spin up a cockroach cluster (personally I just used cockroach demo) and connect to it
- Run:
CREATE USER testuser WITH PASSWORD 'abcd';
GRANT SYSTEM VIEWACTIVITY TO testuser;
GRANT SYSTEM MODIFYSQLCLUSTERSETTING TO testuser;
- Attempt to log in and see the Overview page does not render
- There will be a trace in the console similar to:
bundle.js:5033 TypeError: Cannot read properties of undefined (reading 'value')
at bundle.js:10086:36129
at bundle.js:9986:4310
at bundle.js:9986:3728
at bundle.js:9986:4449
at bundle.js:9986:3728
at bundle.js:9986:4417
at bundle.js:9986:3728
at bundle.js:9986:4417
at bundle.js:9986:3728
at Ue.mapToProps (bundle.js:10124:4574)
Workaround:
- Additionally run:
GRANT SYSTEM VIEWCLUSTERSETTING TO testuser;
- Refresh the page, Overview loads as expected.
Expected behavior
The Overview page should load, as the user has the relevant permissions.
Additional data / screenshots
Investigation
The Settings endpoint (pkg/server/admin.go, lines 1957-2032) queries crdb_internal.cluster_settings
as the logged-in user. The virtual table (pkg/sql/crdb_internal.go, lines 2031-2082) checks
privileges in order:
MODIFYCLUSTERSETTING or VIEWCLUSTERSETTING - all settings returned (includes "version")
MODIFYSQLCLUSTERSETTING only - only sql.defaults.* settings returned ("version" excluded)
- None of the above - InsufficientPrivilege error
// crdb_internal.go line 2032
hasModify, err := p.HasGlobalPrivilegeOrRoleOption(ctx, privilege.MODIFYCLUSTERSETTING)
if err != nil {
return err
}
canViewAll := hasModify
if !canViewAll {
canViewAll, err = p.HasGlobalPrivilegeOrRoleOption(ctx, privilege.VIEWCLUSTERSETTING)
if err != nil {
return err
}
}
canViewSqlOnly := false
if !canViewAll {
canViewSqlOnly, err = p.HasGlobalPrivilegeOrRoleOption(ctx, privilege.MODIFYSQLCLUSTERSETTING)
if err != nil {
return err
}
}
if !canViewAll && !canViewSqlOnly {
return pgerror.Newf(pgcode.InsufficientPrivilege,
"only users with %s, %s or %s system privileges are allowed to read "+
"crdb_internal.cluster_settings", privilege.MODIFYCLUSTERSETTING, privilege.MODIFYSQLCLUSTERSETTING, privilege.VIEWCLUSTERSETTING)
}
In the case of insufficient privilege, the handler in admin.go catches the error and correctly falls back to
ConsoleKeys(), which includes "version". But in case 2, the query succeeds with
a filtered result set, meaning err is nil, and the fallback block is never entered:
// admin.go line 1997
if err != nil {
if pgerror.GetPGCode(err) != pgcode.InsufficientPrivilege {
return nil, srverrors.ServerError(ctx, err)
}
// VIEWACTIVITY check and ConsoleKeys() fallback live here
// but are never reached when MODIFYSQLCLUSTERSETTING made the query succeed
}
It assumes that no error means all settings were returned, which is false if the user has VIEWACTIVITY and
MODIFYSQLCLUSTERSETTING, but not VIEWCLUSTERSETTING.
On the frontend, the selector selectClusterSettingVersion in
/ui/workspaces/db-console/src/redux/clusterSettings/clusterSettings.selectors.ts accesses settings["version"].value without handling a missing key.
export const selectClusterSettingVersion = createSelector(
selectClusterSettings,
(settings): string => {
if (!settings) {
return "";
}
return settings["version"].value; // <--- crashes if "version" is missing
},
);
Other selectors in the same file use settings["version"]?.value || "", but this one doesn't.
Jira issue: CRDB-61392
Describe the problem
The Overview page of the DB Console will crash despite the user having the permissions required to view the page.
This occurs when the logged-in SQL user has
MODIFYSQLCLUSTERSETTINGbut lacksVIEWCLUSTERSETTINGorMODIFYCLUSTERSETTING. The Settings API returns a filtered set ofcluster settings that excludes "version", and the UI crashes trying to access it as it never expects the value to be null.
To Reproduce
Workaround:
GRANT SYSTEM VIEWCLUSTERSETTING TO testuser;Expected behavior
The Overview page should load, as the user has the relevant permissions.
Additional data / screenshots
Investigation
The Settings endpoint (
pkg/server/admin.go, lines 1957-2032) queriescrdb_internal.cluster_settingsas the logged-in user. The virtual table (
pkg/sql/crdb_internal.go, lines 2031-2082) checksprivileges in order:
MODIFYCLUSTERSETTINGorVIEWCLUSTERSETTING- all settings returned (includes "version")MODIFYSQLCLUSTERSETTINGonly - only sql.defaults.* settings returned ("version" excluded)In the case of insufficient privilege, the handler in
admin.gocatches the error and correctly falls back toConsoleKeys(), which includes "version". But in case 2, the query succeeds with
a filtered result set, meaning
erris nil, and the fallback block is never entered:It assumes that no error means all settings were returned, which is false if the user has
VIEWACTIVITYandMODIFYSQLCLUSTERSETTING, but notVIEWCLUSTERSETTING.On the frontend, the selector selectClusterSettingVersion in
/ui/workspaces/db-console/src/redux/clusterSettings/clusterSettings.selectors.tsaccessessettings["version"].valuewithout handling a missing key.Other selectors in the same file use
settings["version"]?.value || "", but this one doesn't.Jira issue: CRDB-61392