Closed KarthickEmis closed 2 years ago
Hi @KarthickEmis, thanks for reaching out to us and I do apologize for the delay in response. Using IAM DB Authentication to connect to Aurora Posgresql is very similar to IAM DB authentication for MySQL. You'll want to ensure your engine version is high enough to support IAM DB Authentication (I used 10.7 in my test) and follow these steps to ensure you have a database account that has IAM DB authentication granted to it, from there the code example for rdsutils.BuildAuthToken should work with minor changes:
sql.Open()
command you'll want to replace "mysql"
with "postgres"
to ensure you are using the correct driver when connecting to your database.Please don't hesitate to reach back out to us if you need further assistance with this.
Hi @KarthickEmis, thanks for reaching out to us and I do apologize for the delay in response. Using IAM DB Authentication to connect to Aurora Posgresql is very similar to IAM DB authentication for MySQL. You'll want to ensure your engine version is high enough to support IAM DB Authentication (I used 10.7 in my test) and follow these steps to ensure you have a database account that has IAM DB authentication granted to it, from there the code example for rdsutils.BuildAuthToken should work with minor changes:
- You'll want to import a postgres driver such as pq in order to open a connection to your database
- In the
sql.Open()
command you'll want to replace"mysql"
with"postgres"
to ensure you are using the correct driver when connecting to your database.Please don't hesitate to reach back out to us if you need further assistance with this.
Hi, Thanks for your reply... I tried in two ways , First I tried with the same you specified(rdsutils.BuildAuthToken ) , but throwing the below error. panic: dial tcp 127.0.0.1:5432: connect: connection refused
awsCreds := stscreds.NewCredentials(session.New(), "**lambdarolearn**")
authToken, err := rdsutils.BuildAuthToken(fmt.Sprintf("%s:%d", config["dbhost"], 5432),
awsRegion, "test", awsCreds)
connectStr := fmt.Sprintf("%s:%s@tcp(%s)/%s?allowCleartextPasswords=true&tls=rds",
"test", authToken, config["dbhost"], config["dbname"])
db, err = sql.Open("postgres", connectStr)
fmt.Printf(" ping db dnsStrr: %s\n", db.Ping())
When i tried in the another way , it throws panic: pq: password authentication failed for user "test"
PFB my code for using iam db authentication
awsCreds := stscreds.NewCredentials(session.New(), "**lambdarolearn**")
authToken, err := rdsutils.BuildAuthToken(fmt.Sprintf("%s:%d", config["dbhost"], 5432),
awsRegion, "test", awsCreds)
dnsStrr := fmt.Sprintf("host=%s port=%d user=%s dbname=%s sslmode=require password=%s",
config["dbhost"], 5432, "test", config["dbname"], authToken)
db, err = sql.Open("postgres", dnsStrr)
fmt.Printf(" ping db dnsStrr: %s\n", db.Ping())
Kindly let me know how to connect to aurora postgresql using iam db authentication.If you have any working example kindly let me know how it is working. Note: I created 10.7 engine version of aurora postgresql
Hello, I'm running into the same issues, and would greatly appreciate some clarification.
@KarthickEmis I've seen the same error you were getting with panic: dial tcp 127.0.0.1
. I think the issue is DSN string parsing in the pq library. Without postgresql://
at the start of the string, it doesn't know to interpret it as a URN, and likely falls back to a default of localhost. I've also had parsing problems because the security token contains the hostname, so if you pass it unescaped in the password
section, it confuses the URN parser.
Like you, I changed from the URN format to the key=value
style DSN and I'm getting better results that way.
@diehlaws I've noticed that if I generate an IAM RDS token using the command line tools, I get a much shorter token, and that token does work to connect to RDS:
$ aws rds generate-db-auth-token --hostname "assetsvc-dev.cfuosmcvqhmr.eu-west-1.rds.amazonaws.com" --port 5432 --region eu-west-1 --username listener > token
$ cat token
assetsvc-dev.cfuosmcvqhmr.eu-west-1.rds.amazonaws.com:5432/?Action=connect&DBUser=listener&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAWHS7GR7QWGRME3HK%2F20191121%2Feu-west-1%2Frds-db%2Faws4_request&X-Amz-Date=20191121T180221Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=ea6c92bb18e20bd17e826adcb8be29a643f5241df47aaa8657fd9e03e4ba54a4
The working token from the CLI tools is only 373 chars long and contains these fields:
In contrast, the token returned by rdsutils.BuildAuthToken
is 1230 characters long, with a different format:
assetsvc-dev.cfuosmcvqhmr.eu-west-1.rds.amazonaws.com:5432?Action=connect&DBUser=listener&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAWHS7GR7QQBLEFKCO%2F20191121%2Feu-west-1%2Frds-db%2Faws4_request&X-Amz-Date=20191121T164430Z&X-Amz-Expires=900&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEMj%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCWV1LXdlc3QtMSJHMEUCIQCP4gOih5kj4WceKMbxzxkSHcII7IRCkLKBEDUM1961TAIgHa5VF4g00y6S0GOjnqVZGGrcI1dJJhlng%2FsxfKws9c4q7wEI8f%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw0Mjg2MjI2NDcyNjUiDL2uWiIFqGnsnPwxiSrDAejeP1IGHeO0Z1NAxcElHHhmeFwpUriJv9vqfrElEkzrqOyVfINzgzI7GPoaU63m8K70ALJA87sHMGl7%2BbYZebnaummG4JnuVPVnn7tR0HlYRwr9ZZUJhlxmAdVdcMpEuPfN50WaG7mQtq%2FXsMKSCzYhA%2ByjXB3bfOhMi68gBVPVQ7zyh%2BKZgkzB3%2BqQyUWqcO3ZX3MoD8KnuXP4IWLG7FKEDP92iynDgnJR7Cl%2FbkdbaEmfmBYu1N73ybGHqfK0vuKX2DC85truBTrgAVPFFA2BhYkQK6HooVyuye6NbYcxWtw3aWLEhy8mUJsvsWkGfG6fH24Bt8m4hqMOufKSPFiWmBKhlCAhH0JCM20GvL6xXAObzhuBIUTVRsSW7tz561iVwrZTrIUVCsMTphTdttHAR%2BpEJuMhTSys9SYn5FqZDRxLMCjHYWfp3d8Z1mIvJYOhNucXaYk6srDhKRYnCMeVe4yT8gUTDZbgsG8hNlzK2%2FUInQbYElpyJEseU6y6CZVeFACWhvtD8FCzEBN%2BXKCFqkqZ5JYjiRUBcDp2osayWmF6bYuzAMphPr5W&X-Amz-SignedHeaders=host&X-Amz-Signature=02d9aa1fbfe574b000695f8e988253f878d010b13f705a847fca587e3c56c7d9
And it contains these fields:
The token from rdsutils
does not work. I get an error like this:
panic: DB Ping() failed: pq: PAM authentication failed for user "listener"
Can anyone clarify the difference, and explain how to use rdsutils
with Postgres RDS/Aurora? A complete working example using rdsutils.BuildAuthToken
with the pq
driver would be extremely helpful.
@diehlaws Would it be helpful if I opened a separate issue with a minimal example showing my own code? Or is it easier to keep discussion concentrated here?
Thanks for any advice or examples you can offer.
I am encountering a similar issues as here. Please provide a small example on how to use it.
Thanks
I was able to get this working. I was passing extra port value to the host earlier while generating the token and it was leading to failed: pq: PAM authentication failed for user
error
Below is the code
func authToken(dbHost, dbUser, region, roleARN string) (token string, err error) {
awsCreds := stscreds.NewCredentials(services.NewSession(aws.NewConfig()), roleARN)
token, err = rdsutils.BuildAuthToken(dbHost, region, dbUser, awsCreds)
return
}
func main() {
roleARN := os.Getenv("DB_ACCESS_ROLE_ARN")
region := os.Getenv("AWS_REGION")
dbHostPort := os.Getenv("DB_HOST") // <host>:<port>
dbUser := os.Getenv("DB_USER")
dbName := os.Getenv("DB_NAME")
dbHost := strings.Split(dbHostPort, ":")[0]
dbPort := strings.Split(dbHostPort, ":")[1]
token, err := authToken(dbHost, dbUser, region, roleARN)
if err == nil {
// http://gorm.io/docs/connecting_to_the_database.html
dbURI := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s", dbHost, dbPort, dbUser, dbName, token)
_, err := gorm.Open("postgres", dbURI)
if err != nil {
log.Panic("Could not get connection")
}
}
}
@KarthickEmis @bjmc ^
I was able to get this working. I was passing extra port value to the host earlier while generating the token and it was leading to failed: pq: PAM authentication failed for user error Below is the code func authToken(dbHost, dbUser, region, roleARN string) (token string, err error) { awsCreds := stscreds.NewCredentials(services.NewSession(aws.NewConfig()), roleARN) token, err = rdsutils.BuildAuthToken(dbHost, region, dbUser, awsCreds) return }
func main() { roleARN := os.Getenv("DB_ACCESS_ROLE_ARN") region := os.Getenv("AWS_REGION") dbHostPort := os.Getenv("DB_HOST") //
: dbUser := os.Getenv("DB_USER") dbName := os.Getenv("DB_NAME") dbHost := strings.Split(dbHostPort, ":")[0] dbPort := strings.Split(dbHostPort, ":")[1] token, err := authToken(dbHost, dbUser, region, roleARN) if err == nil { // http://gorm.io/docs/connecting_to_the_database.html dbURI := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s", dbHost, dbPort, dbUser, dbName, token) _, err := gorm.Open("postgres", dbURI) if err != nil { log.Panic("Could not get connection") } } }
@KarthickEmis @bjmc ^
Hi , PFB for the working piece of code for the IAM DB Authentication package main
import (
"database/sql"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/aws/external"
"github.com/aws/aws-sdk-go-v2/service/rds/rdsutils"
_ "github.com/lib/pq"
)
const awsRegion = "eu-west-2"
func init() {
fmt.Println(" test code base")
cfg, err := external.LoadDefaultAWSConfig()
if err != nil {
fmt.Println(err)
}
config := gettoken()
authToken, err := rdsutils.BuildAuthToken(fmt.Sprintf("%s:%d", config["dbhost"], 5432),
awsRegion, "test", cfg.Credentials)
dnsStrr := fmt.Sprintf("host=%s port=%d user=%s dbname=%s sslmode=require password=%s",
config["dbhost"], 5432, "test", config["dbname"], authToken)
fmt.Println("authtoken: " + authToken)
fmt.Println("--------------------------------------------------------------: ")
fmt.Println("dnsStrr: " + dnsStrr)
db, err = sql.Open("postgres", dnsStrr)
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected with IAM Authentication Token dnsStrr!")
defer db.Close()
}
func gettoken() map[string]string {
conf := make(map[string]string)
conf["dbhost"] = "ur db host name"
conf["dbport"] = "5432"
conf["dbuser"] = "ur user name"
conf["dbname"] = "db user name"
return conf
}
I have not verified it, but for benefit of others on this thread, somebody has written a tutorial with sample code.
I have not verified it, but for benefit of others on this thread, somebody has written a tutorial with sample code.
author of that guide here
Unfortunately, AWS has completely changed their function signatures as of one of their newer library updates without documenting the change whatsoever (which they shouldn’t be doing according to the Golang specs, it should be a new version).
Since this is a breaking undocumented change, and based on some of the comments towards questions asking for better password lifecycle management I’d recommend using a different solution for authentication. Its clear that IAM authentication is a bit of an afterthought or at least geared towards lambda use. If I do get the time to look for a solution I’ll update my guide but since we transitioned away from this in my application it might take a moment
Update on this issue here https://github.com/califlower/golang-aws-rds-iam-postgres/issues/5
We have noticed this issue has not received attention in 1 year. We will close this issue for now. If you think this is in error, please feel free to comment and reopen the issue.
AWS folks, what's the verdict? It doesn't look like this issue has been resolved. Could we please have a complete working example in the docs?
Is this related to a problem?
A clear and concise description of the issue, e.g. I'm always frustrated when...
Feature description
Describe what you want to happen.
Describe alternatives you've considered
Any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Currently this project is having iam db authentication for mysql.
How to connect to Aurora postgresql using iam db authentication?