无法通过IAM用户连接RDS数据库:合规权限仍报错求助
Let's walk through the common issues that could be causing your 1045 Access denied error when trying to connect to RDS using IAM authentication. Even if your IAM policy looks correct, there are several easy-to-miss steps that often trigger this problem.
1. Verify IAM Database Authentication is Enabled on Your RDS Instance
First things first: if your RDS instance doesn't have IAM database authentication turned on, no amount of correct IAM policies will work.
- Go to the AWS RDS Console, select your instance
- Check the Configuration tab for the "IAM database authentication" setting
- Ensure it's set to Enabled (you may need to modify the instance if it's not)
2. Validate Your IAM Policy's Resource ARN
Your policy uses the right format, but double-check the placeholder values are 100% accurate:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["rds-db:connect"], "Resource": ["arn:aws:rds-db:REGION:ACCOUNT-ID:USER:dbi-resource-id/master"] } ] }
- REGION: Must match your RDS instance's region (e.g.,
us-east-1, avoid typos likeuseast-1) - ACCOUNT-ID: Your 12-digit AWS account ID (no hyphens)
- dbi-resource-id: Find this in your RDS instance's Details tab under "Resource ID", or run
aws rds describe-db-instances --query "DBInstances[*].DbiResourceId" - master: Ensure this matches your MySQL username exactly (MySQL is case-sensitive by default)
Test if the policy works using the AWS CLI to simulate the action:
aws iam simulate-custom-policy \ --policy-document file://rds-permission.json \ --action-names rds-db:connect \ --resource-arns arn:aws:rds-db:REGION:ACCOUNT-ID:USER:dbi-resource-id/master
Look for Allowed: true in the output to confirm the policy grants access.
3. Ensure Your MySQL User is Configured for IAM Authentication
Even with the right IAM permissions, your MySQL user master needs to be set up to use the AWS authentication plugin. Run these commands in your MySQL instance (use a regular password-based connection first):
-- Grant basic usage (adjust the database scope as needed) GRANT USAGE ON *.* TO 'master'@'%' REQUIRE SSL; -- Enable AWS IAM authentication for the user ALTER USER 'master'@'%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; -- Flush privileges to apply changes immediately FLUSH PRIVILEGES;
Note: @'%' allows connections from any IP; you can restrict this to your client's IP later, but keep it open for testing.
4. Fix Issues in Your Golang Code
Looking at your code, there are a couple of potential problems:
- Duplicate TLS Config Registration: You register the
customTLS config twice, which can cause unexpected behavior. Combine these into one step. - InsecureSkipVerify: While this works for testing, it's better to use the RDS CA bundle properly instead of skipping verification.
- Missing Connection Ping:
sql.Open()only creates the connection pool, it doesn't test the connection—add aPing()call to validate.
Here's an optimized version of your code:
package main import ( "crypto/tls" "crypto/x509" "database/sql" "fmt" "io/ioutil" "log" "os" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/service/rdsutils" _ "github.com/go-sql-driver/mysql" ) var ( dbUser = os.Getenv("DB_USER") dbEndpoint = os.Getenv("DB_ENDPOINT") awsRegion = os.Getenv("AWS_REGION") dbPort = os.Getenv("DB_PORT") dbName = os.Getenv("DB_NAME") ) func main() { // Load and validate AWS credentials awsCreds := credentials.NewEnvCredentials() _, err := awsCreds.Get() if err != nil { log.Fatalf("Failed to load AWS credentials: %v", err) } // Build IAM authentication token authToken, err := rdsutils.BuildAuthToken(dbEndpoint, awsRegion, dbUser, awsCreds) if err != nil { log.Fatalf("Failed to build auth token: %v", err) } // Load RDS CA certificate bundle rootCertPool := x509.NewCertPool() pemBytes, err := ioutil.ReadFile("rds-ca-bundle.pem") if err != nil { log.Fatalf("Could not read RDS CA file: %v", err) } if !rootCertPool.AppendCertsFromPEM(pemBytes) { log.Fatal("Failed to add RDS CA certificate to pool") } // Register TLS config once err = mysql.RegisterTLSConfig("custom", &tls.Config{ RootCAs: rootCertPool, // Disable InsecureSkipVerify in production! InsecureSkipVerify: false, }) if err != nil { log.Fatalf("Failed to register TLS config: %v", err) } // Build MySQL connection string dnsStr := fmt.Sprintf( "%s:%s@tcp(%s:%s)/%s?allowCleartextPasswords=true&tls=custom", dbUser, authToken, dbEndpoint, dbPort, dbName, ) // Open connection pool and verify connection db, err := sql.Open("mysql", dnsStr) if err != nil { log.Fatalf("Failed to open connection pool: %v", err) } defer db.Close() // Ping to confirm the connection works if err := db.Ping(); err != nil { log.Fatalf("Failed to connect to RDS: %v", err) } fmt.Println("Successfully connected to RDS using IAM authentication!") }
5. Double-Check Network and Security Group Settings
While your error is an authentication issue (not a connection timeout), it's worth confirming:
- Your RDS security group allows inbound traffic on port 3306 from your client's IP
- Your client has internet access to the RDS instance (or is in the same VPC with proper routing)
Work through these steps in order—most likely, the issue is either missing the RDS IAM authentication toggle, incorrect MySQL user configuration, or a typo in your IAM policy's resource ARN.
内容的提问来源于stack exchange,提问作者thelearner

