了解具有 IAM 权限的组

Cognito Groups with IAM Permissions

我要实现的:

我有一个 Cognito 用户池,我有一些用户和一些组。我希望某些用户可以访问 API 网关功能,一些用户可以访问某些功能,而其他用户则不能访问。

我做了什么:

我创建了三个组并将用户分配给每个组。我为每个组分配了一个 IAM 角色,并为每个角色分配了特定的策略。所有用户的组权限如下所示:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "execute-api:*",
            "Resource": "*"
        }
     ]
}

我通过无服务器框架创建了 Lambda 函数和 API 网关资源。我将授权方设置为 Cognito 用户池授权方。

(我尝试了一些不同的方法,比如使用联合身份,但似乎效果不佳)

我的结果是什么:

所有用户都可以完全访问 API 网关。给定的权限似乎对每个用户的访问没有任何影响。

帮助: 我做错了什么? 我怎样才能实现我的目标?

我有更好的解决方案,您不需要 IAM。

只需将 {username, serviceName} 对保存在 S3 或 DB 中。所以每次,您都会收到服务请求:

  1. 检查用户是否获得授权(来自 Cognito)。
  2. 检查用户是否有权使用该服务(S3、MySQL、RDS 等)。

为什么我觉得更好

因为来自服务的 adding/removing 用户,您不需要以管理员身份登录 IAM。希望以后,您可以创建一个用于管理的仪表板。

工作流程

  1. UserA 向您的 securityApi 发送请求。
  2. SecurityApi 检查令牌是否已授权(用户是否有效)。

  3. 如果UserA有效,则securityApi发送用户的username(可以从token的payload中获取)和service name 给一个DB,看用户是否有权限访问该用户。例如 Mysql(为此使用 RDS):

    SELECT username from ServiceX LIMIT 1 WHERE username = "xyz"; 
    
  4. 如果第二步或第三步通过则用户为 1. 有效用户 2. 有权使用该服务。如果用户在步骤 2 或 3 中失败,则用户未被授权使用该服务。

附加到 user pool group 的角色只有在您使用 Cognito Federated Identity 为用户生成凭据时才会出现。 Adding groups to a user pool

IAM roles and their permissions are tied to the temporary AWS credentials that Amazon Cognito identity pools provide for authenticated users. Users in a group are automatically assigned the IAM role for the group when AWS credentials are provided by Amazon Cognito Federated Identities using the Choose role from token option.

所以基本上

  1. 创建一个 identity pool 附加到您的用户池。
  2. 将 API 网关的授权更改为 IAM
  3. 登录用户池后,用户id_token生成federated identity
  4. 使用此身份 (secret key + access key + token) 通过 API 网关进行授权。

现在你的角色应该得到尊重。但请注意 - 您将需要自己生成 AWS SigV4 凭据,因为出于某种原因,这不是开箱即用的。我最终在浏览器中使用 aws-sign-web

PS:您的角色似乎授予对 API 网关的全面访问权限。您还需要修复它。例如我用来限制对一个 API 端点

的访问的样本角色
{
"Version": "2012-10-17",
"Statement": [
    {
        "Action": "execute-api:Invoke",
        "Resource": [
            "arn:aws:execute-api:us-east-2:<aws account id>:<API id>/*/*/acc/*"
        ],
        "Effect": "Allow"
    }
]
}

生成示例代码federated identity

function getAccessToken(idToken, idenPoolId, userPool) {
        let region = idenPoolId.split(":")[0];
        let provider = "cognito-idp." + region + ".amazonaws.com/" + userPool;
        let login = {};

        login[provider] = idToken;

        // Add the User's Id Token to the Cognito credentials login map.
        let credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: idenPoolId,
            Logins: login
        });

        //call refresh method in order to authenticate user and get new temp credentials
        credentials.get((error) => {
            if (error) {
                console.error(error);

                //let response = {
                //  statusCode: 500,
                //  body: JSON.stringify(error)
                //};

                return null;

            } else {
                console.log('Successfully logged!');
                console.log('AKI:'+ credentials.accessKeyId);
                console.log('AKS:'+ credentials.secretAccessKey);
                console.log('token:' + credentials.sessionToken);

                let response = JSON.stringify({
                    'AKI': credentials.accessKeyId,
                    'AKS': credentials.secretAccessKey,
                    'token': credentials.sessionToken
                });

                return response;
            }
        });
    }