Массовое Обновление пользователей AWS Cognito
Введение
AWS Cognito — это мощный безсерверный продукт для управления пользователями. Но ни один продукт или сервис не бывает на 100% завершённым, и, к сожалению, AWS Cognito не является исключением.
Философия Amazon «80%» предполагает, что, достигнув этого порога «готовности», управляемый сервис будет опубликован для ранних пользователей. С этого момента он будет улучшаться на основе отзывов энтузиастов, в основном через GitHub и собственное сообщество AWS re:Post, решая жалобы по одной.
AWS Cognito, безусловно, постоянно претерпевает изменения. Это уже зрелый продукт, но некоторые вещи до сих пор не доведены до совершенства, из-за чего разочарованные разработчики подписываются на длительные обсуждения на GitHub в надежде, что они будут решены. В результате для выполнения некоторых операций всё ещё приходится засучивать рукава и вспоминать навыки работы с командной строкой. Массовое обновление пользователей в AWS Cognito — одна из таких операций.
Проблема
Если вы управляете своими пулами пользователей с помощью AWS Cognito, вы быстро заметите, что этот сервис гораздо менее "гибкий" по сравнению с другими управляемыми сервисами AWS. Некоторые из этих ограничений обусловлены дизайном, например, невозможностью легко мигрировать пользователей из одного пула в другой из-за того, что пароли не хранятся. Однако некоторые из них являются побочным продуктом того, что команда разработчиков не успевает за запросами на новые функции.
Например, нет возможности редактировать атрибуты пользователей в больших объемах. Это касается всех инструментов: AWS CLI, AWS Web Console, AWS CloudFormation, AWS SAM, AWS SDK, AWS CDK и т. д. Если вам нужно изменить большое количество атрибутов пользователей, вам придется немного поэкспериментировать и, возможно, использовать скрипты или функции AWS Lambda для автоматизации процесса.
Решение
Примечание: AWS Cognito не позволяет изменять настройки глобальных атрибутов на уровне пула. То, что мы можем изменить, — это эти атрибуты на уровне пользователя. Если вам нужно изменить глобальные настройки пула пользователей, вам не останется другого выбора, кроме как создать новый пул и реализовать механизм постепенной миграции пользователей, чтобы перенести их из старого пула в новый. Обратитесь к нам, если вам нужна помощь в этом процессе.
Шаг 1: Установка и настройка AWS CLI
Поскольку веб-консоль AWS не позволяет сделать это, мы обратимся к AWS CLI. Следовательно, первым обязательным шагом является установка и правильная настройка этого основного инструмента.
Установка и настройка командной строки AWS выходят за рамки данной статьи, поэтому, если вы еще не настроили её, следуйте официальным инструкциям для выполнения этой задачи. Убедитесь, что вы устанавливаете последнюю версию — на момент написания статьи это версия v2.
Шаг 2: Установите утилиту командной строки jq
Вам также понадобится утилита командной строки jq, которая является самым удобным способом работы с данными в формате JSON в вашей любимой среде оболочки. Подробнее о ней можно узнать на её официальном сайте.
Используя Homebrew, выполните следующую команду:
brew install jq && jq --version
Шаг был выполнен успешно, если в консоли отображается версия пакета, похожая на следующую:
jq-1.7.1
Шаг 3: Составьте и выполните команду
Поскольку мы работаем с AWS Cognito, соответствующая команда CLI будет cognito-idp. Чтобы узнать больше о CLI-интерфейсе этого сервиса, выполните команду:
aws cognito-idp help
При этом вы, как и прежде, убедитесь, что ни одна из команд не позволяет работать с несколькими пользователями одновременно.
Мы будем использовать команду admin-delete-user-attributes для иллюстрации. Тем не менее, вы можете распространить этот подход на другие операции, которые в противном случае разрешены только для одного пользователя. Чтобы узнать больше о специфике этой команды, вы можете выполнить следующую команду:
aws cognito-idp admin-delete-user-attributes help
Первое, что мы хотим сделать, — это получить все имена пользователей из нашего пула.
aws cognito-idp list-users --user-pool-id yourUserPoolID --no-paginate --profile yourCustomAWSProfile
В этом примере мы не фильтруем пользователей, но если вам это необходимо, используйте флаг --filter. Чтобы узнать больше об этом, выполните команду:
aws cognito-idp list-users help
Вы знаете, что делать.
Мы также хотим получить все результаты сразу, без пагинации. Для этого используйте флаг --no-paginate.
Результат выполнения вышеуказанного блока кода вернет JSON-файл, отформатированный примерно так:
{
"Users": [
{
"Username": "some-username-or-uuid",
"Attributes": [
{
"Name": "sub",
"Value": "uuid"
},
{
"Name": "email_verified",
"Value": "true"
},
{
"Name": "custom:yourCustomAttribute",
"Value": "some-value"
},
{
"Name": "email",
"Value": "test@test.com"
}
],
"UserCreateDate": "2024-02-14T00:30:59.508000+08:00",
"UserLastModifiedDate": "2024-02-14T00:31:19.059000+08:00",
"Enabled": true,
"UserStatus": "CONFIRMED"
}
]
}
Содержимое поля Attributes может варьироваться, но структура будет аналогичной.
Теперь нам нужно обработать этот вывод с помощью jq.
Вышеуказанный фрагмент обрабатывает предварительно определённую структуру данных JSON, возвращаемую командой aws cognito-idp list-users. Мы начинаем с корня ., распаковываем атрибут Users, значение которого представляет собой массив [], и, наконец, извлекаем значение атрибута Username для каждого элемента в этом списке. Флаг -r указывает jq, что он должен возвращать значение без начальных и конечных кавычек. Если не использовать этот флаг, кавычки будут рассматриваться как часть значения для поиска на следующем шаге, что приведет к отсутствию результатов. Поэтому этот флаг является здесь необходимым.
Давайте объединим вышеуказанные операции, чтобы получить список чистых имен пользователей, по одному в каждой строке:
aws cognito-idp list-users --user-pool-id YOUR_USER_POOL_ID --no-paginate | jq -r '.Users[].Username'
Символ | передаёт (или "проводит") вывод первой команды как ввод второй команды. Таким образом, результат запроса AWS CLI для Cognito будет обработан утилитой jq.
Теперь давайте итеративно обработаем этот чистый список имён пользователей, чтобы выполнить операции над каждым пользователем по отдельности:
for username in $(aws cognito-idp list-users --user-pool-id yourUserPoolID --no-paginate --profile yourCustomAWSProfile | jq -r '.Users.[].Username'); do SOME VALUABLE WORK HERE; done
Как видите, возможности на этом этапе безграничны. Для завершения примера давайте удалим один из атрибутов. Вот как это можно сделать:
for username in $(aws cognito-idp list-users --user-pool-id yourUserPoolID --no-paginate --profile yourCustomAWSProfile | jq -r '.Users.[].Username'); do aws cognito-idp admin-delete-user-attributes --user-pool-id yourUserPoolID --username $username --user-attribute-names custom:yourCustomUserAttributeToDelete --profile yourCustomAWSProfile; done
Вот и всё, ваш пул пользователей очищен. Почти все операции CRUD на уровне пользователя можно автоматизировать таким образом. Теперь вы готовы к этому.
Заключение
AWS Cognito — это мощное и высоко настраиваемое решение для управления пользователями с возможностью расширения. Оно должно удовлетворять большинство ваших потребностей в аутентификации. Однако некоторые базовые операции, которые вы могли бы ожидать, отсутствуют, либо из-за особенностей дизайна, либо потому что функция всё ещё находится в бэклоге команды разработки, как, например, автоматический редирект после подтверждения регистрации через ссылку. Ну что ж.
Хотя опытные пользователи, вероятно, столкнутся с ограничениями, в большинстве случаев существуют обходные пути, даже если они требуют использования "вторичного решения", как описано выше, где нужно "выбраться" из инструментов AWS и обработать данные через внешний инструмент, а затем "вернуть" их обратно для достижения желаемого эффекта. И, если это утешение, это делает нас всех лучшими инженерами.