-
Notifications
You must be signed in to change notification settings - Fork 456
database_observability: don't log query text if redaction is enabled #4599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,8 @@ const ( | |
| ) | ||
|
|
||
| const ( | ||
| stateActive = "active" | ||
| queryTextClause = ", s.query" | ||
| stateActive = "active" | ||
| ) | ||
|
|
||
| const selectPgStatActivity = ` | ||
|
|
@@ -48,16 +49,16 @@ const selectPgStatActivity = ` | |
| s.wait_event, | ||
| pg_blocking_pids(s.pid) as blocked_by_pids, | ||
| s.query_start, | ||
| s.query_id, | ||
| s.query | ||
| s.query_id | ||
| %s | ||
| FROM pg_stat_activity s | ||
| JOIN pg_database d ON s.datid = d.oid AND NOT d.datistemplate AND d.datallowconn | ||
| WHERE | ||
| s.pid != pg_backend_pid() AND | ||
| s.state != 'idle' AND | ||
| ( | ||
| s.backend_type != 'client backend' OR | ||
| ( | ||
| ( | ||
| coalesce(TRIM(s.query), '') != '' AND | ||
| s.query_id != 0 | ||
| ) | ||
|
|
@@ -194,7 +195,11 @@ func (c *QuerySamples) Name() string { | |
| } | ||
|
|
||
| func (c *QuerySamples) Start(ctx context.Context) error { | ||
| level.Debug(c.logger).Log("msg", "collector started") | ||
| if c.disableQueryRedaction { | ||
| level.Warn(c.logger).Log("msg", "collector started with query redaction disabled. SQL text in query samples may include query parameters.") | ||
| } else { | ||
| level.Debug(c.logger).Log("msg", "collector started") | ||
| } | ||
|
|
||
| c.running.Store(true) | ||
| ctx, cancel := context.WithCancel(ctx) | ||
|
|
@@ -236,7 +241,13 @@ func (c *QuerySamples) Stop() { | |
| } | ||
|
|
||
| func (c *QuerySamples) fetchQuerySample(ctx context.Context) error { | ||
| rows, err := c.dbConnection.QueryContext(ctx, selectPgStatActivity) | ||
| queryTextField := "" | ||
| if c.disableQueryRedaction { | ||
| queryTextField = queryTextClause | ||
| } | ||
|
|
||
| query := fmt.Sprintf(selectPgStatActivity, queryTextField) | ||
| rows, err := c.dbConnection.QueryContext(ctx, query) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to query pg_stat_activity: %w", err) | ||
| } | ||
|
|
@@ -279,7 +290,7 @@ func (c *QuerySamples) fetchQuerySample(ctx context.Context) error { | |
|
|
||
| func (c *QuerySamples) scanRow(rows *sql.Rows) (QuerySamplesInfo, error) { | ||
| sample := QuerySamplesInfo{} | ||
| err := rows.Scan( | ||
| scanArgs := []interface{}{ | ||
| &sample.Now, | ||
| &sample.DatabaseName, | ||
| &sample.PID, | ||
|
|
@@ -300,8 +311,11 @@ func (c *QuerySamples) scanRow(rows *sql.Rows) (QuerySamplesInfo, error) { | |
| &sample.BlockedByPIDs, | ||
| &sample.QueryStart, | ||
| &sample.QueryID, | ||
| &sample.Query, | ||
| ) | ||
| } | ||
| if c.disableQueryRedaction { | ||
| scanArgs = append(scanArgs, &sample.Query) | ||
| } | ||
| err := rows.Scan(scanArgs...) | ||
| return sample, err | ||
| } | ||
|
|
||
|
|
@@ -314,8 +328,10 @@ func (c *QuerySamples) processRow(sample QuerySamplesInfo) (SampleKey, error) { | |
| } | ||
|
|
||
| func (c QuerySamples) validateQuerySample(sample QuerySamplesInfo) error { | ||
| if sample.Query.Valid && sample.Query.String == "<insufficient privilege>" { | ||
| return fmt.Errorf("insufficient privilege to access query. sample set: %+v", sample) | ||
| if c.disableQueryRedaction { | ||
| if sample.Query.Valid && sample.Query.String == "<insufficient privilege>" { | ||
| return fmt.Errorf("insufficient privilege to access query sample set: %+v", sample) | ||
| } | ||
| } | ||
|
|
||
| if !sample.DatabaseName.Valid { | ||
|
|
@@ -426,13 +442,8 @@ func (c *QuerySamples) buildQuerySampleLabels(state *SampleState) string { | |
| } | ||
| } | ||
|
|
||
| queryText := state.LastRow.Query.String | ||
| if !c.disableQueryRedaction { | ||
| queryText = redact(queryText) | ||
| } | ||
|
|
||
| labels := fmt.Sprintf( | ||
| `datname="%s" pid="%d" leader_pid="%s" user="%s" app="%s" client="%s" backend_type="%s" state="%s" xid="%d" xmin="%d" xact_time="%s" query_time="%s" queryid="%d" query="%s" engine="postgres"`, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we removing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes this was on purpose. Can't find the ticket anymore, but at some point we stopped using it on the frontend. |
||
| `datname="%s" pid="%d" leader_pid="%s" user="%s" app="%s" client="%s" backend_type="%s" state="%s" xid="%d" xmin="%d" xact_time="%s" query_time="%s" queryid="%d"`, | ||
| state.LastRow.DatabaseName.String, | ||
| state.LastRow.PID, | ||
| leaderPID, | ||
|
|
@@ -446,11 +457,13 @@ func (c *QuerySamples) buildQuerySampleLabels(state *SampleState) string { | |
| xactDuration, | ||
| queryDuration, | ||
| state.LastRow.QueryID.Int64, | ||
| queryText, | ||
| ) | ||
| if state.LastCpuTime != "" { | ||
| labels = fmt.Sprintf(`%s cpu_time="%s"`, labels, state.LastCpuTime) | ||
| } | ||
| if c.disableQueryRedaction && state.LastRow.Query.Valid { | ||
| labels = fmt.Sprintf(`%s query="%s"`, labels, state.LastRow.Query.String) | ||
| } | ||
| return labels | ||
| } | ||
|
|
||
|
|
@@ -460,12 +473,8 @@ func (c *QuerySamples) buildWaitEventLabels(state *SampleState, we WaitEventOccu | |
| if state.LastRow.LeaderPID.Valid { | ||
| leaderPID = fmt.Sprintf(`%d`, state.LastRow.LeaderPID.Int64) | ||
| } | ||
| queryText := state.LastRow.Query.String | ||
| if !c.disableQueryRedaction { | ||
| queryText = redact(queryText) | ||
| } | ||
| return fmt.Sprintf( | ||
| `datname="%s" pid="%d" leader_pid="%s" user="%s" backend_type="%s" state="%s" xid="%d" xmin="%d" wait_time="%s" wait_event_type="%s" wait_event="%s" wait_event_name="%s" blocked_by_pids="%v" queryid="%d" query="%s" engine="postgres"`, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed query text from |
||
| `datname="%s" pid="%d" leader_pid="%s" user="%s" backend_type="%s" state="%s" xid="%d" xmin="%d" wait_time="%s" wait_event_type="%s" wait_event="%s" wait_event_name="%s" blocked_by_pids="%v" queryid="%d"`, | ||
| state.LastRow.DatabaseName.String, | ||
| state.LastRow.PID, | ||
| leaderPID, | ||
|
|
@@ -480,7 +489,6 @@ func (c *QuerySamples) buildWaitEventLabels(state *SampleState, we WaitEventOccu | |
| waitEventFullName, | ||
| we.BlockedByPIDs, | ||
| state.LastRow.QueryID.Int64, | ||
| queryText, | ||
| ) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semgrep identified an issue in your code:
String-formatted SQL query detected. This could lead to SQL injection if the string is not sanitized properly. Audit this call to ensure the SQL is not manipulable by external data.
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasonsAlternatively, triage in Semgrep AppSec Platform to ignore the finding created by string-formatted-query.
We're currently testing semgrep's diff-aware PR comment feature on a subset of our repos-- if you run into issues or find this spammy, please reach out to @danny.cooper in slack and give feedback.
You can view more details about this finding in the Semgrep AppSec Platform.