Как предоставить пользовательские данные от конечной точки шлюза API к лямбда-авторизатору

Конечные точки шлюза API, которые мы используем, должны быть ограничены разрешениями для определенной аудитории.

Идея состоит в том, чтобы использовать лямбда-авторизатор для получения разрешений от внешней службы, а затем создать политику, разрешающую или запрещающую доступ к конечной точке.

Для сопоставления разрешений конечной точке API конечная точка должна предоставить разрешения, необходимые для авторизатора.

Мой вопрос сейчас заключается в том, как я могу обогатить данные конечной точки своими собственными необходимыми разрешениями и использовать их в лямбда-выражении авторизатора (возможно, через событие) для дальнейшей проверки.

Пример:

  • Пользователь1 перенаправляется на первую конечную точку GET / petstore / pets(для этой конечной точки требуется разрешение -> Вид: Домашние животные)
  • Лямбда-авторизатор запрашивает у пользователя разрешения у внешнего сервиса
  • Служба возвращает: [Вид: Домашние животные, Вид: Что-то еще и т. Д.]
  • Лямбда-авторизатор сопоставляет разрешения пользователя с требуемым разрешением конечной точки и создает политику разрешения на совпадение.
  • User2 делает то же самое, но не имеет разрешения на просмотр домашних животных, нет совпадений -> Запретить

Вот мой код для лямбды:

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, а затем создает политики "Разрешить" или "Запретить".

Итак, где я могу ввести endpointPermissions в моей конечной точке API, чтобы предоставить их Авторизатору?

2 ответа

Решение

Событие, передаваемое Authorizer, содержит метод Arn, который имеет формат:

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

Это даст вам метод и ресурсный путь, который вам нужен. Это также даст вам идентификатор API, но не имя самого API.

Идентификатор API можно использовать для получения имени API с помощью AWS SDK. Смотрите здесь.

Это должно дать вам все необходимое для построения значения endpointPermissions.

У меня есть решение моей проблемы без разбора ARN, но это довольно нетрадиционно:

  1. В методе запроса ресурса создайте параметры строки запроса URL с именами разрешений и установите флажок "обязательно"

запрос метода URL параметры строки запроса

  1. Когда запрос вызывается из клиента (почтальона), эти обязательные параметры должны быть предоставлены как ключи, они зависят от конечной точки. Значения не имеют значения, потому что при оценке будут использоваться только ключи.

параметры запроса почтальона

  1. Событие, полученное авторизатором, теперь содержит queryStringParameters, который можно оценить для дальнейшего использования.

    queryStringParameters в облачном хранилище

Другие вопросы по тегам