-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ccl/sqlproxyccl: add server name indication (SNI) support
Previously the proxy supported two ways of providing tenant id and cluster name information. One was through the database name. The second was through the options parameter. As part of the serverless routing changes, we want to support routing with a tenant id passed through SNI. This PR adds the ability to route using SNI info. Release justification: Low risk, high reward changes to existing functionality Release note: None
- Loading branch information
Showing
4 changed files
with
104 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -237,20 +237,52 @@ func TestProxyAgainstSecureCRDB(t *testing.T) { | |
s, addr := newSecureProxyServer( | ||
ctx, t, sql.Stopper(), &ProxyOptions{RoutingRule: sql.ServingSQLAddr(), SkipVerify: true}, | ||
) | ||
_, port, err := net.SplitHostPort(addr) | ||
require.NoError(t, err) | ||
|
||
url := fmt.Sprintf("postgres://bob:wrong@%s/tenant-cluster-28.defaultdb?sslmode=require", addr) | ||
te.TestConnectErr(ctx, t, url, 0, "failed SASL auth") | ||
|
||
url = fmt.Sprintf("postgres://bob@%s/tenant-cluster-28.defaultdb?sslmode=require", addr) | ||
te.TestConnectErr(ctx, t, url, 0, "failed SASL auth") | ||
|
||
url = fmt.Sprintf("postgres://bob:[email protected]:%s/defaultdb?sslmode=require", port) | ||
te.TestConnectErr(ctx, t, url, codeParamsRoutingFailed, "server error") | ||
|
||
url = fmt.Sprintf("postgres://bob:[email protected]:%s/defaultdb?sslmode=require", port) | ||
te.TestConnectErr(ctx, t, url, codeParamsRoutingFailed, "server error") | ||
|
||
url = fmt.Sprintf("postgres://bob:builder@%s/tenant-cluster-28.defaultdb?sslmode=require", addr) | ||
te.TestConnect(ctx, t, url, func(conn *pgx.Conn) { | ||
require.Equal(t, int64(1), s.metrics.CurConnCount.Value()) | ||
require.NoError(t, runTestQuery(ctx, conn)) | ||
}) | ||
require.Equal(t, int64(1), s.metrics.SuccessfulConnCount.Count()) | ||
|
||
// SNI provides tenant ID. | ||
url = fmt.Sprintf("postgres://bob:[email protected]:%s/defaultdb?sslmode=require", port) | ||
te.TestConnect(ctx, t, url, func(conn *pgx.Conn) { | ||
require.Equal(t, int64(1), s.metrics.CurConnCount.Value()) | ||
require.NoError(t, runTestQuery(ctx, conn)) | ||
}) | ||
|
||
// SNI and database provide tenant IDs that match. | ||
url = fmt.Sprintf( | ||
"postgres://bob:[email protected]:%s/tenant-cluster-28.defaultdb?sslmode=require", port, | ||
) | ||
te.TestConnect(ctx, t, url, func(conn *pgx.Conn) { | ||
require.Equal(t, int64(1), s.metrics.CurConnCount.Value()) | ||
require.NoError(t, runTestQuery(ctx, conn)) | ||
}) | ||
|
||
// SNI and database provide tenant IDs that don't match. | ||
url = fmt.Sprintf( | ||
"postgres://bob:[email protected]:%s/tenant-cluster-29.defaultdb?sslmode=require", port, | ||
) | ||
te.TestConnectErr(ctx, t, url, codeParamsRoutingFailed, "server error") | ||
|
||
require.Equal(t, int64(3), s.metrics.SuccessfulConnCount.Count()) | ||
require.Equal(t, int64(2), s.metrics.AuthFailedCount.Count()) | ||
require.Equal(t, int64(3), s.metrics.RoutingErrCount.Count()) | ||
} | ||
|
||
func TestProxyTLSConf(t *testing.T) { | ||
|
@@ -1466,7 +1498,13 @@ func (te *tester) TestConnect(ctx context.Context, t *testing.T, url string, fn | |
t.Helper() | ||
te.setAuthenticated(false) | ||
te.setErrToClient(nil) | ||
conn, err := pgx.Connect(ctx, url) | ||
connConfig, err := pgx.ParseConfig(url) | ||
require.NoError(t, err) | ||
if !strings.EqualFold(connConfig.Host, "127.0.0.1") { | ||
connConfig.TLSConfig.ServerName = connConfig.Host | ||
connConfig.Host = "127.0.0.1" | ||
} | ||
conn, err := pgx.ConnectConfig(ctx, connConfig) | ||
require.NoError(t, err) | ||
fn(conn) | ||
require.NoError(t, conn.Close(ctx)) | ||
|
@@ -1487,6 +1525,10 @@ func (te *tester) TestConnectErr( | |
|
||
// Prevent pgx from tying to connect to the `::1` ipv6 address for localhost. | ||
cfg.LookupFunc = func(ctx context.Context, s string) ([]string, error) { return []string{s}, nil } | ||
if !strings.EqualFold(cfg.Host, "127.0.0.1") && cfg.TLSConfig != nil { | ||
cfg.TLSConfig.ServerName = cfg.Host | ||
cfg.Host = "127.0.0.1" | ||
} | ||
conn, err := pgx.ConnectConfig(ctx, cfg) | ||
if err == nil { | ||
_ = conn.Close(ctx) | ||
|