如何从API网关端点向lambda授权者提供自定义数据

时间:2018-11-16 09:20:20

标签: amazon-web-services aws-lambda authorization aws-api-gateway lambda-authorizer

我们正在使用的API网关端点必须通过对特定受众的权限进行限制。

想法是使用lambda授权器从外部服务获取权限,然后创建策略以允许或拒绝对端点的访问。

为使权限与API端点匹配,端点需要向授权者提供所需的权限。

我的问题是,现在我该如何利用其自身所需的权限来充实端点数据,并在授权者lambda中(可能通过事件)使用它们进行进一步的验证。

示例:

  • User1被转发到第一个端点 GET / petstore / pets (此端点需要权限-> View:Pets
  • Lambda授权者从外部服务请求用户权限
  • 该服务返回:[ View:Pets View:Somethingelse 等。]
  • lambda授权者将用户权限与所需的端点权限进行匹配,并在匹配项上创建“允许”策略
  • User2相同,但没有查看宠物的权限,没有匹配项->拒绝

这是我的lambda代码:

import {Callback, Context} from 'aws-lambda';
import {Authorizer} from './authorizer';

export class App {

    constructor(private authorizer: Authorizer = new Authorizer()) {
    }

    public handleEvent(event, callback: Callback): Promise<void> {
        return this.authorizer.checkAuthorization(event, callback)
            .then((policy) => callback(null, policy))
            .catch((error) => callback(error, null));
    }

}

const app: App = new App();

module.exports.lambda_handler = async (event) => {
    return await app.handleEvent(event);
};

checkAuthorization方法的代码:

export class Authorizer {


    public resourceAuthorizer: ResourceAuthorizer = new ResourceAuthorizer();
    public authenticationChecker: AuthenticationChecker = new AuthenticationChecker();

    public checkAuthorization(event, callback): Promise<object> {

        const endpointPermissions = event.endpointPermissions;  // <== this is what I need, a custom field in the event which
                                                            // is provided from the api endpoint in some way
                                                            // in my example this whould contain a string or json 
                                                            // with 'View:Pets' and 'View:Somethingelse'

        return this.authenticationChecker.check(event)
            .then((decodedJwt) => {
                const principalId: string = decodedJwt.payload.sub;

            return Promise.resolve(decodedJwt)
                .then((jwt) => this.resourceAuthorizer.check(jwt, event.endpointPermissions))
                .then((payload) => callback(null,
                getAuthorizationPolicy(principalId, 'Allow', event.endpointPermissions, payload)))
                .catch((payload) => callback(null,
                getAuthorizationPolicy(principalId, 'Deny', event.endpointPermissions, payload)));
            }).catch((error) => {
                console.log(error);
                callback('Unauthorized');
            });
    }
}

event.endpointPermissions 基本上就是我想要的。根据API端点,应使用该端点所需的权限来填充。然后,resourceAuthorizer从外部服务获取用户的权限,并将其与endpointPermissions进行比较,然后创建“允许”或“拒绝”策略。

那么我在哪里可以在API端点中输入endpointPermissions以提供给Authorizer?

2 个答案:

答案 0 :(得分:1)

传递给授权者的事件包含methodArn,其格式为:

arn:aws:execute-api:<Region id>:<Account id>:<API id>/<Stage>/<Method>/<Resource path>

这将为您提供所需的方法和资源路径。它还会为您提供API的标识符,而不是API本身的名称。

API ID可用于通过使用AWS开发工具包获取API名称。参见here

这应该为您提供构造EndpointPermissions值所需的一切。

答案 1 :(得分:0)

我无需解析ARN就可以解决我的问题,但这非常不常规:

  1. 在资源的方法请求中,创建具有权限名称的URL查询字符串参数,并设置“必需”复选框。

method request URL query string parameters

  1. 从客户端(邮递员)调用请求时,必须将这些强制性参数作为键提供,它们是特定于端点的。值无关紧要,因为评估时只使用键。

postman request parameters

  1. 授权者收到的事件现在包含queryStringParameters,可以对其进行评估以进一步使用。

    queryStringParameters in cloudwatch