如何从 API 网关端点向 lambda 授权方提供自定义数据
How to provide custom data from API gateway endpoint to lambda authorizer
我们正在使用的 API 网关端点应通过对特定受众的权限进行限制。
想法是使用 lambda 授权方从外部服务获取权限,然后创建策略以允许或拒绝对端点的访问。
为了匹配 API 端点的权限,端点需要向授权方提供它需要的权限。
我现在的问题是如何使用自己所需的权限丰富端点数据并在授权方 lambda 中使用它们(可能通过事件)以进行进一步验证。
示例:
- User1 被转发到第一个端点 GET/petstore/pets(此端点需要权限 -> View:Pets)
- Lambda 授权方请求来自外部服务的用户权限
- 服务returns:[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 的事件包含一个 methodArn,其格式为:
arn:aws:execute-api:<Region id>:<Account id>:<API id>/<Stage>/<Method>/<Resource path>
这将为您提供所需的方法和资源路径。它还会为您提供 API 的标识符,但不会为您提供 API 本身的名称。
API id,可用于通过AWS SDK获取API名称。参见 here。
这应该为您提供构建 endpointPermissions 值所需的一切。
我在无需解析 ARN 的情况下找到了问题的解决方案,但这非常不合常规:
- 在资源的方法请求中创建 URL 带有权限名称的查询字符串参数并设置 'required'
的复选框
- 当从客户端 (Postman) 调用请求时,这些强制参数必须作为键提供,它们是端点特定的。这些值无关紧要,因为在评估时只会使用键。
授权方收到的事件现在包含可以评估以供进一步使用的 queryStringParameters。
我们正在使用的 API 网关端点应通过对特定受众的权限进行限制。
想法是使用 lambda 授权方从外部服务获取权限,然后创建策略以允许或拒绝对端点的访问。
为了匹配 API 端点的权限,端点需要向授权方提供它需要的权限。
我现在的问题是如何使用自己所需的权限丰富端点数据并在授权方 lambda 中使用它们(可能通过事件)以进行进一步验证。
示例:
- User1 被转发到第一个端点 GET/petstore/pets(此端点需要权限 -> View:Pets)
- Lambda 授权方请求来自外部服务的用户权限
- 服务returns:[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 的事件包含一个 methodArn,其格式为:
arn:aws:execute-api:<Region id>:<Account id>:<API id>/<Stage>/<Method>/<Resource path>
这将为您提供所需的方法和资源路径。它还会为您提供 API 的标识符,但不会为您提供 API 本身的名称。
API id,可用于通过AWS SDK获取API名称。参见 here。
这应该为您提供构建 endpointPermissions 值所需的一切。
我在无需解析 ARN 的情况下找到了问题的解决方案,但这非常不合常规:
- 在资源的方法请求中创建 URL 带有权限名称的查询字符串参数并设置 'required' 的复选框
- 当从客户端 (Postman) 调用请求时,这些强制参数必须作为键提供,它们是端点特定的。这些值无关紧要,因为在评估时只会使用键。
授权方收到的事件现在包含可以评估以供进一步使用的 queryStringParameters。