简体   繁体   English

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

[英]How to provide custom data from API gateway endpoint to lambda authorizer

The API Gateway endpoints we are using shall be restricted via permissions to a specific audience. 我们使用的API网关端点应通过对特定受众的权限进行限制。

The idea is to use the lambda authorizer to fetch the permissions from an external service and then create the policy to allow or deny access to the endpoint. 想法是使用lambda授权器从外部服务获取权限,然后创建策略以允许或拒绝对端点的访问。

For the matching of the permissions to the API endpoint the endpoint would need to provide the permissions it needs to the authorizer. 为了使权限与API端点匹配,端点将需要向授权者提供所需的权限。

My question is now how can I enrich the endpoint data with its own required permissions and use them in the authorizer lambda(probably via the event) for further validation. 我的问题是,现在我该如何利用自己所需的权限来充实端点数据,并在授权者lambda中使用它们(可能通过事件)以进行进一步的验证。

Example: 例:

  • User1 is forwarded to the first endpoint GET/petstore/pets (this endpoint needs the permission -> View:Pets ) 将User1转发到第一个端点GET / petstore / pets (此端点需要权限-> View:Pets
  • Lambda authorizer requests the user permissions from the external service Lambda授权者从外部服务请求用户权限
  • The service returns: [ View:Pets , View:Somethingelse , etc.] 服务返回:[ View:PetsView:Somethingelse等]
  • The lambda authorizer matches the user permissions against the required endpoint permission and creates the Allow policy on a match Lambda授权者将用户权限与所需的端点权限进行匹配,并在匹配项上创建“允许”策略
  • User2 does the same but does not have the permission for viewing pets, no match -> Deny User2相同,但是没有查看宠物的权限,没有匹配项->拒绝

Here is my code for the lambda: 这是我的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);
};

Code for the checkAuthorization method: 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');
            });
    }
}

The event.endpointPermissions is basically what I am looking for. event.endpointPermissions基本上是我想要的。 Depending on the API endpoint this should be filled with the permissions neccessary for that endpoint. 根据API端点,应使用该端点所需的权限来填充。 The resourceAuthorizer then fetches the users Permissions from the external service and compares them to the endpointPermissions and then creates the Allow or Deny policies. 然后,resourceAuthorizer从外部服务中获取用户权限,并将其与endpointPermissions进行比较,然后创建“允许”或“拒绝”策略。

So where can I enter the endpointPermissions in my API Endpoint to provide them to the Authorizer? 因此,在哪里可以在API端点中输入endpointPermissions以将其提供给Authorizer?

The event being passed to the Authorizer contains a methodArn, which is in the format: 传递给Authorizer的事件包含methodArn,其格式为:

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

This would give you the Method and Resource Path that you need. 这将为您提供所需的方法和资源路径。 It also would give you an identifier of the API, but not the name of the API itself. 它还会为您提供API的标识符,但不会提供API本身的名称。

The API id, can be used to get the API name by using the AWS SDK. 通过使用AWS开发工具包,可以使用API​​ ID来获取API名称。 See here . 这里

This should give you everything you need to construct your endpointPermissions value. 这应该为您提供构造EndpointPermissions值所需的一切。

I got a solution to my problem without having to parse the ARN, but it's pretty unconventional: 我无需解析ARN就可以解决我的问题,但这非常不常规:

  1. In the method request of a resource create URL query string parameters with the permission names and set the checkbox for 'required' 在资源的方法请求中,创建具有权限名称的URL查询字符串参数,并设置“必需”复选框

方法请求URL查询字符串参数

  1. When the request is called from the client(Postman) these mandatory parameters have to be provided as keys, they are endpoint-specific. 从客户端(邮递员)调用请求时,必须将这些强制性参数作为键提供,它们是特定于端点的。 The values do not matter because only the keys will be used at evaluation. 值无关紧要,因为评估时仅会使用键。

邮递员请求参数

  1. The event received by the authorizer now contains the queryStringParameters which can be evaluated for further use. 授权者收到的事件现在包含queryStringParameters,可以对其进行评估以进一步使用。

    cloudwatch中的queryStringParameters

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM