Skip to content

Commit d057bda

Browse files
craig[bot]darinppRaduBerinde
committed
108039: sqlproxyccl: fix non-auth error causing throttle r=darinpp a=darinpp Currently an error that occurs after a successful authentication but before the SQL server is ready to serve queries is considered an authentication failure and causes a throttle. In the cases where the connections are limited (due to usage limits) this causes blocks and prevents the clients to connect. This PR fixes the issue by not considering errors that came after the authentication was successful as conditions to throttle. Fixes: https://cockroachlabs.atlassian.net/browse/CC-25314 Release note: None 108296: go.mod: bump Pebble to 40d3f411e45b r=RaduBerinde a=RaduBerinde 40d3f411 pebble: expose the secondary cache size as an option 077c3e8b ci: use any 1.20 go version ff9402f0 Makefile: add testcoverage target 7e548be8 db: log flushed memtables in-memory size 83c9361c pebble: Collect Pebble Key Statistics fe0ea048 manifest: Added Virtual SSTable Metadata Bounds Checking 42d81d23 internal/rangekey: remove ForeignSSTTransformer 9c487492 *: simplify pointCollapsingIter, use vanilla iters for foreign SSTs 5e7f8852 db: introduce Download API Release note: None Epic: none Co-authored-by: Darin Peshev <[email protected]> Co-authored-by: Radu Berinde <[email protected]>
3 parents 2786ad3 + 7215dd0 + 0942ede commit d057bda

File tree

8 files changed

+103
-46
lines changed

8 files changed

+103
-46
lines changed

DEPS.bzl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,10 +1595,10 @@ def go_deps():
15951595
patches = [
15961596
"@com_github_cockroachdb_cockroach//build/patches:com_github_cockroachdb_pebble.patch",
15971597
],
1598-
sha256 = "7ea06d5b0207ed3f20b5962bde7af18e6744fe089a98c51d66ac812252746342",
1599-
strip_prefix = "github.com/cockroachdb/[email protected]20230728153158-ce43e6535942",
1598+
sha256 = "f0319e618ed024b7d708e2c1f8cf0d4b9b7e4112943288ba6036e893a7f8c151",
1599+
strip_prefix = "github.com/cockroachdb/[email protected]20230807145728-40d3f411e45b",
16001600
urls = [
1601-
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/pebble/com_github_cockroachdb_pebble-v0.0.0-20230728153158-ce43e6535942.zip",
1601+
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/pebble/com_github_cockroachdb_pebble-v0.0.0-20230807145728-40d3f411e45b.zip",
16021602
],
16031603
)
16041604
go_repository(

build/bazelutil/distdir_files.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ DISTDIR_FILES = {
320320
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/go-test-teamcity/com_github_cockroachdb_go_test_teamcity-v0.0.0-20191211140407-cff980ad0a55.zip": "bac30148e525b79d004da84d16453ddd2d5cd20528e9187f1d7dac708335674b",
321321
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/gostdlib/com_github_cockroachdb_gostdlib-v1.19.0.zip": "c4d516bcfe8c07b6fc09b8a9a07a95065b36c2855627cb3514e40c98f872b69e",
322322
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/logtags/com_github_cockroachdb_logtags-v0.0.0-20230118201751-21c54148d20b.zip": "ca7776f47e5fecb4c495490a679036bfc29d95bd7625290cfdb9abb0baf97476",
323-
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/pebble/com_github_cockroachdb_pebble-v0.0.0-20230728153158-ce43e6535942.zip": "7ea06d5b0207ed3f20b5962bde7af18e6744fe089a98c51d66ac812252746342",
323+
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/pebble/com_github_cockroachdb_pebble-v0.0.0-20230807145728-40d3f411e45b.zip": "f0319e618ed024b7d708e2c1f8cf0d4b9b7e4112943288ba6036e893a7f8c151",
324324
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/redact/com_github_cockroachdb_redact-v1.1.5.zip": "11b30528eb0dafc8bc1a5ba39d81277c257cbe6946a7564402f588357c164560",
325325
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/returncheck/com_github_cockroachdb_returncheck-v0.0.0-20200612231554-92cdbca611dd.zip": "ce92ba4352deec995b1f2eecf16eba7f5d51f5aa245a1c362dfe24c83d31f82b",
326326
"https://storage.googleapis.com/cockroach-godeps/gomod/github.com/cockroachdb/sentry-go/com_github_cockroachdb_sentry_go-v0.6.1-cockroachdb.2.zip": "fbb2207d02aecfdd411b1357efe1192dbb827959e36b7cab7491731ac55935c9",

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ require (
116116
github.com/cockroachdb/go-test-teamcity v0.0.0-20191211140407-cff980ad0a55
117117
github.com/cockroachdb/gostdlib v1.19.0
118118
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b
119-
github.com/cockroachdb/pebble v0.0.0-20230728153158-ce43e6535942
119+
github.com/cockroachdb/pebble v0.0.0-20230807145728-40d3f411e45b
120120
github.com/cockroachdb/redact v1.1.5
121121
github.com/cockroachdb/returncheck v0.0.0-20200612231554-92cdbca611dd
122122
github.com/cockroachdb/stress v0.0.0-20220803192808-1806698b1b7b

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,8 @@ github.com/cockroachdb/gostdlib v1.19.0/go.mod h1:+dqqpARXbE/gRDEhCak6dm0l14AaTy
493493
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
494494
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
495495
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
496-
github.com/cockroachdb/pebble v0.0.0-20230728153158-ce43e6535942 h1:y+9IilMcEy6qyDIZ94Vw3hJTk17J4j21TaMIe8C29Zg=
497-
github.com/cockroachdb/pebble v0.0.0-20230728153158-ce43e6535942/go.mod h1:FN5O47SBEz5+kO9fG8UTR64g2WS1u5ZFCgTvxGjoSks=
496+
github.com/cockroachdb/pebble v0.0.0-20230807145728-40d3f411e45b h1:ymYyDZy5WYRTBqPVYgy0XUW+gHx2HeRkyt1FJmNJVOo=
497+
github.com/cockroachdb/pebble v0.0.0-20230807145728-40d3f411e45b/go.mod h1:FN5O47SBEz5+kO9fG8UTR64g2WS1u5ZFCgTvxGjoSks=
498498
github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
499499
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
500500
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=

pkg/ccl/sqlproxyccl/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ go_library(
5353
"@org_golang_google_grpc//codes",
5454
"@org_golang_google_grpc//credentials/insecure",
5555
"@org_golang_google_grpc//status",
56+
"@org_golang_x_exp//slices",
5657
],
5758
)
5859

@@ -93,6 +94,7 @@ go_test(
9394
"//pkg/sql",
9495
"//pkg/sql/catalog/descs",
9596
"//pkg/sql/pgwire",
97+
"//pkg/sql/pgwire/pgcode",
9698
"//pkg/sql/pgwire/pgerror",
9799
"//pkg/sql/pgwire/pgwirebase",
98100
"//pkg/testutils",

pkg/ccl/sqlproxyccl/authentication.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ import (
1313

1414
"github.com/cockroachdb/cockroach/pkg/ccl/sqlproxyccl/interceptor"
1515
"github.com/cockroachdb/cockroach/pkg/ccl/sqlproxyccl/throttler"
16+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
1617
"github.com/cockroachdb/errors"
1718
pgproto3 "github.com/jackc/pgproto3/v2"
19+
"golang.org/x/exp/slices"
1820
)
1921

22+
// These errors occur after successful auth but are sent back as a result of
23+
// the auth request. Receiving such error shouldn't trigger throttle.
24+
var pgPostAuthErrorCodes = []string{
25+
pgcode.TooManyConnections.String(),
26+
}
27+
2028
// authenticate handles the startup of the pgwire protocol to the point where
2129
// the connections is considered authenticated. If that doesn't happen, it
2230
// returns an error.
@@ -111,13 +119,21 @@ var authenticate = func(
111119
// Server has rejected the authentication response from the client and
112120
// has closed the connection.
113121
case *pgproto3.ErrorResponse:
114-
throttleError := throttleHook(throttler.AttemptInvalidCredentials)
122+
// The error may be in response of auth message but may not indicate
123+
// unsuccessful authentication. Clear throttle if this is the case.
124+
var throttleError error
125+
if slices.Contains(pgPostAuthErrorCodes, tp.Code) {
126+
throttleError = throttleHook(throttler.AttemptOK)
127+
} else {
128+
throttleError = throttleHook(throttler.AttemptInvalidCredentials)
129+
}
115130
if throttleError != nil {
116131
if err = feSend(toPgError(throttleError)); err != nil {
117132
return nil, err
118133
}
119134
return nil, throttleError
120135
}
136+
121137
if err = feSend(backendMsg); err != nil {
122138
return nil, err
123139
}

pkg/ccl/sqlproxyccl/authentication_test.go

Lines changed: 74 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"testing"
1414

1515
"github.com/cockroachdb/cockroach/pkg/ccl/sqlproxyccl/throttler"
16+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
1617
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
1718
"github.com/jackc/pgproto3/v2"
1819
"github.com/stretchr/testify/assert"
@@ -98,14 +99,14 @@ func TestAuthenticateClearText(t *testing.T) {
9899
func TestAuthenticateThrottled(t *testing.T) {
99100
defer leaktest.AfterTest(t)()
100101

101-
server := func(t *testing.T, be *pgproto3.Backend, authResponse pgproto3.BackendMessage) {
102+
server := func(t *testing.T, be *pgproto3.Backend) {
102103
require.NoError(t, be.Send(&pgproto3.AuthenticationCleartextPassword{}))
103104

104105
msg, err := be.Receive()
105106
require.NoError(t, err)
106107
require.Equal(t, msg, &pgproto3.PasswordMessage{Password: "password"})
107108

108-
require.NoError(t, be.Send(authResponse))
109+
require.NoError(t, be.Send(&pgproto3.ErrorResponse{Message: "wrong password"}))
109110
}
110111

111112
client := func(t *testing.T, fe *pgproto3.Frontend) {
@@ -130,44 +131,79 @@ func TestAuthenticateThrottled(t *testing.T) {
130131
require.Error(t, err)
131132
}
132133

133-
type testCase struct {
134-
name string
135-
result pgproto3.BackendMessage
136-
expectedStatus throttler.AttemptStatus
137-
}
138-
for _, tc := range []testCase{
139-
{
140-
name: "AuthenticationOkay",
141-
result: &pgproto3.AuthenticationOk{},
142-
expectedStatus: throttler.AttemptOK,
143-
},
144-
{
145-
name: "AuthenticationError",
146-
result: &pgproto3.ErrorResponse{Message: "wrong password"},
147-
expectedStatus: throttler.AttemptInvalidCredentials,
148-
},
149-
} {
150-
t.Run(tc.name, func(t *testing.T) {
151-
proxyToServer, serverToProxy := net.Pipe()
152-
proxyToClient, clientToProxy := net.Pipe()
153-
sqlServer := pgproto3.NewBackend(pgproto3.NewChunkReader(serverToProxy), serverToProxy)
154-
sqlClient := pgproto3.NewFrontend(pgproto3.NewChunkReader(clientToProxy), clientToProxy)
155-
156-
go server(t, sqlServer, &pgproto3.AuthenticationOk{})
157-
go client(t, sqlClient)
158-
159-
_, err := authenticate(proxyToClient, proxyToServer, nil, /* proxyBackendKeyData */
160-
func(status throttler.AttemptStatus) error {
161-
require.Equal(t, throttler.AttemptOK, status)
162-
return throttledError
163-
})
164-
require.Error(t, err)
165-
require.Contains(t, err.Error(), "connection attempt throttled")
166-
167-
proxyToServer.Close()
168-
proxyToClient.Close()
134+
proxyToServer, serverToProxy := net.Pipe()
135+
proxyToClient, clientToProxy := net.Pipe()
136+
sqlServer := pgproto3.NewBackend(pgproto3.NewChunkReader(serverToProxy), serverToProxy)
137+
sqlClient := pgproto3.NewFrontend(pgproto3.NewChunkReader(clientToProxy), clientToProxy)
138+
139+
go server(t, sqlServer)
140+
go client(t, sqlClient)
141+
142+
_, err := authenticate(proxyToClient, proxyToServer, nil, /* proxyBackendKeyData */
143+
func(status throttler.AttemptStatus) error {
144+
require.Equal(t, throttler.AttemptInvalidCredentials, status)
145+
return throttledError
169146
})
147+
require.Error(t, err)
148+
require.Contains(t, err.Error(), "connection attempt throttled")
149+
150+
proxyToServer.Close()
151+
proxyToClient.Close()
152+
}
153+
154+
func TestErrorFollowingAuthenticateNotThrottled(t *testing.T) {
155+
defer leaktest.AfterTest(t)()
156+
157+
server := func(t *testing.T, be *pgproto3.Backend) {
158+
require.NoError(t, be.Send(&pgproto3.AuthenticationCleartextPassword{}))
159+
160+
msg, err := be.Receive()
161+
require.NoError(t, err)
162+
require.Equal(t, msg, &pgproto3.PasswordMessage{Password: "password"})
163+
164+
require.NoError(t, be.Send(&pgproto3.ErrorResponse{
165+
Code: pgcode.TooManyConnections.String(),
166+
Message: "sorry, too many clients already"}))
170167
}
168+
169+
client := func(t *testing.T, fe *pgproto3.Frontend) {
170+
msg, err := fe.Receive()
171+
require.NoError(t, err)
172+
require.Equal(t, msg, &pgproto3.AuthenticationCleartextPassword{})
173+
174+
require.NoError(t, fe.Send(&pgproto3.PasswordMessage{Password: "password"}))
175+
176+
// Try reading from the connection. This check ensures authorize
177+
// swallowed the OK/Error response from the sql server.
178+
msg, err = fe.Receive()
179+
require.NoError(t, err)
180+
require.Equal(t, msg, &pgproto3.ErrorResponse{
181+
Code: pgcode.TooManyConnections.String(),
182+
Message: "sorry, too many clients already"})
183+
}
184+
185+
proxyToServer, serverToProxy := net.Pipe()
186+
proxyToClient, clientToProxy := net.Pipe()
187+
sqlServer := pgproto3.NewBackend(pgproto3.NewChunkReader(serverToProxy), serverToProxy)
188+
sqlClient := pgproto3.NewFrontend(pgproto3.NewChunkReader(clientToProxy), clientToProxy)
189+
190+
go server(t, sqlServer)
191+
go client(t, sqlClient)
192+
193+
var throttleCallCount int
194+
_, err := authenticate(proxyToClient, proxyToServer, nil, /* proxyBackendKeyData */
195+
func(status throttler.AttemptStatus) error {
196+
throttleCallCount++
197+
require.Equal(t, throttler.AttemptOK, status)
198+
return nil
199+
})
200+
require.Equal(t, 1, throttleCallCount)
201+
require.Error(t, err)
202+
require.Contains(t, err.Error(),
203+
"codeAuthFailed: authentication failed: sorry, too many clients already")
204+
205+
proxyToServer.Close()
206+
proxyToClient.Close()
171207
}
172208

173209
func TestAuthenticateError(t *testing.T) {

pkg/sql/pgwire/conn.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ func (c *conn) processCommands(
207207

208208
var decrementConnectionCount func()
209209
if decrementConnectionCount, retErr = sqlServer.IncrementConnectionCount(c.sessionArgs); retErr != nil {
210+
// This will return pgcode.TooManyConnections which is used by the sql proxy
211+
// to skip failed auth throttle (as in this case the auth was fine but the
212+
// error occurred before sending back auth ok msg)
210213
_ = c.sendError(ctx, retErr)
211214
return
212215
}

0 commit comments

Comments
 (0)