Skip to content

Commit

Permalink
fix: impersonated user uses downscoped token
Browse files Browse the repository at this point in the history
When an impersonated user logs in with Auto IAM AuthN, the login token
is downscoped to support login only.

Fixes #1519.
  • Loading branch information
enocom committed Oct 31, 2022
1 parent 18c7e58 commit fd7089d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 9 deletions.
17 changes: 17 additions & 0 deletions internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ func dialOptions(c Config, i InstanceConnConfig) []cloudsqlconn.DialOption {
return opts
}

const iamLoginScope = "https://www.googleapis.com/auth/sqlservice.login"

func credentialsOpt(c Config, l cloudsql.Logger) (cloudsqlconn.Option, error) {
// If service account impersonation is configured, set up an impersonated
// credentials token source.
Expand Down Expand Up @@ -238,6 +240,21 @@ func credentialsOpt(c Config, l cloudsql.Logger) (cloudsqlconn.Option, error) {
if err != nil {
return nil, err
}
if c.IAMAuthN {
iamLoginTS, err := impersonate.CredentialsTokenSource(
context.Background(),
impersonate.CredentialsConfig{
TargetPrincipal: c.ImpersonateTarget,
Delegates: c.ImpersonateDelegates,
Scopes: []string{iamLoginScope},
},
iopts...,
)
if err != nil {
return nil, err
}
return cloudsqlconn.WithIAMAuthNTokenSources(ts, iamLoginTS), nil
}
return cloudsqlconn.WithTokenSource(ts), nil
}

Expand Down
43 changes: 34 additions & 9 deletions tests/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"flag"
"fmt"
"os"
"strings"
"testing"

"github.com/GoogleCloudPlatform/cloud-sql-proxy/v2/internal/proxy"
Expand Down Expand Up @@ -196,16 +197,40 @@ func TestPostgresIAMDBAuthn(t *testing.T) {
t.Fatal("'postgres_user_iam' not set")
}

dsn := fmt.Sprintf("host=localhost user=%s database=%s sslmode=disable",
defaultDSN := fmt.Sprintf("host=localhost user=%s database=%s sslmode=disable",
*postgresIAMUser, *postgresDB)
// using the global flag
proxyConnTest(t,
[]string{"--auto-iam-authn", *postgresConnName},
"pgx", dsn)
// using the instance-level query param
proxyConnTest(t,
[]string{fmt.Sprintf("%s?auto-iam-authn=true", *postgresConnName)},
"pgx", dsn)
impersonatedIAMUser := strings.ReplaceAll(*impersonatedUser, ".gserviceaccount.com", "")

tcs := []struct {
desc string
dsn string
args []string
}{
{
desc: "using default flag",
args: []string{"--auto-iam-authn", *postgresConnName},
dsn: defaultDSN,
},
{
desc: "using query param",
args: []string{fmt.Sprintf("%s?auto-iam-authn=true", *postgresConnName)},
dsn: defaultDSN,
},
{
desc: "using impersonation",
args: []string{
"--auto-iam-authn",
"--impersonate-service-account", *impersonatedUser,
*postgresConnName},
dsn: fmt.Sprintf("host=localhost user=%s database=%s sslmode=disable",
impersonatedIAMUser, *postgresDB),
},
}
for _, tc := range tcs {
t.Run(tc.desc, func(t *testing.T) {
proxyConnTest(t, tc.args, "pgx", tc.dsn)
})
}
}

func TestPostgresHealthCheck(t *testing.T) {
Expand Down

0 comments on commit fd7089d

Please sign in to comment.