AWS API Gateway

时间:2018-06-14 12:54:31

标签: amazon-web-services aws-api-gateway aws-cognito

我正在构建一个应用程序,用户可以通过Rest API访问DynamoDb中的某些数据。

我的想法是:

  1. 用户访问API网关,由Cognito用户池进行身份验证;
  2. API Gateway调用Lambda函数(用Python编写);
  3. Lambda函数访问DynamoDB并返回数据。
  4. 我希望能够根据用户限制对DynamoDb的访问级别。最初我认为Lambda函数可以继承用户的权限,但这不起作用,因为它需要执行角色。

    实现这一目标的最佳方法是什么?例如,我可以将用户信息传递给Lambda函数,而Lambda函数又可以在访问DynamoDb之前承担此角色吗?如果是这样,我们将感激代码示例。

3 个答案:

答案 0 :(得分:0)

查看SpaceFinder - Serverless Auth Reference AppUse API Gateway Lambda Authorizers

使用Cognito,您可以使用RBAC:

  

Amazon Cognito标识池为您的经过身份验证的用户分配一组   用于访问AWS资源的临时,有限权限凭据。   通过IAM角色控制每个用户的权限   你创造。您可以定义规则以为每个用户选择角色   基于用户ID令牌中的声明。您可以定义默认角色   对于经过身份验证的用您还可以使用单独的IAM角色定义   对未经过身份验证的访客用户的有限权限。

所以你可以为每个用户创建特定的角色,尽管最好使用组

使用Lambda授权人,您可以创建自己的策略。一个例子是awslabs

答案 1 :(得分:0)

除了blueCat的答案外,我还短暂地尝试赋予Lambda函数sts:AssumeRole权限,然后让其承担通过API调用它的Cognito用户的角色。然后,我可以使用它来获取一组新的凭据,并在Cognito用户的权限下进行一些活动。 lambda内部的代码大致是:

def lambda_handler(event, context):
    sts_client = boto3.client('sts')
    role = event['requestContext']['authorizer']['claims']['cognito:roles']
    cognito_role = sts_client.assume_role(
        RoleArn=role,
        RoleSessionName='lambda-session',
        DurationSeconds=3600
    )
    credentials = cognito_role['Credentials']
    sess = boto3.session.Session(
        aws_access_key_id=credentials['AccessKeyId'], 
        aws_secret_access_key=credentials['SecretAccessKey'],
        aws_session_token=credentials['SessionToken']
    )
    # Do something as the assumed user, e.g. access S3
    s3_client = sess.client('s3')
    # Do stuff here...

尽管这有效,但我发现承担该角色并获取S3客户端大约需要0.5 s的开销,并且由于该函数是特定于用户的,因此无法在函数调用之间重用此会话。因此,这种方法并不适合我的应用程序。

我已经决定让我的Lambda拥有对相关DynamoDb表的完全访问权限,并使用Cognito用户组和Lambda授权者来限制个人用户可以调用的API部分。

答案 2 :(得分:0)

我也处理了这个问题,但是我用Node.js实现了我的解决方案,我发现虽然您的问题是针对Python实现的,但也许有人会偶然发现这个问题,以寻求JS的答案,我想到了这可以帮助下一个来的人。

听起来好像您在用户使用自定义属性针对您的Cognito用户池拥有Authorization的凭据后,正在尝试制定有效的Authenticated策略。

我创建了一个库,该库用于导出一些函数,这些函数可以让我捕获已验证用户的UserPoolIdUsername,以便捕获custom:<attribute>我需要在lambda内使用,以便实现的条件可以将API消耗给我需要为我的应用程序已认证的每个用户提供授权的其余AWS服务。

这是我的图书馆:

import AWS from "aws-sdk";
// ensure correct AWS region is set
AWS.config.update({
    region: "us-east-2"
});

// function will parse the user pool id from a string
export function parseUserPoolId(str) {
    let regex = /[^[/]+(?=,)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the user pool id: ", match);

    return match.toString();
}

// function will parse the username from a string
export function parseUserName(str) {
    let regex = /[a-z,A-Z,0-9,-]+(?![^:]*:)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the username: ", match);

    return match.toString();
}

// function retries UserAttributes array from cognito
export function getCustomUserAttributes(upid, un) {
    // instantiate the cognito IdP
    const cognito = new AWS.CognitoIdentityServiceProvider({
        apiVersion: "2016-04-18"
    });

    const params = {
        UserPoolId: upid,
        Username: un
    };

    console.log("UserPoolId....: ", params.UserPoolId);
    console.log("Username....: ", params.Username);

    try {
        const getUser = cognito.adminGetUser(params).promise();
        console.log("GET USER....: ", getUser);
        // return all of the attributes from cognito
        return getUser;
    } catch (err) {
        console.log("ERROR in getCustomUserAttributes....: ", err.message);
        return err;
    }
}

实施此库后,现在您可以为其创建授权策略的任何lambda都使用它。

在您的lambda里面,您需要导入上面的库(我在下面省略了import语句,您将需要添加这些以便可以访问导出的函数),并且可以实现它们的用法:

export async function main(event, context) {
  const upId = parseUserPoolId(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Step 2 --> Get the UserName from the requestContext
  const usrnm = parseUserName(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Request body is passed to a json encoded string in
  // the 'event.body'
  const data = JSON.parse(event.body);

  try {
    // TODO: Make separate lambda for AUTHORIZATION
    let res = await getCustomUserAttributes(upId, usrnm);

    console.log("THIS IS THE custom:primaryAccountId: ", res.UserAttributes[4].Value);
    console.log("THIS IS THE custom:ROLE: ", res.UserAttributes[3].Value);
    console.log("THIS IS THE custom:userName: ", res.UserAttributes[1].Value);

    const primaryAccountId = res.UserAttributes[4].Value;

  } catch (err) {
    // eslint-disable-next-line
    console.log("This call failed to getattributes");
    return failure({
      status: false
    });
  }
}


Cognito的响应将为数组提供所需的自定义属性。 Console.log使用console.log("THIS IS THE Cognito response: ", res.UserAttributes);记录Cognito的响应,并在CloudWatch日志中检查所需属性的索引号,并使用以下方法调整所需的索引:

res.UserAttributes[n]

现在,您拥有一种authorization机制,可以在lambda中以不同条件使用该机制,以允许用户POST到DynamoDB,或使用您的应用程序中的任何其他AWS服务,并为每个经过身份验证的用户提供正确的授权。

相关问题