使用 Cognito UnAuth 角色时的 IAM 权限问题

Posted

技术标签:

【中文标题】使用 Cognito UnAuth 角色时的 IAM 权限问题【英文标题】:IAM permission issue when using Cognito UnAuth role 【发布时间】:2021-08-18 01:23:58 【问题描述】:

我正在制作一个简单的 React 应用程序来通过 DescribeDBInstances API 访问 RDS 数据。我想允许公共访问,所以我使用 Cognito 并启用了未经身份验证的访问。

我为提供的 UnAuth 角色附加了以下策略,但在尝试从 javascript (nodejs) 使用 RDS API 时仍然收到以下错误:


    "Version": "2012-10-17",
    "Statement": [
        
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "rds:DescribeDBInstances",
            "Resource": "*"
        
    ]

AccessDenied: User: arn:aws:sts::(account):assumed-role/Cognito_TestUnauth_Role/CognitoIdentityCredentials is not authorized to perform: rds:DescribeDBInstances on resource: arn:aws:rds:us-east-1:(account):db:*

我修改了我的帐户 ID。

还附加了此默认策略:


    "Version": "2012-10-17",
    "Statement": [
        
            "Effect": "Allow",
            "Action": [
                "mobileanalytics:PutEvents",
                "cognito-sync:*"
            ],
            "Resource": "*"
        
    ]

这是我的调用代码:

import  RDSClient, DescribeDBInstancesCommand  from "@aws-sdk/client-rds";
import  CognitoIdentityClient  from "@aws-sdk/client-cognito-identity";
import  fromCognitoIdentityPool  from "@aws-sdk/credential-provider-cognito-identity";

// see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-rds/index.html
export default async function getDbInstances() 
    const region = "us-east-1";
    const client = new RDSClient(
        region,
        credentials: fromCognitoIdentityPool(
          client: new CognitoIdentityClient( region ),
          identityPoolId: "(my identity pool ID)",
        )
    );

    const command = new DescribeDBInstancesCommand();
    return await client.send(command).DBInstances;

我有点疯了,看来一切都设置正确了。缺少什么?

【问题讨论】:

【参考方案1】:

我在 Cognito 的 IAM 角色文档中找到了答案:https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html(请参阅“访问策略”部分)

建议 Cognito 使用增强型身份验证并默认启用,但由于它在后台使用 GetCredentialForIdentity API,因此无论 IAM 策略如何,访问都仅限于某些 AWS 服务(RDS 不是允许的服务)。我没有看到任何方法可以覆盖此限制。

解决方案是切换到基本身份验证(您必须先在 Cognito 身份池设置中启用它)。这是我使用基本身份验证然后获取 RDS 实例的工作 nodejs 代码:

import  RDSClient, DescribeDBInstancesCommand  from "@aws-sdk/client-rds";
import  
    CognitoIdentityClient, 
    GetIdCommand ,
    GetOpenIdTokenCommand
 from "@aws-sdk/client-cognito-identity";
import  getDefaultRoleAssumerWithWebIdentity  from "@aws-sdk/client-sts";
import  fromWebToken  from "@aws-sdk/credential-provider-web-identity";

const region = "us-east-1";
const cognitoClient = new CognitoIdentityClient( region )

// see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-rds/index.html
export default async function getDbInstances() 
    const  Token, IdentityId  = await getTokenUsingBasicFlow();
    const client = new RDSClient(
        region,
        credentials: fromWebToken( 
            roleArn: "arn:aws:iam::(account id):role/Cognito_RDSDataAppPoolUnauth_Role",
            webIdentityToken: Token,
            roleSessionName: IdentityId.substring(IdentityId.indexOf(":") + 1),
            roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity()
         )
    );

    const command = new DescribeDBInstancesCommand();
    return (await client.send(command)).DBInstances;


async function getTokenUsingBasicFlow() 
    const getIdCommand = new GetIdCommand( IdentityPoolId: "us-east-1:(identity pool id)" );
    const id = (await cognitoClient.send(getIdCommand)).IdentityId;
    const getOpenIdTokenCommand = new GetOpenIdTokenCommand( IdentityId: id );
    return await cognitoClient.send(getOpenIdTokenCommand);

这是我编写实现所遵循的基本身份验证流程与增强版的文档:https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html

【讨论】:

以上是关于使用 Cognito UnAuth 角色时的 IAM 权限问题的主要内容,如果未能解决你的问题,请参考以下文章

从 Cognito 组担任 IAM 角色

AWS Cognito 角色:区分联合身份池角色和用户池组角色

使用 Cognito IAM 角色的端点上的 Spring 安全性?

为 aws cognito id 令牌生成基于角色的声明

模糊角色映射规则:cognito with microsoft active directory

我们可以在 AWS Cognito 的单个用户池中拥有多个角色吗?