Skip to content

Commit

Permalink
Switch shell / connect to use caching_sha2_password by default
Browse files Browse the repository at this point in the history
This switches up both connect and shell to use `caching_sha2_password`
by default. `connect` gets an option to also select the legacy
`mysql_native_password` option. `shell` selects based on the `mysql
--version` returns. For MySQL 8.x and later, it now uses
`caching_sha2_password`.

Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
  • Loading branch information
dbussink committed Oct 9, 2024
1 parent 0733e5b commit d68bc44
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.23.1 as build
FROM golang:1.23.2 as build
WORKDIR /app
COPY . .

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ endif
REPO=planetscale
NAME=pscale
BUILD_PKG=github.com/planetscale/cli/cmd/pscale
GORELEASE_CROSS_VERSION ?= v1.23.1
GORELEASE_CROSS_VERSION ?= v1.23.2
SYFT_VERSION ?= 1.9.0

.PHONY: all
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: '2'

services:
app:
image: golang:1.23.1
image: golang:1.23.2
volumes:
- .:/work
working_dir: /work
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.goreleaser
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG GORELEASE_CROSS_VERSION=v1.23.1
ARG GORELEASE_CROSS_VERSION=v1.23.2
FROM ghcr.io/goreleaser/goreleaser-cross:${GORELEASE_CROSS_VERSION}

RUN apt-get update && apt-get install -y openssh-client
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/planetscale/cli

go 1.23.1
go 1.23.2

require (
github.com/99designs/keyring v1.2.2
Expand All @@ -23,9 +23,9 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/pkg/errors v0.9.1
github.com/planetscale/planetscale-go v0.108.0
github.com/planetscale/planetscale-go v0.110.0
github.com/planetscale/psdb v0.0.0-20240109164348-6848e728f6e7
github.com/planetscale/psdbproxy v0.0.0-20240927190836-61feaf3c8bdb
github.com/planetscale/psdbproxy v0.0.0-20241009145102-7fdfa92ae3ca
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0
Expand All @@ -39,6 +39,7 @@ require (
golang.org/x/sys v0.26.0
golang.org/x/text v0.19.0
gopkg.in/yaml.v2 v2.4.0
vitess.io/vitess v0.10.3-0.20240927074858-3e5371377b43
)

require (
Expand Down Expand Up @@ -91,7 +92,6 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
vitess.io/vitess v0.10.3-0.20240927074858-3e5371377b43 // indirect
)

replace github.com/golang/glog => github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e h1:MZ8D+Z3m2vvqGZLvoQfpaGg/j1fNDr4j03s3PRz4rVY=
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e/go.mod h1:hwAsSPQdvPa3WcfKfzTXxtEq/HlqwLjQasfO6QbGo4Q=
github.com/planetscale/planetscale-go v0.108.0 h1:KwLhKsntOO2yokjYxfBtUwHN9/n+c6PnYPbsibZ8jmE=
github.com/planetscale/planetscale-go v0.108.0/go.mod h1:2s0/iqbBEBEL5k+3t0+eNztAU3bYxUynLQs4yLrKNDI=
github.com/planetscale/planetscale-go v0.110.0 h1:iaS/4pbP/efBmLtzr+cH8gjhLy1OjAovOgSqL+Gbobk=
github.com/planetscale/planetscale-go v0.110.0/go.mod h1:ldGffCLckkR8fjGDjDFs4WcjlDr8uqg2qRUZhRYBEMI=
github.com/planetscale/psdb v0.0.0-20240109164348-6848e728f6e7 h1:dxdoFKWVDlV1gq8UQC8NWCofLjCEjEHw47gfeojgs28=
github.com/planetscale/psdb v0.0.0-20240109164348-6848e728f6e7/go.mod h1:WZmi4gw3rOK+ryd1inGxgfKwoFV04O7xBCqzWzv0/0U=
github.com/planetscale/psdbproxy v0.0.0-20240927190836-61feaf3c8bdb h1:eJqW2GfcbKOkUCNHBmHOIWrX4sIaYUJ9xljnlNYtVPQ=
github.com/planetscale/psdbproxy v0.0.0-20240927190836-61feaf3c8bdb/go.mod h1:qxC4twwQwRjHb9lt2DB/Ny0CuhJs1rrxskPbBLDljgo=
github.com/planetscale/psdbproxy v0.0.0-20241009145102-7fdfa92ae3ca h1:E5E1yyZ03FzA/6styZr5C2L3DdqhnkZsKSJy5q4JnuU=
github.com/planetscale/psdbproxy v0.0.0-20241009145102-7fdfa92ae3ca/go.mod h1:qxC4twwQwRjHb9lt2DB/Ny0CuhJs1rrxskPbBLDljgo=
github.com/planetscale/vitess-types v0.0.0-20231211191709-770e14433716 h1:FD6vnHCirVPeyn+E6Z0HyXoAqXzjfTcRpgss/63im6w=
github.com/planetscale/vitess-types v0.0.0-20231211191709-770e14433716/go.mod h1:8KWsIjuUBs+xlbfn9wBCxicFZqV8BCPIFoqlOSs+60I=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
Expand Down
19 changes: 18 additions & 1 deletion internal/cmd/connect/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (

"github.com/mattn/go-shellwords"
"github.com/spf13/cobra"

"vitess.io/vitess/go/mysql"
)

func ConnectCmd(ch *cmdutil.Helper) *cobra.Command {
Expand All @@ -34,6 +36,7 @@ func ConnectCmd(ch *cmdutil.Helper) *cobra.Command {
role string
noRandom bool
replica bool
authMethod string
}

cmd := &cobra.Command{
Expand Down Expand Up @@ -95,6 +98,18 @@ argument:
role = cmdutil.ReaderRole
}

authMethod := mysql.CachingSha2Password
if flags.authMethod != "" {
switch flags.authMethod {
case "caching_sha2_password":
authMethod = mysql.CachingSha2Password
case "mysql_native_password":
authMethod = mysql.MysqlNativePassword
default:
return fmt.Errorf("unsupported auth method: %s", flags.authMethod)
}
}

// check whether database and branch exist
dbBranch, err := client.DatabaseBranches.Get(ctx, &planetscale.GetDatabaseBranchRequest{
Organization: ch.Config.Organization,
Expand Down Expand Up @@ -156,7 +171,7 @@ argument:

errCh := make(chan error, 1)
go func() {
errCh <- proxy.Serve(l)
errCh <- proxy.Serve(l, authMethod)
}()

go func() {
Expand Down Expand Up @@ -215,6 +230,8 @@ argument:
cmd.PersistentFlags().StringVar(&flags.role, "role",
"", "Role defines the access level, allowed values are: reader, writer, readwriter, admin. Defaults to 'reader' for replica passwords, otherwise defaults to 'admin'.")
cmd.Flags().BoolVar(&flags.replica, "replica", false, "When enabled, the password will route all reads to the branch's primary replicas and all read-only regions.")
cmd.PersistentFlags().StringVar(&flags.authMethod, "mysql-auth-method",
"", "MySQL auth method defines the authentication method returned for the MySQL protocol. Allowed values are: caching_sha2_password, mysql_native_password. Defaults to 'caching_sha2_password'.")

return cmd
}
Expand Down
7 changes: 6 additions & 1 deletion internal/cmd/database/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
_ "github.com/go-sql-driver/mysql"

"github.com/spf13/cobra"

"vitess.io/vitess/go/mysql"
)

type dumpFlags struct {
Expand Down Expand Up @@ -173,7 +175,10 @@ func dump(ch *cmdutil.Helper, cmd *cobra.Command, flags *dumpFlags, args []strin
defer l.Close()

go func() {
if err := proxy.Serve(l); err != nil {
// We have to use mysql.MysqlNativePassword here because we still end
// up using https://github.com/xelabs/go-mysqlstack which is unmaintained
// and doesn't support caching_sha2_password.
if err := proxy.Serve(l, mysql.MysqlNativePassword); err != nil {
ch.Printer.Println("proxy error: ", err)
}
}()
Expand Down
4 changes: 3 additions & 1 deletion internal/cmd/database/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
ps "github.com/planetscale/planetscale-go/planetscale"

"github.com/spf13/cobra"

"vitess.io/vitess/go/mysql"
)

type restoreFlags struct {
Expand Down Expand Up @@ -127,7 +129,7 @@ func restore(ch *cmdutil.Helper, cmd *cobra.Command, flags *restoreFlags, args [
defer l.Close()

go func() {
if err := proxy.Serve(l); err != nil {
if err := proxy.Serve(l, mysql.MysqlNativePassword); err != nil {
ch.Printer.Println("proxy error: ", err)
}
}()
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ second argument:
runForeground = false
}

mysqlPath, err := cmdutil.MySQLClientPath()
mysqlPath, authMethod, err := cmdutil.MySQLClientPath()
if err != nil {
return err
}
Expand Down Expand Up @@ -210,7 +210,7 @@ second argument:

errCh := make(chan error, 1)
go func() {
errCh <- proxy.Serve(l)
errCh <- proxy.Serve(l, authMethod)
}()

go func() {
Expand Down
47 changes: 39 additions & 8 deletions internal/cmdutil/cmdutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"

Expand All @@ -18,6 +20,8 @@ import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
exec "golang.org/x/sys/execabs"

"vitess.io/vitess/go/mysql"
)

const WarnAuthMessage = "not authenticated yet. Please run 'pscale auth login'"
Expand Down Expand Up @@ -166,10 +170,12 @@ func HasHomebrew() bool {
return err == nil
}

var versionRegex = regexp.MustCompile(`Ver ([0-9]+)\.([0-9]+)\.([0-9]+)`)

// MySQLClientPath checks whether the 'mysql' client exists and returns the
// path to the binary. The returned error contains instructions to install the
// client.
func MySQLClientPath() (string, error) {
func MySQLClientPath() (string, mysql.AuthMethodDescription, error) {
// 'brew install mysql-client' installs the client into an unusual path
// https://docs.brew.sh/FAQ#why-should-i-install-homebrew-in-the-default-location
var homebrewPrefix string
Expand All @@ -183,30 +189,55 @@ func MySQLClientPath() (string, error) {
homebrewPrefix = "/home/linuxbrew/.linuxbrew"
}

authMethod := mysql.CachingSha2Password
oldpath := os.Getenv("PATH")
newpath := homebrewPrefix + "/opt/mysql-client/bin/" + string(os.PathListSeparator) + oldpath
newpath := homebrewPrefix + "/opt/mysql-client/bin/" +
homebrewPrefix + "/opt/mysql/bin/" +
string(os.PathListSeparator) + oldpath
defer func() {
if err := os.Setenv("PATH", oldpath); err != nil {
fmt.Println("failed to restore PATH", err)
}
}()

if err := os.Setenv("PATH", newpath); err != nil {
return "", err
return "", authMethod, err
}

path, err := exec.LookPath("mysql")
if err == nil {
return path, nil
if err != nil {
return installInstructions("couldn't find the 'mysql' command-line tool required to run this command.")
}

cmd := exec.Command("mysql", "--version")
out, err := cmd.Output()
if err != nil {
return "", authMethod, fmt.Errorf("failed to run 'mysql --version': %w", err)
}

v := versionRegex.FindStringSubmatch(string(out))
if len(v) != 4 {
return "", authMethod, fmt.Errorf("could not parse server version from: %s", string(out))
}
major, err := strconv.Atoi(v[1])
if err != nil {
return "", authMethod, fmt.Errorf("could not parse server version from: %s", string(out))
}

msg := "couldn't find the 'mysql' command-line tool required to run this command."
if major < 8 {
authMethod = mysql.MysqlNativePassword
}

return path, authMethod, nil
}

func installInstructions(msg string) (string, mysql.AuthMethodDescription, error) {
installURL := "https://planetscale.com/docs/reference/planetscale-environment-setup"

switch runtime.GOOS {
case "darwin":
if HasHomebrew() {
return "", fmt.Errorf("%s\nTo install, run: brew install mysql-client", msg)
return "", mysql.CachingSha2Password, fmt.Errorf("%s\nTo install, run: brew install mysql-client@8.4", msg)
}

installURL = "https://planetscale.com/docs/reference/planetscale-environment-setup#macos-instructions"
Expand All @@ -216,7 +247,7 @@ func MySQLClientPath() (string, error) {
installURL = "https://planetscale.com/docs/reference/planetscale-environment-setup#windows-instructions"
}

return "", fmt.Errorf("%s\nTo install, follow the instructions: %s", msg, installURL)
return "", mysql.CachingSha2Password, fmt.Errorf("%s\nTo install, follow the instructions: %s", msg, installURL)
}

func ParseSSLMode(sslMode string) ps.ExternalDataSourceSSLVerificationMode {
Expand Down
24 changes: 24 additions & 0 deletions internal/mock/keyspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ type BranchKeyspacesService struct {

CreateFn func(context.Context, *ps.CreateBranchKeyspaceRequest) (*ps.Keyspace, error)
CreateFnInvoked bool

ResizeFn func(context.Context, *ps.ResizeKeyspaceRequest) (*ps.KeyspaceResizeRequest, error)
ResizeInvoked bool

CancelResizeFn func(context.Context, *ps.CancelKeyspaceResizeRequest) error
CancelResizeInvoked bool

ResizeStatusFn func(context.Context, *ps.KeyspaceResizeStatusRequest) (*ps.KeyspaceResizeRequest, error)
ResizeStatusInvoked bool
}

func (s *BranchKeyspacesService) List(ctx context.Context, req *ps.ListBranchKeyspacesRequest) ([]*ps.Keyspace, error) {
Expand Down Expand Up @@ -48,3 +57,18 @@ func (s *BranchKeyspacesService) Create(ctx context.Context, req *ps.CreateBranc
s.CreateFnInvoked = true
return s.CreateFn(ctx, req)
}

func (s *BranchKeyspacesService) Resize(ctx context.Context, req *ps.ResizeKeyspaceRequest) (*ps.KeyspaceResizeRequest, error) {
s.ResizeInvoked = true
return s.ResizeFn(ctx, req)
}

func (s *BranchKeyspacesService) CancelResize(ctx context.Context, req *ps.CancelKeyspaceResizeRequest) error {
s.CancelResizeInvoked = true
return s.CancelResizeFn(ctx, req)
}

func (s *BranchKeyspacesService) ResizeStatus(ctx context.Context, req *ps.KeyspaceResizeStatusRequest) (*ps.KeyspaceResizeRequest, error) {
s.ResizeStatusInvoked = true
return s.ResizeStatusFn(ctx, req)
}

0 comments on commit d68bc44

Please sign in to comment.