无法通过IAM身份验证访问RDS数据库

时间:2018-01-07 14:44:27

标签: amazon-web-services go amazon-rds

我无法使用IAM用户连接到我的RDS数据库。

数据库用户名:master
IAM用户:api-user

我已为用户分配了用户程序化访问权限并添加了以下政策:

enter image description here

自定义rds-permission定义为:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html

    {
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
             "rds-db:connect"
         ],
         "Resource": [
             "arn:aws:rds-db:REGION:ACCOUNT-ID:USER:dbi-resource-id/DB_ACCOUNT_NAME"
         ]
      }
   ]
}

奇怪的是,即使我已经完全按照文档中的要求定义了我的自定义权限,也无法识别:

enter image description here

enter image description here

当我尝试使用身份验证令牌(通过golang)进行连接时,我收到以下错误:

error: ERROR: Error 1045: Access denied for user 'master'@'x.x.x.189' (using password: YES)

我的政策似乎不起作用!

即使它是无关紧要的,这是我通过我的IAM用户连接的方式:

//Yes Env vars are available
//creating new credentials from environment variables
//AWS_ACCESS_KEY_ID  and  AWS_SECRET_ACCESS_KEY
awsCreds := credentials.NewEnvCredentials()

//creating authentication token for the database connection
authToken, err := rdsutils.BuildAuthToken(dbEndpoint, awsRegion, dbUser, awsCreds)
if err != nil {
    Logger.LogFatal("Unable to build Authentication Token")
    log.Fatal("Unable to build Authentication Token")  //todo remove
}

//setting up TLS
mysql.RegisterTLSConfig("custom", &tls.Config{
    InsecureSkipVerify: true,
})

// Creating the MySQL DNS string for the DB connection
// user:password@protocol(endpoint)/dbname?<params>
dnsStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s allowCleartextPasswords=true&tls=custom",
    dbUser, authToken, dbEndpoint,dbPort, dbName,
)
rootCertPool := x509.NewCertPool() //NewCertPool returns a new, empty CertPool.

pem, err := ioutil.ReadFile("rds-ca-bundle.pem") //reading the provided pem
if err != nil {
    log.Fatal("! Could not read certificates")
}
fmt.Println("Loading certificate seems to work")
//AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
//pushing in the pem
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
    log.Fatal("Failed to append PEM.")
}
fmt.Println("Appending certificate seems to work too")

//setting up TLS
//we dont need a client ca?
mysql.RegisterTLSConfig("custom", &tls.Config{
    RootCAs: rootCertPool,
    InsecureSkipVerify: true,
})
database, err = sql.Open("mysql", dnsStr)

3 个答案:

答案 0 :(得分:3)

根据来自AWS Github存储库的Go编程语言示例,您需要创建如下凭据:

IAM ARN

参考: IAM authentication go example

import (
    "database/sql"
    "fmt"
    "log"
    "os"

    "github.com/go-sql-driver/mysql"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/rds/rdsutils"
)

awsCreds := stscreds.NewCredentials(session.New(&aws.Config{Region: &awsRegion}), iamArn) 

// iamArn: arn:aws:rds-db:region:account-id:dbuser:dbi-resource-id/data‌​base-user-name

authToken, err := rdsutils.BuildAuthToken(dbEndpoint, awsRegion, dbUser, awsCreds)

我几乎可以肯定你错过了IAM ARN的那一部分。

准备数据库用户

参考: Preparing a Database User

  

您需要连接到数据库并使用AWS身份验证插件创建用户。

     

以下SQL语句创建名为lambda的数据库用户。 AWSAuthenticationPlugin不是指定密码,而是用于标识用户。替换为您要授予用户访问权限的数据库的名称。

CREATE USER 'master' IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
GRANT ALL PRIVILEGES ON <DB_NAME>.* TO 'master'@'%';
FLUSH PRIVILEGES;

奖金推荐

参考: Limitations for IAM Database Authentication

我不知道您的项目中IAM身份验证的目的是什么,但我认为AWS文档中的以下内容非常重要:

  

IAM数据库身份验证的限制

     

使用IAM数据库身份验证,每秒最多限制为20个新连接。如果您使用的是db.t2.micro实例类,则限制为每秒10个连接。

     

Amazon RDS for MySQL和Aurora MySQL数据库引擎不会对每秒的身份验证尝试施加任何限制。但是,使用IAM数据库身份验证时,应用程序必须生成身份验证令牌。然后,您的应用程序使用该令牌连接到数据库实例或群集。如果超过每秒最大新连接数限制,则IAM数据库身份验证的额外开销可能会导致连接限制。额外的开销甚至可能导致现有连接丢失。

     

我们建议如下:

     
      
  • 使用IAM数据库身份验证作为临时,个人访问数据库的机制。

  •   
  • 如果您的应用程序每秒需要超过20个新连接,请不要使用IAM数据库身份验证。

  •   
  • 仅对可以轻松重试的工作负载使用IAM数据库身份验证。

  •   
     

注意

     

有关MySQL的最大总连接数的信息,请参阅最大MySQL连接数。有关Aurora MySQL的最大总连接数的信息,请参阅Aurora MySQL数据库实例的最大连接数。

答案 1 :(得分:0)

我也遇到了同样的问题。在我添加了用于构建Auth令牌的端口号之后(在网上进行了大量查找),它得到了解决。

之前是这样的:

authToken, err := rdsutils.BuildAuthToken(host, region, username, sess.Config.Credentials)

我必须更改为:

authToken, err := rdsutils.BuildAuthToken(fmt.Sprintf("%s:%d", host, 3306), region, username, sess.Config.Credentials)

这是针对Golang应用程序的。但是其他语言SDK也可能适用。 我从https://luktom.net/en/e1544-aws-lambda-and-mysql-iam-authentication-in-go

得到了这个答案

AWS的某些人需要更新其 official docs on this

答案 2 :(得分:0)

Ele 提供的答案部分错误,这是正确的代码:

arn := "arn:aws:iam::00000000000:role/your-TaskRole"
awsCreds := stscreds.NewCredentials(session.New(&aws.Config{Region: aws.String(Region)}), arn)

所以 arn 不是 iam db 用户之一,而是分配给您的资源(EC2、ECS、Fargate)的角色的 arn

请记住,您也必须使用 TLS 通过 IAM 身份验证连接到数据库