Как защитить микросервисы в AWS с помощью Cognito, API Gateway и Lambda

1656551541 kak zashhitit mikroservisy v aws s pomoshhyu cognito api gateway
1*CKz6WCjkxktPPhGtpXGefA
Позвольте мне войти! (Гифи)

Обрабатывать аутентификацию болезненно. Но большинство программ нужно аутентифицировать пользователей и контролировать, к каким ресурсам они могут получить доступ. Микросервисы, хотя и становятся популярнее, могут прибавлять сложности. Вам нужно подстраховаться оба действия и взаимодействия пользователя между услуги.

AWS предлагает несколько отличных строительных блоков для архитектуры микросервисов. Но, как и мебель из IKEA, вам придется собирать детали самостоятельно. Кроме того, инструкции не очень хорошие.

Мы создадим простую программу и настроим AWS на проверку подлинности пользователя и защиту микросервиса.

TL;DR (для нетерпеливых)

Рабочая демонстрация: (пользователь: demouser пароль: demoPASS123)

GitHub Repo: https://github.com/csepulv/auth-api-demo

Базовый вариант использования/предположения: Есть две группы ресурсов. а) нуждающиеся аутентифицирован пользователь и б) те, что нет.

Мы воспользуемся

Для дочитавших до конца есть вкусности.

Теперь для деталей.

Концептуальная модель применения

Демо-приложение реализует следующую модель.

1*vq_EQibUjpiCK1C_rF1azg
  • Пользователь входит в программу и получает маркер аутентификации
  • AWS использует этот маркер для подтверждения личности и для авторизации запросов пользователей на защищенные ресурсы
  • шлюз приложений создает виртуальный ров между пользователями и ресурсами программы

Сервисы AWS

Если вы новичок в AWS, есть официальный портал AWS Getting Started. Кроме того, Udemy имеет бесплатный курс AWS Essentials.

Вам нужен доступ к аккаунту AWS. Вы можете подписаться на бесплатный уровень AWS.

AWS Lambda

Хотя EC2 является одним из самых популярных вариантов AWS, я думаю, что Lambda лучше подходит для микросервисов. Экземпляры EC2 являются виртуальными машинами. Вы несете ответственность за все, от операционной системы до всего запускаемого программного обеспечения. Лямбда – это модель функции как службы. Нет предоставления или развертывания сервера; вы пишете свою логику обслуживания.

Дополнительную информацию см. в документации AWS Lambda.

Но с лямбдами есть складка. Пользователь программы не может получить прямой доступ к ним. Лямбда-функции нужны триггеры, вызывающие функцию Лямбда. Это может быть сообщение в очереди или в нашем случае запрос шлюза API.

Шлюз AWS API

Шлюз API обеспечивает ров вокруг ваших служб приложений. Он может регистрировать активность пользователей, аутентифицировать запросы и использовать политику использования (например, ограничение скорости). (Документация AWS API Gateway является хорошим справочником.)

AWS Cognito

AWS Cognito — это служба управления пользователями, аутентификация и контроль доступа. К сожалению, все функции и конфигурация могут запутать. (Подобно безопасности и аутентификации всегда были легкими. ? ) Мы сосредоточимся на основных элементах Cognito для защиты нашего API.

Настройка программы и среды

1*b46gRLzVry1kr8ikUOrXMg
Элементы программы

Рецепт нашей демонстрационной программы:

  1. В AWS Cognito создайте пользовательский пул (с клиентской программой) и федеративный пул идентификационных данных.
  2. В AWS API Gateway создайте план использования и ключ API
  3. Используя Claudia JS, создайте и разверните простой API на основе AWS Lambda.
  4. Обновите роль AWS IAM для предоставления аутентифицированным пользователям доступа к защищенным методам API
  5. Создайте одностраничное приложение (SPA) с помощью create-react-app. Он будет использовать AWS Cognito и выполнять подписанные (и аутентифицированные) запросы API

Подробные настройки AWS включаются aws-setup.md, в демонстрационном репозитории GitHub Мы выделим аспекты настройки и объясним, как все работает.

AWS Cognito

Пул пользователей, клиентская программа и доменное имя

Мы создадим пул пользователей со значениями по умолчанию. Детали и скриншоты:

Объединенный пул идентификационных данных

Может быть немного непонятно, что нам нужен и пул пользователей, и федеративный пул идентификационных данных. Ашан Фернандо имеет достаточно хорошее объяснение в этой публикации. Проще говоря,

  • Пулы пользователей предоставить пользователю доступ к программе. Это похоже на такие службы, как Auth0.
  • А Объединенный пул идентификационных данных предоставляет доступ к ресурсам AWS.

Объединив два пула, наше приложение может аутентифицировать пользователя, а AWS назначит временные учетные данные. Эти учетные данные дают пользователю доступ к ресурсам AWS. Роль IAM, настроенная в пуле идентификационных данных, определяет привилегии для временных учетных данных.

Подробная настройка пула федеративных идентификационных данных находится здесь.

Шлюз AWS API

Я предлагаю создать план использования для нашего API. Хотя это не обязательное условие, это хорошая практика, поскольку затраты на AWS могут «убежать», если вы не будете осторожны. Мы создадим а План использованияназван api-auth-demo и установите частоту дросселя и пакета, а также ежедневную квоту для вызовов API. Мы также создадим ключ API, который будет использовать веб-клиентское приложение. (Полная информация о настройках здесь.)

1*hyVIHxcwGElJbWp3cEYebw
лимиты и квоты

Мы завершили основную часть настройки AWS. Теперь мы напишем наши лямбда-функции, а затем создадим наше веб-приложение React.

AWS Lambda и Claudia JS

Мы напишем наши лямбда функции с помощью Node.js. Claudia.js развернет наши Lambdas и настроит шлюз API. (Обратите внимание, что бессерверная платформа придает подобную функциональность.)

Для нашего примера нам нужен простой API. Мы создадим два метода API (то есть очень простые микросервисы): один для аутентифицированных пользователей и один для гостей.

Мы будем использовать Claudia API Builder, позволяющий отображать несколько маршрутов на одну лямбду. Механизм маршрутизации подобен маршрутизации в таких фреймворках, как Express.js.


const ApiBuilder = require("claudia-api-builder");
const api = new ApiBuilder();

api.get("/no-auth",request => {
    return {message: "Open for All!"};
  },
  { apiKeyRequired: true }
);

api.get("/require-auth", request => {
    return {message: "You're past the velvet rope!"};
  },
  { apiKeyRequired: true, authorizationType: "AWS_IAM" }
);

module.exports = api;
view rawapi.js hosted with ❤ by GitHub

Мы будем использовать командную строку Claudia.js для развертывания API в AWS.

claudia create --region us-west-2  --api-module api --name auth-api-demo

ПРИМЕЧАНИЕ. Любые изменения в api.js нужно будет повторно развернуть. Используйтеclaudia update...

Ключи API и авторизация

в api.js, {apiKeyRequired: true} указывает, что для запросов API требуется ключ API. {authorizationType: 'AWS_IAM'} настройка шлюза API для авторизации с помощью AWS IAM. Основной механизм аутентификации не очевиден. Документы AWS описывают подход, но результат:

  • когда пользователь войдет в систему, Cognito выдаст токены для временных учетных данных (полученных через STS).
  • для защищенных ресурсов приложение должно подписывать запросы с помощью этих учетных данных
  • AWS декодирует и проверяет подпись
  • если подпись действительна, шлюз API отправляет запрос

Есть и другие способы авторизации. В документации Claudia.js описано, как указать другие методы. (Соответствующие документы AWS находятся здесь.)

Роли AWS IAM для аутентифицированных пользователей

Нам нужно изменить привилегии для ролей IAM для аутентифицированных пользователей. Нам нужно разрешить вызвать созданный нами метод API Gateway.

Нам нужен ARN шлюз API. Выделите консоль API Gateway и найдите ресурс/метод API Gateway.

1*EaRh0csoB_smLKrY42uIBA
ARN (показано выделено)
  • Скопируйте ARN
  • Выделите консоль IAM и найдите Аутентифицированная роль создан при настройке объединенного пула идентификаций Cognito
  • добавить ан Встроенная политика как указано ниже
1*UZPI5CLzl3xdxg6A9IHwLg
введите ARN, скопированный с ресурса API Gateway (в выделенной области)
  • В политике укажите скопированный ARN для ресурса шлюза API.

Аутентифицированные пользователи могут теперь вызвать наши защищенные методы API.

Услуга в службе контроля доступа

Настройка Cognito позволит пользователю вызывать метод API. Но вызов этого метода является триггером для функции лямбды. Функция лямбда выполняется в контексте другой роли IAM. Это больше не прямой запрос пользователя, а взаимодействие AWS с сервисом. Роли IAM обеспечивают контроль доступа для этого взаимодействия.

Claudia.JS создал роль IAM для функции Лямбды. (Вы также можете вручную создать эту роль и указать ее идентификатор для Claudia.JS через файл --role параметр. Детали здесь.)

Если наша функция Lambda нуждается в доступе к другим ресурсам AWS, нам нужно будет обновить роль IAM Lambda и предоставить эти привилегии. Это может быть, к примеру, база данных RDS.

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

Теперь мы можем создать веб-приложение для наших пользователей.

Веб-приложение React

Я собираюсь создать одностраничное веб-приложение React (SPA). Приложение Vue.js или Angular также подойдет. Для клиентской программы есть два важных компонента: AWS Amplify и aws4 модуль.

AWS Amplify обеспечивает простую интеграцию с AWS Cognito. aws4 – популярная библиотека для подписания запросов AWS с помощью подписей запросов AWS версии 4. AWS использовала подписанные запросы на защищенные ресурсы (т.е. запросы авторизованных пользователей).

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

Для аутентификации нам необходимо выполнить некое управление состоянием. В примере приложения не используется ни одна структура, но в реальном приложении я бы предложил Mobx (или Redux.)

В демонстрационном приложении, auth-store.js управляет состоянием аутентификации пользователя. Он состоит из состояния проверки подлинности пользователя и учетных данных. К таким привыкли

  • визуализировать различные компоненты и стили для аутентифицированных и гостевых пользователей
  • подписывать запросы на защищенные методы API

Хотя AWS Amplify управляет большей частью интеграции AWS Cognito, нам нужно поработать.

Определение состояния авторизации с AWS Amplify

Документация AWS Amplify в некоторых областях хорошая, а в других – дефицитная. Я предлагаю прочитать раздел Аутентификация в документации Amplify. Это описываетAuth компонент, взаимодействующий с Cognito.

Однако все еще есть некоторые аспекты, которые документация четко не освещает. AWS Amplify не позволяет легко узнать состояние аутентификации. (Здесь обсуждается эта сложность.) Amplify настраивается асинхронно, без обратного вызова. Но э aws-amplify класс, который может помочь.

The Hub класс в aws-amplify модуль ведет себя как излучатель событий. Нас интересуют два события: configured и cognitoHostedUI.

1*4tvCgp1hgYXycSJleun6rw
загрузка страницы / настройка последовательности

После того, как AWS Amplify настроит файл Auth компонент, он излучает configured событие. После этого наша программа может запросить статус проверки подлинности текущего пользователя. Это полезно, например, когда наша программа загружается.

1*vWN0pVQVoa0qY-jg3HottA
последовательность изменения состояния входа/аутентификации

При использовании программы нам необходимо знать, меняется ли состояние аутентификации. Существует sign-in событие, но это не то событие, которое мы хотим, поскольку наша демонстрационная программа использует OAuth и пользовательский интерфейс Cognito Hosted. The sign-in событие используется на специальном экране входа/регистрации или при использовании встроенного интерфейса Amplify React. Для OAuth Amplify отправляет файл cognitoHostedUI событие после завершения процесса входа OAuth.

Подписание запросов

Текущий пользователь будет иметь учетные данные, изданные AWS Cognito. Они содержат идентификатор доступаа секретный ключи а сеансовый ключ. Эти доступны по телефону Auth.currentCredentials() в aws-amplify. Для методов API, авторизованных IAM, требуется знак запрос с помощью подписей AWS V4. К счастью, aws4 модуль обрабатывает сложности создания этих подписей.

в api-client.js,


import aws4 from "aws4";

const apiHost = process.env.REACT_APP_API_HOST;
const apiKey = process.env.REACT_APP_API_KEY;
const region = process.env.REACT_APP_REGION;

export async function authenticatedCall(authStore) {
  const opts = {
    method: "GET",
    service: "execute-api",
    region: region,
    path: "/latest/require-auth",
    host: apiHost,
    headers: { "x-api-key": apiKey },
    url: `
  };
  const credentials = await authStore.getCredentials();
  const { accessKeyId, secretAccessKey, sessionToken } = credentials;
  const request = aws4.sign(opts, {
    accessKeyId,
    secretAccessKey,
    sessionToken
  });
  delete request.headers.Host;
  const response = await fetch(opts.url, {
    headers: request.headers
  });
  if (response.ok) {
    return await response.json();
  } else return { message: response.statusText };
}

export async function noAuthCall(authStore) {
  const response = await fetch(` {
    headers: { "x-api-key": apiKey }
  });
  return await response.json();
}
view rawapi-client.js hosted with ❤ by GitHub

Демо

Наконец-то мы можем бежать npm start и запустите приложение! Когда мы впервые попадаем в программу, мы являемся гостем (неаутентифицированным пользователем). Вы также можете посетить, чтобы попробовать.

1*5jsOZ6Qsn6xFn9eqZixKDA

Мы можем получить доступ к незащищенным методам.

1*fCm0PGScMXKBMtNzea7QOw
авторизация не нужна

Но если мы попытаемся получить доступ к защищенному ресурсу, это не получится.

1*UEcp7iF8kWvrE8dnjpZ0WQ
не аутентифицировано

Но если мы войдем в систему, мы сможем получить доступ к защищенным ресурсам.

Нажмите Войти и использовать demouser с паролем от demoPASS123.

1*ot3j4-o8OaBiaagTy9hMfg
после входа – кнопки отображают состояние аутентификации

Теперь мы можем нажать кнопку Req. Auth кнопку, чтобы получить доступ к защищенному методу API.

1*kANusN4eyPy0PBufRlD51A

Вау! Нам пришлось настроить несколько сервисов и переварить множество информации. Но теперь у нас есть приложение, которое является моделью для аутентификации микросервисов на AWS.

1*uvDysqC-6VLSBHIEmjrmmw
Giphy

Что теперь?

Подход в этой статье – «всех-ин» на AWS. Это был осознанный выбор, чтобы показать, как разные части AWS сочетаются вместе, чтобы решить общую потребность, а именно аутентификацию. В этой статье есть альтернативы методам, и я очерчу некоторые из них.

А для оставшихся со мной до конца у меня есть прощальные подарки.

Спасибо, что прочли!

Добавить комментарий

Ваш адрес email не будет опубликован.