我有点不知道这里可能出了什么问题。我一直遵循这组说明,让我的 Lambda 根据以下说明使用 IAM 身份验证连接到 RDS: https://cloudonaut.io/passwordless-database-authentication-for-aws-lambda/
现在,我已经检查我的 RDS 集群确实启用了 IAM 身份验证 - 我已经创建了用户并授予了所有必要的权限(执行了几次),并且我已经验证了此处的“签名者”步骤确实生成了一个据称有效的令牌。
此外,lambda 具有
rds-db:connect
的权限,我什至为 lambda 角色添加了 RDS 完全访问权限(尽管我认为这不是必需的)。
不过,当我尝试连接时,我只是得到了这个:
"errorType": "Error",
"errorMessage": "Access denied for user 'mydbuser'@'19.196.193.217' (using password: YES)",
"code": "ER_ACCESS_DENIED_ERROR",
"errno": 1045,
"sqlState": "28000",
"sqlMessage": "Access denied for user 'mydbuser'@'19.196.193.217' (using password: YES)",
我还注意到我得到的令牌有一些 URL 编码位,所以我尝试对其进行 URL 解码,但这并没有导致任何结果。
我不知道这可能会在哪里失败,而且错误消息完全没有帮助。相关用户的补助金是:
GRANT USAGE ON *.* TO 'mydbuser'@'%'
GRANT ALL PRIVILEGES ON `mydbuser`.* TO 'mydbuser'@'%'
所以这暗示它不接受令牌作为密码。我的连接代码如下所示:
const mysql = require('mysql2');
...
signer.getAuthToken({
region: 'my+region',
hostname: process.env.ENDPOINT,
port: 3306,
username: 'mydbuser'
}, function(err, token) {
var connection = mysql.createConnection({
host: process.env.ENDPOINT,
port: 3306,
user: 'mydbuser',
password: token,
database: 'mydb',
ssl: { ca: fs.readFileSync(__dirname + '/rds-combined-ca-bundle.pem') },
authSwitchHandler: function (data, cb) {
if (data.pluginName === 'mysql_clear_password') {
cb(null, Buffer.from(token + '\0'));
}
}
});
connection.connect((res, err) => {
console.log(res, err);
});
connection.query(
`SELECT 1;`, ...
此外,完整生成的令牌确实包含
X-Amz-Security-Token
,因此它暗示根据我迄今为止的研究,它是有效的。
此时还有什么可能失败?
我用
Python
遇到了这个确切的问题,我花了很长时间才弄清楚。
我的问题不是数据库配置或 IAM 权限问题,而是与连接参数有关。我正在使用
AWS Aurora MySQL
连接到 sqlalchemy
+ 使用 pymysql
IAM Authentication
:
DBHostname = DBCLUSTER_HOSTNAME
DBPort = DBCLUSTER_PORT
DBUsername = DBCLUSTER_USER
DBName = DBCLUSTER_NAME
engine = sqlalchemy.create_engine(
"mysql+pymysql:///"
) # connection params will be set by the event callback
@sqlalchemy.event.listens_for(engine, "do_connect")
def provide_token(dialect, conn_rec, cargs, cparams):
client = boto3.client("rds")
token = client.generate_db_auth_token(
DBHostname=DBHostname,
Port=int(DBPort),
DBUsername=DBUsername,
Region=REGION,
)
# set up db connection parameters, alternatively we can get these from boto3 describe_db_instances
cparams["host"] = DBHostname
cparams["port"] = int(DBPort)
cparams["user"] = DBUsername
cparams["password"] = token
cparams["database"] = DBName
cparams["ssl"] = {
"ca": "ssl-ca-bundle.pem",
"verify_identity": False,
}
cparams["auth_plugin_map"] = {
"mysql_clear_password": None,
}