2022-09-14 12:46:34 -07:00
// Copyright (c) HashiCorp, Inc.
2021-06-25 14:06:31 -04:00
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2020-10-10 16:12:04 -04:00
package connect
import (
2021-06-25 14:06:31 -04:00
"fmt"
"os"
2020-10-10 16:12:04 -04:00
"strings"
2023-10-22 17:48:54 -07:00
"github.com/hashicorp/boundary/api/proxy"
2020-10-10 16:12:04 -04:00
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/posener/complete"
)
const (
postgresSynopsis = "Authorize a session against a target and invoke a Postgres client to connect"
)
func postgresOptions ( c * Command , set * base . FlagSets ) {
f := set . NewFlagSet ( "Postgres Options" )
f . StringVar ( & base . StringVar {
Name : "style" ,
Target : & c . flagPostgresStyle ,
EnvVar : "BOUNDARY_CONNECT_POSTGRES_STYLE" ,
Completion : complete . PredictSet ( "psql" ),
Default : "psql" ,
Usage : `Specifies how the CLI will attempt to invoke a Postgres client. This will also set a suitable default for -exec if a value was not specified. Currently-understood values are "psql".` ,
})
f . StringVar ( & base . StringVar {
Name : "username" ,
Target : & c . flagUsername ,
EnvVar : "BOUNDARY_CONNECT_USERNAME" ,
Completion : complete . PredictNothing ,
2021-06-25 14:06:31 -04:00
Usage : `Specifies the username to pass through to the client. May be overridden by credentials sourced from a credential store.` ,
})
f . StringVar ( & base . StringVar {
Name : "dbname" ,
Target : & c . flagDbname ,
EnvVar : "BOUNDARY_CONNECT_DBNAME" ,
Completion : complete . PredictNothing ,
Usage : `Specifies the database name to pass through to the client.` ,
2020-10-10 16:12:04 -04:00
})
}
type postgresFlags struct {
flagPostgresStyle string
}
func ( p * postgresFlags ) defaultExec () string {
return strings . ToLower ( p . flagPostgresStyle )
}
2023-10-22 17:48:54 -07:00
func ( p * postgresFlags ) buildArgs ( c * Command , port , ip , _ string , creds proxy . Credentials ) ( args , envs [] string , retCreds proxy . Credentials , retErr error ) {
2022-07-20 15:17:15 -07:00
var username , password string
retCreds = creds
2023-10-22 17:48:54 -07:00
if len ( retCreds . UsernamePassword ) > 0 {
2022-07-20 15:17:15 -07:00
// Mark credential as consumed so it is not printed to user
2023-10-22 17:48:54 -07:00
retCreds . UsernamePassword [ 0 ]. Consumed = true
2022-06-15 09:30:45 -07:00
2022-07-20 15:17:15 -07:00
// For now just grab the first username password credential brokered
2023-10-22 17:48:54 -07:00
username = retCreds . UsernamePassword [ 0 ]. Username
password = retCreds . UsernamePassword [ 0 ]. Password
2021-06-25 14:06:31 -04:00
}
2020-10-10 16:12:04 -04:00
switch p . flagPostgresStyle {
case "psql" :
2024-01-21 19:34:33 -08:00
if port != "" {
args = append ( args , "-p" , port )
}
args = append ( args , "-h" , ip )
2021-06-25 14:06:31 -04:00
if c . flagDbname != "" {
args = append ( args , "-d" , c . flagDbname )
}
switch {
2022-07-20 15:17:15 -07:00
case username != "" :
args = append ( args , "-U" , username )
2021-06-25 14:06:31 -04:00
case c . flagUsername != "" :
2020-10-10 16:12:04 -04:00
args = append ( args , "-U" , c . flagUsername )
}
2021-06-25 14:06:31 -04:00
2022-07-20 15:17:15 -07:00
if password != "" {
2022-09-14 12:46:34 -07:00
passfile , err := os . CreateTemp ( "" , "*" )
2021-06-25 14:06:31 -04:00
if err != nil {
2023-10-22 17:48:54 -07:00
return nil , nil , proxy . Credentials {}, fmt . Errorf ( "Error saving postgres password to tmp file: %w" , err )
2021-06-25 14:06:31 -04:00
}
c . cleanupFuncs = append ( c . cleanupFuncs , func () error {
if err := os . Remove ( passfile . Name ()); err != nil {
return fmt . Errorf ( "Error removing temporary password file; consider removing %s manually: %w" , passfile . Name (), err )
}
return nil
})
2022-07-20 15:17:15 -07:00
_ , err = passfile . WriteString ( fmt . Sprintf ( "*:*:*:*:%s" , password ))
2021-06-25 14:06:31 -04:00
if err != nil {
2023-10-22 17:48:54 -07:00
return nil , nil , proxy . Credentials {}, fmt . Errorf ( "Error writing password file to %s: %w" , passfile . Name (), err )
2021-06-25 14:06:31 -04:00
}
if err := passfile . Close (); err != nil {
2023-10-22 17:48:54 -07:00
return nil , nil , proxy . Credentials {}, fmt . Errorf ( "Error closing password file after writing to %s: %w" , passfile . Name (), err )
2021-06-25 14:06:31 -04:00
}
envs = append ( envs , fmt . Sprintf ( "PGPASSFILE=%s" , passfile . Name ()))
if c . flagDbname == "" {
c . UI . Warn ( "Credentials are being brokered but no -dbname parameter provided. psql may misinterpret another parameter as the database name." )
}
}
2020-10-10 16:12:04 -04:00
}
2021-06-25 14:06:31 -04:00
return
2020-10-10 16:12:04 -04:00
}