AWS RDS-DB:Connect 适用于用户,但不适用于角色

问题描述 投票:0回答:1

我可以将相同的策略分配给 AWS IAM 中的用户和角色,当我尝试使用角色连接到 RDS 时,它不起作用,但当我使用用户连接时,它确实起作用。我对角色和用户设置了相同的策略,并设置了我的代码,以便我可以在直接使用用户和承担角色的用户之间切换。唯一的区别是 cred 变量中是否有凭证属性。

用户和代入角色都可以访问SecretsManager,但只有用户可以访问RDS数据库。 RDS 日志显示该角色的 PAM 身份验证失败,因此出现了问题。

  const cred = false ? {} : {
    credentials: await new STSClient({ region: "us-east-2" }).send(new AssumeRoleCommand({
      RoleArn: "... valid role arn ...",
      RoleSessionName: "Test",
    })).then(role => {
      if (!role.Credentials?.AccessKeyId || !role.Credentials.SecretAccessKey) throw "failed to assume role";
      console.log("Role Assumed");
      return {
        accessKeyId: role.Credentials.AccessKeyId,
        secretAccessKey: role.Credentials.SecretAccessKey,
        sessionToken: role.Credentials.SessionToken,
      };
    })
  };
  const { SecretString: normalstr } = await new SecretsManagerClient({ region: "us-east-2", ...cred }).send(new GetSecretValueCommand({
    SecretId: "... valid secret arn ...",
    VersionStage: "AWSCURRENT",
  }));
  const env = JSON.parse(normalstr);
  const rds = new Signer({
    region: env.DB_REGION,
    hostname: env.DB_HOSTNAME,
    port: +env.DB_PORT,
    username: auth.user,
    ...cred
  });
  
  const db = await getPrismaClient(rds);

  db.customer.findUnique({...});
  // The role gets: User `user` was denied access on the database `db.public`
  // The user gets a successful query


  1. 我到处寻找任何拒绝语句,但在用户、角色或策略中找不到任何拒绝语句。我在 RDS 中找不到数据库的任何类型的资源策略。角色和用户都没有设置权限边界。
  2. 所有 AssumeRole 权限均已正确设置,因为代入的角色可以访问机密。
  3. 在 lambda 中运行具有相同角色的相同代码会出现相同的错误(这开始了本次调查)。
  4. 不久前我也遇到了 ec2 的问题,我通过将用户访问密钥直接放在机密中来解决,这确实不是 AWS 希望您做的,但它应该工作的方式实际上并不.
  5. 该用户没有附加任何其他权限或策略,因此肯定来自此策略。

要记住的重要一点是,我对用户和角色有相同的策略,并且两者都可以访问秘密管理器,这是策略中的项目之一,但只有用户可以访问数据库,这是政策中的其他项目。

typescript amazon-rds amazon-iam
1个回答
0
投票

问题最终是因为我试图使用 URL 对象构造连接字符串。不知何故,它对角色造成了破坏,但对用户却没有造成影响。我通过记录密码(签名的 RDS 令牌)然后将其直接粘贴到 PG Admin 中来解决这个问题。成功了。

长话短说:不要这样做:

    const dburl = new URL("https://dud");
    dburl.username = username;
    dburl.password = password;
    dburl.hostname = DB_HOSTNAME;
    dburl.port = DB_PORT;
    dburl.pathname = DB_NAME;
    dburl.search = "?sslmode=require";
    // cut https: and set the protocol
    return "postgres:" + dburl.toString().slice(6);

这样做:

    return `postgres://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${DB_HOSTNAME}:${DB_PORT}/${encodeURIComponent(DB_NAME)}?sslmode=require`
© www.soinside.com 2019 - 2024. All rights reserved.