Skip to content

Commit

Permalink
feat: add support for credentials JSON flag
Browse files Browse the repository at this point in the history
Fixes #323.
  • Loading branch information
enocom committed Sep 19, 2022
1 parent 47b39d3 commit 7f2ba2d
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 5 deletions.
9 changes: 9 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,15 @@ func parseConfig(cmd *Command, conf *proxy.Config, args []string) error {
if conf.CredentialsFile != "" && conf.GcloudAuth {
return newBadCommandError("cannot specify --credentials-file and --gcloud-auth flags at the same time")
}
if conf.CredentialsJSON != "" && conf.Token != "" {
return newBadCommandError("cannot specify --credentials-json and --token flags at the same time")
}
if conf.CredentialsJSON != "" && conf.CredentialsFile != "" {
return newBadCommandError("cannot specify --credentials-json and --credentials-file flags at the same time")
}
if conf.CredentialsJSON != "" && conf.GcloudAuth {
return newBadCommandError("cannot specify --credentials-json and --gcloud-auth flags at the same time")
}

if userHasSet("http-port") && !userHasSet("prometheus") && !userHasSet("health-check") {
cmd.logger.Infof("Ignoring --http-port because --prometheus or --health-check was not set")
Expand Down
20 changes: 19 additions & 1 deletion cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,25 @@ func TestNewCommandWithErrors(t *testing.T) {
desc: "when both gcloud auth and credentials file are set",
args: []string{
"--gcloud-auth",
"--credential-file", "/path/to/file", "proj:region:inst"},
"--credentials-file", "/path/to/file", "proj:region:inst"},
},
{
desc: "when both token and credentials JSON are set",
args: []string{
"--token", "a-token",
"--credentials-json", `{"json":"here"}`, "proj:region:inst"},
},
{
desc: "when both credentials file and credentials JSON are set",
args: []string{
"--credentials-file", "/a/file",
"--credentials-json", `{"json":"here"}`, "proj:region:inst"},
},
{
desc: "when both gcloud auth and credentials JSON are set",
args: []string{
"--gcloud-auth",
"--credentials-json", `{"json":"here"}`, "proj:region:inst"},
},
{
desc: "when the unix socket query param contains multiple values",
Expand Down
2 changes: 1 addition & 1 deletion internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (c *Config) DialerOptions(l cloudsql.Logger) ([]cloudsqlconn.Option, error)
c.CredentialsFile,
))
case c.CredentialsJSON != "":
l.Infof("Authorizing with JSON credentials")
l.Infof("Authorizing with JSON credentials environment variable")
opts = append(opts, cloudsqlconn.WithCredentialsJSON(
[]byte(c.CredentialsJSON),
))
Expand Down
13 changes: 13 additions & 0 deletions tests/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package tests
import (
"context"
"database/sql"
"io/ioutil"
"net/http"
"net/http/httputil"
"os"
Expand Down Expand Up @@ -54,6 +55,18 @@ func removeAuthEnvVar(t *testing.T) (*oauth2.Token, string, func()) {
}
}

func keyfile(t *testing.T) string {
path := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
if path == "" {
t.Fatal("GOOGLE_APPLICATION_CREDENTIALS not set")
}
creds, err := ioutil.ReadFile(path)
if err != nil {
t.Fatalf("io.ReadAll(): %v", err)
}
return string(creds)
}

// proxyConnTest is a test helper to verify the proxy works with a basic connectivity test.
func proxyConnTest(t *testing.T, args []string, driver, dsn string) {
ctx, cancel := context.WithTimeout(context.Background(), connTestTimeout)
Expand Down
22 changes: 20 additions & 2 deletions tests/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,24 @@ func TestMySQLAuthWithCredentialsFile(t *testing.T) {
"mysql", cfg.FormatDSN())
}

func TestMySQLHealthCheck(t *testing.T) {
testHealthCheck(t, *mysqlConnName)
func TestMySQLAuthWithCredentialsJSON(t *testing.T) {
if testing.Short() {
t.Skip("skipping MySQL integration tests")
}
requireMySQLVars(t)
creds := keyfile(t)
_, _, cleanup := removeAuthEnvVar(t)
defer cleanup()

cfg := mysql.Config{
User: *mysqlUser,
Passwd: *mysqlPass,
DBName: *mysqlDB,
AllowNativePasswords: true,
Addr: "127.0.0.1:3306",
Net: "tcp",
}
proxyConnTest(t,
[]string{"--credentials-json", creds, *mysqlConnName},
"mysql", cfg.FormatDSN())
}
5 changes: 4 additions & 1 deletion tests/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,14 @@ func TestPostgresAuthWithCredentialsJSON(t *testing.T) {
t.Skip("skipping Postgres integration tests")
}
requirePostgresVars(t)
creds := keyfile(t)
_, _, cleanup := removeAuthEnvVar(t)
defer cleanup()

dsn := fmt.Sprintf("host=localhost user=%s password=%s database=%s sslmode=disable",
*postgresUser, *postgresPass, *postgresDB)
proxyConnTest(t,
[]string{"--credentials-json", os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"), *postgresConnName},
[]string{"--credentials-json", string(creds), *postgresConnName},
"pgx", dsn)
}

Expand Down
16 changes: 16 additions & 0 deletions tests/sqlserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ func TestSQLServerAuthWithCredentialsFile(t *testing.T) {
"sqlserver", dsn)
}

func TestSQLServerAuthWithCredentialsJSON(t *testing.T) {
if testing.Short() {
t.Skip("skipping SQL Server integration tests")
}
requireSQLServerVars(t)
creds := keyfile(t)
_, _, cleanup := removeAuthEnvVar(t)
defer cleanup()

dsn := fmt.Sprintf("sqlserver://%s:%s@127.0.0.1?database=%s",
*sqlserverUser, *sqlserverPass, *sqlserverDB)
proxyConnTest(t,
[]string{"--credentials-json", creds, *sqlserverConnName},
"sqlserver", dsn)
}

func TestSQLServerHealthCheck(t *testing.T) {
testHealthCheck(t, *sqlserverConnName)
}

0 comments on commit 7f2ba2d

Please sign in to comment.