@@ -24,6 +24,7 @@ import (
24
24
25
25
"github.com/cockroachdb/apd/v3"
26
26
"github.com/cockroachdb/cockroach/pkg/base"
27
+ "github.com/cockroachdb/cockroach/pkg/clusterversion"
27
28
"github.com/cockroachdb/cockroach/pkg/config/zonepb"
28
29
"github.com/cockroachdb/cockroach/pkg/jobs"
29
30
"github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
@@ -46,6 +47,7 @@ import (
46
47
"github.com/cockroachdb/cockroach/pkg/sql/catalog/colinfo"
47
48
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
48
49
"github.com/cockroachdb/cockroach/pkg/sql/parser"
50
+ "github.com/cockroachdb/cockroach/pkg/sql/privilege"
49
51
"github.com/cockroachdb/cockroach/pkg/sql/roleoption"
50
52
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
51
53
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
@@ -1839,9 +1841,27 @@ func (s *adminServer) Settings(
1839
1841
}
1840
1842
1841
1843
if ! hasModify && ! hasView {
1842
- return nil , status .Errorf (
1843
- codes .PermissionDenied , "this operation requires either %s or %s role options" ,
1844
- roleoption .VIEWCLUSTERSETTING , roleoption .MODIFYCLUSTERSETTING )
1844
+ if s .st .Version .IsActive (ctx , clusterversion .SystemPrivilegesTable ) {
1845
+ hasViewSystemPrivilege , err := s .checkHasSystemPrivilege (ctx , user , "VIEWCLUSTERSETTING" )
1846
+ if err != nil {
1847
+ return nil , err
1848
+ }
1849
+
1850
+ hasModifystemPrivilege , err := s .checkHasSystemPrivilege (ctx , user , "MODIFYCLUSTERSETTING" )
1851
+ if err != nil {
1852
+ return nil , err
1853
+ }
1854
+
1855
+ if ! hasViewSystemPrivilege && ! hasModifystemPrivilege {
1856
+ return nil , status .Errorf (
1857
+ codes .PermissionDenied , "this operation requires either %s or %s system privileges" ,
1858
+ privilege .VIEWCLUSTERSETTING , privilege .MODIFYCLUSTERSETTING )
1859
+ }
1860
+ } else {
1861
+ return nil , status .Errorf (
1862
+ codes .PermissionDenied , "this operation requires either %s or %s role options" ,
1863
+ roleoption .VIEWCLUSTERSETTING , roleoption .MODIFYCLUSTERSETTING )
1864
+ }
1845
1865
}
1846
1866
}
1847
1867
@@ -3411,6 +3431,7 @@ func (s *adminServer) dialNode(
3411
3431
// have admin privileges.
3412
3432
type adminPrivilegeChecker struct {
3413
3433
ie * sql.InternalExecutor
3434
+ st * cluster.Settings
3414
3435
}
3415
3436
3416
3437
// requireAdminUser's error return is a gRPC error.
@@ -3440,9 +3461,21 @@ func (c *adminPrivilegeChecker) requireViewActivityPermission(ctx context.Contex
3440
3461
}
3441
3462
3442
3463
if ! hasViewActivity {
3443
- return status .Errorf (
3444
- codes .PermissionDenied , "this operation requires the %s role option" ,
3445
- roleoption .VIEWACTIVITY )
3464
+ hasSystemPrivilege , err := c .checkHasSystemPrivilege (ctx , userName , "VIEWACTIVITY" )
3465
+ if err != nil {
3466
+ return err
3467
+ }
3468
+ if c .st .Version .IsActive (ctx , clusterversion .SystemPrivilegesTable ) {
3469
+ if ! hasSystemPrivilege {
3470
+ return status .Errorf (
3471
+ codes .PermissionDenied , "this operation requires the %s system privilege" ,
3472
+ privilege .VIEWACTIVITY )
3473
+ }
3474
+ } else {
3475
+ return status .Errorf (
3476
+ codes .PermissionDenied , "this operation requires the %s role option" ,
3477
+ roleoption .VIEWACTIVITY )
3478
+ }
3446
3479
}
3447
3480
}
3448
3481
return nil
@@ -3462,13 +3495,29 @@ func (c *adminPrivilegeChecker) requireViewActivityOrViewActivityRedactedPermiss
3462
3495
return serverError (ctx , err )
3463
3496
}
3464
3497
3465
- if ! hasViewActivity {
3466
- hasViewActivityRedacted , err := c .hasRoleOption (ctx , userName , roleoption .VIEWACTIVITYREDACTED )
3467
- if err != nil {
3468
- return serverError (ctx , err )
3469
- }
3498
+ hasViewActivityRedacted , err := c .hasRoleOption (ctx , userName , roleoption .VIEWACTIVITYREDACTED )
3499
+ if err != nil {
3500
+ return serverError (ctx , err )
3501
+ }
3502
+
3503
+ if ! hasViewActivity && ! hasViewActivityRedacted {
3504
+ if c .st .Version .IsActive (ctx , clusterversion .SystemPrivilegesTable ) {
3505
+ hasVASystemPrivilege , err := c .checkHasSystemPrivilege (ctx , userName , "VIEWACTIVITY" )
3506
+ if err != nil {
3507
+ return err
3508
+ }
3509
+
3510
+ hasVARSystemPrivilege , err := c .checkHasSystemPrivilege (ctx , userName , "VIEWACTIVITYREDACTED" )
3511
+ if err != nil {
3512
+ return err
3513
+ }
3470
3514
3471
- if ! hasViewActivityRedacted {
3515
+ if ! hasVASystemPrivilege && ! hasVARSystemPrivilege {
3516
+ return status .Errorf (
3517
+ codes .PermissionDenied , "this operation requires the %s or %s system privilege" ,
3518
+ privilege .VIEWACTIVITY , privilege .VIEWACTIVITYREDACTED )
3519
+ }
3520
+ } else {
3472
3521
return status .Errorf (
3473
3522
codes .PermissionDenied , "this operation requires the %s or %s role options" ,
3474
3523
roleoption .VIEWACTIVITY , roleoption .VIEWACTIVITYREDACTED )
@@ -3499,6 +3548,17 @@ func (c *adminPrivilegeChecker) requireViewActivityAndNoViewActivityRedactedPerm
3499
3548
codes .PermissionDenied , "this operation requires %s role option and is not allowed for %s role option" ,
3500
3549
roleoption .VIEWACTIVITY , roleoption .VIEWACTIVITYREDACTED )
3501
3550
}
3551
+ if c .st .Version .IsActive (ctx , clusterversion .SystemPrivilegesTable ) {
3552
+ hasVARSystemPrivilege , err := c .checkHasSystemPrivilege (ctx , userName , "VIEWACTIVITYREDACTED" )
3553
+ if err != nil {
3554
+ return err
3555
+ }
3556
+ if hasVARSystemPrivilege {
3557
+ return status .Errorf (
3558
+ codes .PermissionDenied , "this operation requires %s system privilege and is not allowed for %s system privilege" ,
3559
+ privilege .VIEWACTIVITY , privilege .VIEWACTIVITYREDACTED )
3560
+ }
3561
+ }
3502
3562
return c .requireViewActivityPermission (ctx )
3503
3563
}
3504
3564
return nil
@@ -3575,6 +3635,26 @@ func (c *adminPrivilegeChecker) hasRoleOption(
3575
3635
return bool (dbDatum ), nil
3576
3636
}
3577
3637
3638
+ // checkHasSystemPrivilege is a helper function which executes
3639
+ // a query to see if rows return non-nil based on the
3640
+ // privilege provided.
3641
+ func (c * adminPrivilegeChecker ) checkHasSystemPrivilege (
3642
+ ctx context.Context , user username.SQLUsername , privilege string ,
3643
+ ) (bool , error ) {
3644
+ row , err := c .ie .QueryRowEx (
3645
+ ctx , "check-has-system-privilege" , nil , /* txn */
3646
+ sessiondata.InternalExecutorOverride {User : username .RootUserName ()},
3647
+ `SELECT * FROM system.privileges WHERE username = $1 AND privileges @> ARRAY[$2]` ,
3648
+ user , privilege )
3649
+ if err != nil {
3650
+ return false , err
3651
+ }
3652
+ if row == nil {
3653
+ return false , nil
3654
+ }
3655
+ return true , nil
3656
+ }
3657
+
3578
3658
var errRequiresAdmin = status .Error (codes .PermissionDenied , "this operation requires admin privilege" )
3579
3659
3580
3660
func errRequiresRoleOption (option roleoption.Option ) error {
0 commit comments