Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ cmd_%:
go build $(BUILDFLAGS) -o $(OUTPUT) $(SOURCE)

golangci-lint:
GOBIN=$(GOBIN) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0
GOBIN=$(GOBIN) GOTOOLCHAIN=go1.25.8 go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8

go-header:
GOBIN=$(GOBIN) go install github.com/denis-tingaikin/go-header/cmd/go-header@latest
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM alpine:edge as builder
FROM golang:1.25.8-alpine AS builder

RUN apk add --no-cache --progress git make go
RUN apk add --no-cache --progress git make
ARG VERSION
ARG BRANCH
ARG COMMIT
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/pingcap/tiproxy

go 1.21
go 1.25.8

require (
github.com/BurntSushi/toml v1.2.1
Expand Down
5 changes: 3 additions & 2 deletions lib/cli/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ func doRequest(ctx context.Context, bctx *Context, method string, url string, rd
res, err := bctx.Client.Do(req)
if err != nil {
if errors.Is(err, io.EOF) {
if req.URL.Scheme == "https" {
switch req.URL.Scheme {
case "https":
req.URL.Scheme = "http"
} else if req.URL.Scheme == "http" {
case "http":
req.URL.Scheme = "https"
}
// probably server did not enable TLS, try again with plain http
Expand Down
2 changes: 1 addition & 1 deletion lib/config/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ type TLSConfig struct {
}

func (c TLSConfig) HasCert() bool {
return !(c.Cert == "" && c.Key == "")
return c.Cert != "" || c.Key != ""
}

func (c TLSConfig) HasCA() bool {
Expand Down
2 changes: 1 addition & 1 deletion lib/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/pingcap/tiproxy/lib

go 1.21
go 1.25.8

require (
github.com/cenkalti/backoff/v4 v4.2.1
Expand Down
39 changes: 17 additions & 22 deletions lib/util/security/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ func NewCert(server bool) *CertInfo {
func (ci *CertInfo) Reload(lg *zap.Logger) (tlsConfig *tls.Config, err error) {
// Some methods to rotate server config:
// - For certs: customize GetCertificate / GetConfigForClient.
// - For CA: customize ClientAuth + VerifyPeerCertificate / GetConfigForClient
// - For CA: customize ClientAuth + VerifyConnection / GetConfigForClient
// Some methods to rotate client config:
// - For certs: customize GetClientCertificate
// - For CA: customize InsecureSkipVerify + VerifyPeerCertificate
// - For CA: customize InsecureSkipVerify + VerifyConnection
prevExpireTime := ci.getExpireTime()
if ci.server {
lg = lg.With(zap.String("tls", "server"), zap.Any("cfg", ci.cfg.Load()))
Expand Down Expand Up @@ -82,20 +82,11 @@ func (ci *CertInfo) getClientCert(*tls.CertificateRequestInfo) (*tls.Certificate
return cert, nil
}

func (ci *CertInfo) verifyPeerCertificate(rawCerts [][]byte, _ [][]*x509.Certificate) error {
if len(rawCerts) == 0 {
func (ci *CertInfo) verifyPeerCertificates(certs []*x509.Certificate) error {
if len(certs) == 0 {
return nil
}

certs := make([]*x509.Certificate, len(rawCerts))
for i, asn1Data := range rawCerts {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
certs[i] = cert
}

cas := ci.ca.Load()
if cas == nil {
cas = x509.NewCertPool()
Expand All @@ -120,6 +111,10 @@ func (ci *CertInfo) verifyPeerCertificate(rawCerts [][]byte, _ [][]*x509.Certifi
return err
}

func (ci *CertInfo) verifyConnection(cs tls.ConnectionState) error {
return ci.verifyPeerCertificates(cs.PeerCertificates)
}

func (ci *CertInfo) loadCA(pemCerts []byte) (*x509.CertPool, error) {
pool := x509.NewCertPool()
for len(pemCerts) > 0 {
Expand Down Expand Up @@ -155,10 +150,10 @@ func (ci *CertInfo) buildServerConfig(lg *zap.Logger) (*tls.Config, error) {
}

tcfg := &tls.Config{
MinVersion: GetMinTLSVer(cfg.MinTLSVersion, lg),
GetCertificate: ci.getCert,
GetClientCertificate: ci.getClientCert,
VerifyPeerCertificate: ci.verifyPeerCertificate,
MinVersion: GetMinTLSVer(cfg.MinTLSVersion, lg),
GetCertificate: ci.getCert,
GetClientCertificate: ci.getClientCert,
VerifyConnection: ci.verifyConnection,
}

var certPEM, keyPEM []byte
Expand Down Expand Up @@ -239,11 +234,11 @@ func (ci *CertInfo) buildClientConfig(lg *zap.Logger) (*tls.Config, error) {
}

tcfg := &tls.Config{
MinVersion: GetMinTLSVer(cfg.MinTLSVersion, lg),
GetCertificate: ci.getCert,
GetClientCertificate: ci.getClientCert,
InsecureSkipVerify: true,
VerifyPeerCertificate: ci.verifyPeerCertificate,
MinVersion: GetMinTLSVer(cfg.MinTLSVersion, lg),
GetCertificate: ci.getCert,
GetClientCertificate: ci.getClientCert,
InsecureSkipVerify: true,
VerifyConnection: ci.verifyConnection,
}

certBytes, err := os.ReadFile(cfg.CA)
Expand Down
2 changes: 1 addition & 1 deletion pkg/balance/metricsreader/backend_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ func TestQueryBackendConcurrently(t *testing.T) {
const initialRules, initialBackends = 3, 3
var buf strings.Builder
for i := 0; i < initialRules+1; i++ {
buf.WriteString(fmt.Sprintf("name%d 100\n", i))
_, _ = fmt.Fprintf(&buf, "name%d 100\n", i)
}
resp := buf.String()

Expand Down
4 changes: 2 additions & 2 deletions pkg/balance/observer/backend_health.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ func (bh *BackendHealth) String() string {
_, _ = sb.WriteString("down")
}
if bh.PingErr != nil {
_, _ = sb.WriteString(fmt.Sprintf(", err: %s", bh.PingErr.Error()))
_, _ = fmt.Fprintf(&sb, ", err: %s", bh.PingErr)
}
if len(bh.ServerVersion) > 0 {
_, _ = sb.WriteString(", version: ")
_, _ = sb.WriteString(bh.ServerVersion)
}
if bh.Labels != nil {
_, _ = sb.WriteString(fmt.Sprintf(", labels: %v", bh.Labels))
_, _ = fmt.Fprintf(&sb, ", labels: %v", bh.Labels)
}
return sb.String()
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/balance/observer/health_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestReadServerVersion(t *testing.T) {
backend.stopSQLServer()

//test for respBody not ok
backend.mockHttpHandler.setHTTPRespBody("")
backend.setHTTPRespBody("")
backend.startSQLServer()
health = hc.Check(context.Background(), backend.sqlAddr, info)
require.False(t, health.Healthy)
Expand Down Expand Up @@ -120,7 +120,7 @@ func (srv *backendServer) setServerVersion(version string) {
GitHash: "",
}
body, _ := json.Marshal(resp)
srv.mockHttpHandler.setHTTPRespBody(string(body))
srv.setHTTPRespBody(string(body))
}

func (srv *backendServer) startHTTPServer() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/balance/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (b *backendWrapper) GetBackendInfo() observer.BackendInfo {

func (b *backendWrapper) Equals(health observer.BackendHealth) bool {
b.mu.RLock()
equal := b.mu.BackendHealth.Equals(health)
equal := b.mu.Equals(health)
b.mu.RUnlock()
return equal
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/manager/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func TestFilePath(t *testing.T) {
// For linux, it creates another file. For macOS, it doesn't touch the file.
f, err = os.Create(filepath.Join(tmpdir, "cfg"))
require.NoError(t, err)
_, err = f.WriteString(fmt.Sprintf("proxy.pd-addrs = \"%s\"", pdAddr1))
_, err = fmt.Fprintf(f, "proxy.pd-addrs = \"%s\"", pdAddr1)
require.NoError(t, err)
require.NoError(t, f.Close())
},
Expand All @@ -219,7 +219,7 @@ func TestFilePath(t *testing.T) {
}
f, err := os.Create("_tmp/cfg")
require.NoError(t, err)
_, err = f.WriteString(fmt.Sprintf("proxy.pd-addrs = \"%s\"", pdAddr1))
_, err = fmt.Fprintf(f, "proxy.pd-addrs = \"%s\"", pdAddr1)
require.NoError(t, err)
require.NoError(t, f.Close())
},
Expand All @@ -233,7 +233,7 @@ func TestFilePath(t *testing.T) {
require.NoError(t, os.Mkdir("_tmp", 0755))
f, err := os.Create("_tmp/cfg")
require.NoError(t, err)
_, err = f.WriteString(fmt.Sprintf("proxy.pd-addrs = \"%s\"", pdAddr3))
_, err = fmt.Fprintf(f, "proxy.pd-addrs = \"%s\"", pdAddr3)
require.NoError(t, err)
require.NoError(t, f.Close())
t.Log("write _tmp")
Expand All @@ -250,7 +250,7 @@ func TestFilePath(t *testing.T) {

f, err := os.Create(filename)
require.NoError(t, err)
_, err = f.WriteString(fmt.Sprintf("proxy.pd-addrs = \"%s\"", pdAddr3))
_, err = fmt.Fprintf(f, "proxy.pd-addrs = \"%s\"", pdAddr3)
require.NoError(t, err)
require.NoError(t, f.Close())
require.Eventually(t, func() bool {
Expand All @@ -267,7 +267,7 @@ func TestFilePath(t *testing.T) {
} else {
f, err := os.Create(test.filename)
require.NoError(t, err)
_, err = f.WriteString(fmt.Sprintf("proxy.pd-addrs = \"%s\"", pdAddr1))
_, err = fmt.Fprintf(f, "proxy.pd-addrs = \"%s\"", pdAddr1)
require.NoError(t, err)
require.NoError(t, f.Close())
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/manager/elect/election.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (m *election) onRetired() {
m.member.OnRetired()
m.isOwner = false
// Delete the metric so that it doesn't show on Grafana.
metrics.OwnerGauge.MetricVec.DeletePartialMatch(map[string]string{metrics.LblType: m.trimedKey})
metrics.OwnerGauge.DeletePartialMatch(map[string]string{metrics.LblType: m.trimedKey})
}

// waitRetire retires after another member becomes the owner so that there will always be an owner.
Expand Down
3 changes: 2 additions & 1 deletion pkg/manager/vip/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ func TestMultiVIP(t *testing.T) {
require.NoError(t, err)
require.Eventually(t, func() bool {
return strings.Count(text.String(), "adding VIP success") >= 2 ||
strings.Count(text.String(), "ip: command not found") >= 2
strings.Count(text.String(), "ip: command not found") >= 2 ||
strings.Count(text.String(), "executable file not found") >= 2
}, 3*time.Second, 10*time.Millisecond)
vm1.PreClose()
vm2.PreClose()
Expand Down
4 changes: 3 additions & 1 deletion pkg/manager/vip/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ func TestAddDelIP(t *testing.T) {
}

isOtherErr := func(err error) bool {
return strings.Contains(err.Error(), "command not found") || strings.Contains(err.Error(), "not in the sudoers file")
return strings.Contains(err.Error(), "command not found") ||
strings.Contains(err.Error(), "not in the sudoers file") ||
strings.Contains(err.Error(), "executable file not found")
}

for i, test := range tests {
Expand Down
8 changes: 4 additions & 4 deletions pkg/proxy/backend/authenticator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ func TestUnsupportedCapability(t *testing.T) {
for _, cfgs := range cfgOverriders {
ts, clean := newTestSuite(t, tc, cfgs...)
ts.authenticateFirstTime(t, func(t *testing.T, _ *testSuite) {
if ts.mc.clientConfig.capability&requiredFrontendCaps != requiredFrontendCaps {
if ts.mc.capability&requiredFrontendCaps != requiredFrontendCaps {
require.ErrorIs(t, ts.mp.err, ErrClientCap)
require.Nil(t, ErrToClient(ts.mp.err))
require.Equal(t, SrcClientHandshake, Error2Source(ts.mp.err))
} else if ts.mb.backendConfig.capability&defRequiredBackendCaps != defRequiredBackendCaps {
} else if ts.mb.capability&defRequiredBackendCaps != defRequiredBackendCaps {
require.ErrorIs(t, ts.mp.err, ErrBackendCap)
require.Equal(t, ErrBackendCap, ErrToClient(ts.mp.err))
require.Equal(t, SrcBackendHandshake, Error2Source(ts.mp.err))
Expand Down Expand Up @@ -583,8 +583,8 @@ func TestUpgradeBackendCap(t *testing.T) {
require.Equal(t, pnet.Capability(0), ts.mb.capability&pnet.ClientCompress)
})
// After upgrade, the backend also supports compression.
ts.mb.backendConfig.capability |= pnet.ClientCompress
ts.mb.backendConfig.capability |= pnet.ClientZstdCompressionAlgorithm
ts.mb.capability |= pnet.ClientCompress
ts.mb.capability |= pnet.ClientZstdCompressionAlgorithm
ts.authenticateSecondTime(t, func(t *testing.T, ts *testSuite) {
require.Equal(t, referCfg.clientConfig.capability&pnet.ClientCompress, ts.mc.capability&pnet.ClientCompress)
require.Equal(t, referCfg.clientConfig.capability&pnet.ClientCompress, ts.mp.authenticator.capability&pnet.ClientCompress)
Expand Down
4 changes: 3 additions & 1 deletion pkg/proxy/backend/backend_conn_mgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ func (mgr *BackendConnManager) Connect(ctx context.Context, clientIO pnet.Packet

mgr.cmdProcessor.capability = mgr.authenticator.capability
childCtx, cancelFunc := context.WithCancel(ctx)
mgr.cancelFunc = cancelFunc
mgr.cancelFunc = func() {
cancelFunc()
}
mgr.lastActiveTime = endTime
if mgr.cpt != nil && !reflect.ValueOf(mgr.cpt).IsNil() {
mgr.cpt.InitConn(endTime, mgr.connectionID, mgr.authenticator.dbname)
Expand Down
6 changes: 3 additions & 3 deletions pkg/proxy/backend/backend_conn_mgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ func TestCloseWhileConnect(t *testing.T) {
client: ts.mc.authenticate,
proxy: func(clientIO, backendIO pnet.PacketIO) error {
go func() {
require.NoError(ts.t, ts.mp.BackendConnManager.Close())
require.NoError(ts.t, ts.mp.Close())
}()
err := ts.mp.Connect(context.Background(), clientIO, ts.mp.frontendTLSConfig, ts.mp.backendTLSConfig, "", "")
if err == nil {
Expand Down Expand Up @@ -1244,7 +1244,7 @@ func TestCloseWhileExecute(t *testing.T) {
return err
}
go func() {
require.NoError(ts.t, ts.mp.BackendConnManager.Close())
require.NoError(ts.t, ts.mp.Close())
}()
return ts.mp.ExecuteCmd(context.Background(), request)
},
Expand All @@ -1268,7 +1268,7 @@ func TestCloseWhileGracefulClose(t *testing.T) {
{
proxy: func(clientIO, backendIO pnet.PacketIO) error {
go func() {
require.NoError(ts.t, ts.mp.BackendConnManager.Close())
require.NoError(ts.t, ts.mp.Close())
}()
ts.mp.GracefulClose()
return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/proxy/backend/testsuite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (ts *testSuite) authenticateFirstTime(t *testing.T, c checker) {
// The proxy reconnects to the proxy using preserved client data.
// This must be called after authenticateFirstTime.
func (ts *testSuite) authenticateSecondTime(t *testing.T, c checker) {
ts.mb.backendConfig.authSucceed = true
ts.mb.authSucceed = true
ts.tc.reconnectBackend(t)
ts.runAndCheck(t, c, nil, ts.mb.authenticate, ts.mp.authenticateSecondTime)
if c == nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/proxy/net/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (crw *compressedReadWriter) ResetSequence() {
// the client/server begins reading or writing.
func (crw *compressedReadWriter) BeginRW(status rwStatus) {
if crw.rwStatus != status {
crw.packetReadWriter.SetSequence(crw.sequence)
crw.SetSequence(crw.sequence)
crw.rwStatus = status
}
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/proxy/net/packetio.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,14 @@ func (brw *basicReadWriter) TLSConnectionState() tls.ConnectionState {
// This function normally costs 1ms, so don't call it too frequently.
// This function may incorrectly return true if the system is extremely slow.
func (brw *basicReadWriter) IsPeerActive() bool {
if err := brw.Conn.SetReadDeadline(time.Now().Add(time.Millisecond)); err != nil {
if err := brw.SetReadDeadline(time.Now().Add(time.Millisecond)); err != nil {
return false
}
active := true
if _, err := brw.ReadWriter.Peek(1); err != nil {
if _, err := brw.Peek(1); err != nil {
active = !errors.Is(err, io.EOF)
}
if err := brw.Conn.SetReadDeadline(time.Time{}); err != nil {
if err := brw.SetReadDeadline(time.Time{}); err != nil {
return false
}
return active
Expand Down
4 changes: 2 additions & 2 deletions pkg/proxy/net/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (prw *proxyReadWriter) writeProxy() error {
return errors.Wrap(err, ErrWriteConn)
}
// according to the spec, we better flush to avoid server hanging
if err := prw.packetReadWriter.Flush(); err != nil {
if err := prw.Flush(); err != nil {
return err
}
prw.proxyInited.Store(true)
Expand All @@ -133,7 +133,7 @@ func (prw *proxyReadWriter) parseProxyV2() (*proxyprotocol.Proxy, error) {
}

// yes, it is proxyV2
_, err = prw.packetReadWriter.Discard(len(proxyprotocol.MagicV2))
_, err = prw.Discard(len(proxyprotocol.MagicV2))
if err != nil {
return nil, errors.WithStack(errors.Wrap(err, ErrReadConn))
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/proxy/net/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type tlsInternalConn struct {
}

func (br *tlsInternalConn) Write(p []byte) (n int, err error) {
return br.packetReadWriter.DirectWrite(p)
return br.DirectWrite(p)
}

func (p *packetIO) ServerTLSHandshake(tlsConfig *tls.Config) (tls.ConnectionState, error) {
Expand Down
Loading