Skip to content

Commit 6a14da4

Browse files
author
gtr
committed
sql: add system privileges to error messages in statement stats tables
This commit implements the VIEWACTIVITY and VIEWACTIVITYREDACTED system privileges to the crdb_internal.node_statement_statistics table to provide fine-grained permissions to view the error message for failed statements. Release note (sql change): the crdb_interanal.node_statement_statistics table redact the error message if the user has VIEWACTIVITYREDACTED, and do not redact the error message if the user has VIEWACTIVITY. If the user has both, VIEWACTIVITYREDACTED takes precedence and the last error is redacted.
1 parent 708e6f0 commit 6a14da4

File tree

11 files changed

+202
-32
lines changed

11 files changed

+202
-32
lines changed

pkg/ccl/logictestccl/tests/3node-tenant/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/crdb_internal.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,12 +1516,24 @@ CREATE TABLE crdb_internal.node_statement_statistics (
15161516
latency_seconds_p99 FLOAT
15171517
)`,
15181518
populate: func(ctx context.Context, p *planner, _ catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error {
1519-
hasViewActivityOrViewActivityRedacted, err := p.HasViewActivityOrViewActivityRedactedRole(ctx)
1520-
if err != nil {
1519+
shouldRedactError := false
1520+
// Check if the user is admin.
1521+
if isAdmin, err := p.HasAdminRole(ctx); err != nil {
15211522
return err
1522-
}
1523-
if !hasViewActivityOrViewActivityRedacted {
1524-
return noViewActivityOrViewActivityRedactedRoleError(p.User())
1523+
} else if !isAdmin {
1524+
// If the user is not admin, check the individual VIEWACTIVITY and VIEWACTIVITYREDACTED
1525+
// privileges.
1526+
if hasViewActivityRedacted, err := p.HasViewActivityRedacted(ctx); err != nil {
1527+
return err
1528+
} else if hasViewActivityRedacted {
1529+
shouldRedactError = true
1530+
} else if hasViewActivity, err := p.HasViewActivity(ctx); err != nil {
1531+
return err
1532+
} else if !hasViewActivity {
1533+
// If the user is not admin and does not have VIEWACTIVITY or VIEWACTIVITYREDACTED,
1534+
// return insufficient privileges error.
1535+
return noViewActivityOrViewActivityRedactedRoleError(p.User())
1536+
}
15251537
}
15261538

15271539
var alloc tree.DatumAlloc
@@ -1530,8 +1542,12 @@ CREATE TABLE crdb_internal.node_statement_statistics (
15301542

15311543
statementVisitor := func(_ context.Context, stats *appstatspb.CollectedStatementStatistics) error {
15321544
errString := tree.DNull
1533-
if stats.Stats.SensitiveInfo.LastErr != "" {
1534-
errString = alloc.NewDString(tree.DString(stats.Stats.SensitiveInfo.LastErr))
1545+
if shouldRedactError {
1546+
errString = alloc.NewDString(tree.DString("<redacted>"))
1547+
} else {
1548+
if stats.Stats.SensitiveInfo.LastErr != "" {
1549+
errString = alloc.NewDString(tree.DString(stats.Stats.SensitiveInfo.LastErr))
1550+
}
15351551
}
15361552

15371553
errCode := tree.DNull

pkg/sql/logictest/testdata/logic_test/statement_statistics_errors

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
# by CRDB ("$ internal-migration-manager-find-jobs" for example) since they can be flaky. We are
77
# also ordering by "last_error_code" to maintain consistency.
88

9+
user root
10+
911
# Test 1: division by zero. Error code "22012" should be added.
1012
statement error division by zero
1113
SELECT 2/0;
1214

13-
query T
14-
SELECT last_error_code FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
15+
query TT
16+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
1517
----
16-
22012
18+
22012 division by zero
1719

1820
# Test 2: database does not exist. Error code "3D000" should be added.
1921
query TTTTTT colnames,rowsort
@@ -28,34 +30,34 @@ test root NULL NULL {} NULL
2830
statement error pq: database "posgres" does not exist
2931
use posgres
3032

31-
query T
32-
SELECT last_error_code FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
33+
query TT
34+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
3335
----
34-
22012
35-
3D000
36+
22012 division by zero
37+
3D000 database "posgres" does not exist
3638

3739
# Test 3: Nonexistant user. Error code "42704" should be added.
3840
statement error pq: role/user "who" does not exist
3941
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES to who
4042

41-
query T
42-
SELECT last_error_code FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
43+
query TT
44+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
4345
----
44-
22012
45-
3D000
46-
42704
46+
22012 division by zero
47+
3D000 database "posgres" does not exist
48+
42704 role/user "who" does not exist
4749

4850
# Test 4: Insufficient privilege. Error code "42501" should be added.
4951
statement error schema cannot be modified: "crdb_internal"
5052
CREATE TABLE crdb_internal.example (abc INT)
5153

52-
query T
53-
SELECT last_error_code FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
54+
query TT
55+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
5456
----
55-
22012
56-
3D000
57-
42501
58-
42704
57+
22012 division by zero
58+
3D000 database "posgres" does not exist
59+
42501 schema cannot be modified: "crdb_internal"
60+
42704 role/user "who" does not exist
5961

6062
# Test 5: Foreign key violation. Error code "23503" should be added.
6163
statement ok
@@ -67,11 +69,11 @@ INSERT INTO dst(x) VALUES ('example')
6769
statement error foreign key
6870
UPDATE dst SET x = 'xyz'
6971

70-
query T
71-
SELECT last_error_code FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
72+
query TT
73+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
7274
----
73-
22012
74-
23503
75-
3D000
76-
42501
77-
42704
75+
22012 division by zero
76+
23503 update on table "dst" violates foreign key constraint "dst_x_fkey"
77+
3D000 database "posgres" does not exist
78+
42501 schema cannot be modified: "crdb_internal"
79+
42704 role/user "who" does not exist
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Check that error messages and error codes are being surfaced correctly
2+
#
3+
# For these tests, a statement containing an intentional error is made and the
4+
# crdb_internal.node_statement_statistics virtual table is queried to validate that the error code
5+
# is recorded. When querying the node statistics table, we are ignoring statements made internally
6+
# by CRDB ("$ internal-migration-manager-find-jobs" for example) since they can be flaky. We are
7+
# also ordering by "last_error_code" to maintain consistency. Here we are also testing that the
8+
# error message is redacted for the VIEWACTIVITYREDACTED privilege.
9+
10+
11+
# Grant testuser the VIEWACTIVITYREDACTED system privilege.
12+
statement ok
13+
GRANT SYSTEM VIEWACTIVITYREDACTED TO testuser;
14+
15+
query TTB
16+
SHOW SYSTEM GRANTS
17+
----
18+
testuser VIEWACTIVITYREDACTED false
19+
20+
21+
# Switch to testuser
22+
user testuser
23+
24+
# Test 1: division by zero. Error code "22012" should be added.
25+
statement error division by zero
26+
SELECT 2/0;
27+
28+
query TT
29+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
30+
----
31+
22012 <redacted>
32+
33+
# Test 2: database does not exist. Error code "3D000" should be added.
34+
query TTTTTT colnames,rowsort
35+
SHOW DATABASES
36+
----
37+
database_name owner primary_region secondary_region regions survival_goal
38+
defaultdb root NULL NULL {} NULL
39+
postgres root NULL NULL {} NULL
40+
test root NULL NULL {} NULL
41+
42+
statement error pq: database "posgres" does not exist
43+
use posgres
44+
45+
query TT
46+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
47+
----
48+
22012 <redacted>
49+
3D000 <redacted>
50+
51+
# Test 3: Nonexistant user. Error code "42704" should be added.
52+
statement error pq: role/user "who" does not exist
53+
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES to who
54+
55+
query TT
56+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
57+
----
58+
22012 <redacted>
59+
3D000 <redacted>
60+
42704 <redacted>
61+
62+
# Test 4: Give testuser the VIEWACTIVITY system privilege and remove the VIEWACTIVITYREDACTED privilege.
63+
user root
64+
65+
statement ok
66+
GRANT SYSTEM VIEWACTIVITY TO testuser
67+
68+
statement ok
69+
REVOKE SYSTEM VIEWACTIVITYREDACTED FROM testuser
70+
71+
user testuser
72+
73+
# Now the error message should not be redacted.
74+
75+
query TT
76+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
77+
----
78+
22012 division by zero
79+
3D000 database "posgres" does not exist
80+
42704 role/user "who" does not exist
81+
82+
# Test 5: Give tesuser the VIEWACTIVITYREDACTED privilege again. This time, the error message should be redacted,
83+
# as VIEWACTIVITYREDACTED takes precedence over VIEWACTIVITY.
84+
user root
85+
86+
statement ok
87+
GRANT SYSTEM VIEWACTIVITYREDACTED TO testuser
88+
89+
user testuser
90+
91+
query TT
92+
SELECT last_error_code, last_error FROM crdb_internal.node_statement_statistics WHERE last_error_code!='NULL' AND application_name NOT LIKE '$ %' ORDER BY last_error_code ASC;
93+
----
94+
22012 <redacted>
95+
3D000 <redacted>
96+
42704 <redacted>

pkg/sql/logictest/tests/fakedist-disk/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/logictest/tests/fakedist-vec-off/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/logictest/tests/fakedist/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/logictest/tests/local-legacy-schema-changer/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/logictest/tests/local-mixed-22.2-23.1/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/logictest/tests/local-vec-off/generated_test.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)