Настройка программного доступа к AWS для федеративных удостоверений, защищенных MFA

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

Соревнование

Для доступа к ресурсам AWS из-за пределов VPC обычно требуются какие-то учетные данные AWS. Есть две формы учетных данных для доступа - долгосрочные и краткосрочные ключи. Для создания долгосрочных учетных данных вы используете пользователей IAM. Каждый член команды получает своего собственного пользователя IAM, который затем может использовать для создания этих долгосрочных учетных данных.

Однако моей целью было полностью перевести нашу команду на использование исключительно федеративных удостоверений для всех форм доступа к AWS. Такой подход дает несколько больших преимуществ, подробно описанных в этой главе документации службы IAM. Еще одна проблема, с которой мы столкнулись, заключалась в том, что наш корпоративный портал входа в систему был защищен уровнем MFA.

Примечание. Если у вас нет корпоративного портала для федеративной аутентификации пользователей, взгляните на это сообщение в блоге AWS, чтобы узнать, как его настроить.

Решение

Решение, которое я придумал, состоит из нескольких частей.

  1. Во-первых, мы собираемся использовать среду автоматизации браузера для загрузки и входа на портал. Мы собираемся использовать Selenium, и это поможет нам решить проблему MFA, о которой я упоминал выше.
  2. Затем мы будем использовать прокси MITM для сбора данных сетевого обмена и несколько строк кода для извлечения из него утверждения SAML. По моему опыту, Selenium API совершенно не помог в этом, и использование прокси-сервера MITM было единственным способом зафиксировать обмен SAML AJAX.
  3. Наконец, мы будем использовать класс STS из AWS SDK для аутентификации в качестве федеративного удостоверения по нашему выбору. Шаг аутентификации вернет набор временных учетных данных для доступа, которые мы будем использовать для настройки доступа к CodeCommit с git * утилитой командной строки и доступа к ресурсам AWS из приложения Node.js.

1. Автоматизация входа на корпоративный портал

Реализация этого шага во многом зависит от того, как реализован ваш корпоративный портал входа. Вам нужно будет использовать веб-драйвер Selenium для программного взаимодействия со страницей входа. Вдобавок к этому вам также, вероятно, потребуется реализовать своего рода приглашение командной строки для сбора учетных данных ADFS от пользователя, уведомления его о текущем статусе процесса входа, о том, должны ли они захватить и ввести код OTP или предпринять действия. на любом другом механизме MFA, который вы можете использовать.

2. Настройка прокси, извлечение подтверждения SAML.

Мы будем использовать browsermob-proxy для этого шага, поскольку он поддерживает HTTPS (полный MITM). Он будет работать как отдельный процесс в операционной системе. Настройка этого прокси вначале меня немного расстраивала, и вы можете почувствовать то же самое, поэтому позвольте мне объяснить, как это работает:

  1. Вы создаете в своей системе демон browsermob-proxy. Отдельно от вашего приложения Selenium. Вы выбираете хост и порт для его запуска, однако сам этот демон еще не является прокси-сервером.
  2. Чтобы создать прокси, вы отправляете демону HTTP-запрос POST на маршрут /proxy с параметрами запроса в качестве настроек. Это создает новый прокси для этого демона и делает его доступным на указанном хосте и порту. Две настройки, которые могут оказаться полезными, - это port и httpProxy. Первый позволяет указать порт для создания прокси-сервера, а второй позволяет указать вышестоящий прокси-сервер, что полезно, если ваш корпоративный портал входа скрыт за корпоративным прокси-сервером.

В следующем примере будет создан демон browsermob на порту localhost 9900 и прокси-сервер MITM на порту localhost 27960. Он также проинструктирует ваш новый прокси-сервер отправлять все входящие запросы через proxy.corp.company.com прокси-сервер верхнего уровня, эффективно создавая цепочку прокси.

# start a browsermob daemon
# to install it, follow instructions on it's GitHub homepage
# https://github.com/lightbody/browsermob-proxy/
/usr/bin/browsermob-proxy -port 8080
# create a MITM proxy
curl -X POST localhost:9900/proxy?port=27960&httpProxy=proxy.corp.company.com

После создания прокси-сервера вам нужно будет указать экземпляру браузера использовать его. Если вы используете Chrome, передайте ему следующий переключатель:

--proxy-server localhost:27960

С Selenium это можно сделать с помощью класса ChromeOptions. Подробнее о настройке параметров прокси в Chrome через интерфейс командной строки можно прочитать здесь.

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

# initiate recording by sending a PUT request to browsermob daemon;
# captureContent param will enable recording of POST data;
# number between /proxy and /har is port where MITM proxy is running
curl -X PUT localhost:9900/proxy/27960/har?captureContent=true
# user signs-in to AWS console through corporate sign-in portal...
# ...success!
# run the same exact command to fetch the data recorded so far
curl -X PUT localhost:9900/proxy/27960/har?captureContent=true

Эта команда вернет довольно здоровенный ответ JSON в формате HAR, который вам нужно будет программно перебирать, ища POST-запрос на https://signin.aws.amazon.com/saml. Запрос будет содержать поле с именем SAMLResponse, и данные в этом поле - это то, что нам нужно.

На этом этапе вы также можете выключить прокси-сервер, чтобы предотвратить потенциальную утечку памяти. Это можно сделать, отправив демону запрос DELETE:

curl -X DELETE localhost:9900/proxy/27960

3. Получение и использование временных учетных данных для доступа

Теперь, когда у нас есть утверждение SAML, пора превратить его в пару временных учетных данных для доступа. Как я уже упоминал, мы собираемся использовать класс STS из AWS SDK (подробнее см. assumeRoleWithSAML здесь).

// javascript code
const params = {
    SAMLAssertion: "AssertionYouGotFromHarDump",
    PrincipalArn: "arn:of:saml:provider:for:federated/identity",
    RoleArn: "arn:of:federated:identity:that:fetched/samlAssertion"
}
sts.assumeRoleWithSAML(params, () => ...);

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

// successful response
{
    ...
    Credentials: {
        AccessKeyId: "AAAAAABBBBBBBCC...",
        Expiration: <Date Representation>,       
        SecretAccessKey: "sEcReTaCcEsSkEy...",
        SessionToken: "sEsSiOnToKeN..."
    }
    ...
},

Чтобы использовать их, во-первых, вам нужно убедиться, что вы не указали какие-либо ключи доступа к AWS в переменных среды вашей ОС, оболочки или приложения, включая внедрение переменных среды в ваше приложение из .env файлов.

После проверки вы можете вставить свои недавно полученные учетные данные в ~/.aws/credentials файл, изменив его программно или используя интерфейс командной строки AWS:

# set credentials on the default AWS CLI profile
aws configure set aws_access_key_id AAAAAAAAAA... --profile default
aws configure set aws_secret_access_key bQbGAb... --profile default
aws configure set aws_session_token aaABAaabAA... --profile default

Это обеспечит доступ к AWS для всех приложений или сценариев оболочки, которые используют AWS CLI или AWS SDK, поскольку оба инструмента будут читать из конфигурации, хранящейся в каталоге ~/.aws. Фактически, существует целая резервная система, которой следуют эти инструменты, поэтому я попросил вас сначала убедиться, что вы не указываете какие-либо переменные среды!

Примечание. Вы можете сделать дополнительный шаг и взять на себя другую роль с более ограниченными разрешениями в зависимости от приложения, которому вы пытаетесь предоставить программный доступ. В этом случае вам нужно будет запустить еще один вызов STS, используя уже полученные учетные данные:

const params = {
   AccessKeyId: "...keyYouObtained",
   SecretAccessKey: "...keyYouObtained",
   SessionToken: "...keyYouObtained",
   RoleArn: "arn:of:role:that:you:want/toUse",
   RoleSessionName: "[email protected]"
}
sts.assumeRole(params, ...);

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

Настройка Git для использования временных учетных данных

До сих пор мы могли получить набор временных учетных данных и использовать их в приложениях, работающих в наших локальных средах. Однако, если вы используете CodeCommit, вы также можете обновить конфигурацию Git для работы с временными учетными данными STS. Это позволит вам избежать использования учетных данных SSH или HTTPS, которые по сути являются еще одной формой долгосрочных учетных данных, от которых мы пытаемся избавиться.

Чтобы переключиться на временные учетные данные, отключите все используемые менеджеры учетных данных Git, а затем выполните следующие команды git:

git config --global credential.helper \
    '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true

Примечание. Если вы запускаете эти команды git в Windows, опустите символ «\» с новой строки и используйте двойные кавычки вместо одинарных кавычек для заключения части [! Aws… $ @].

После этого обязательно обновите исходные URL-адреса в каждом локальном репозитории Git, извлеченном из CodeCommit, в формат HTTPS, если вы использовали формат SSH. Кроме того, убедитесь, что вы выполняете одни и те же файлы inpackage.json во всех проектах, которые используют пакеты CodeCommit в качестве зависимостей NPM.

Однако если эти package.json обновления нарушают ваши конвейеры сборки или развертывания в облаке, ознакомьтесь с статьей, которую я написал об использовании временных учетных данных в конвейерах CI / CD в облаке AWS!

Заключение

В зависимости от вашего варианта использования вы можете автоматизировать этот процесс еще больше, чтобы улучшить взаимодействие с разработчиками. Я решил не вдаваться в подробности, так как эта статья на данный момент становится довольно длинной :), но я могу абсолютно представить, как упаковать это приложение Selenium вместе с демоном browsermob и всеми его зависимостями в образ Docker и даже интегрировать его как микросервис в существующие контейнерные приложения.

Переход на краткосрочные учетные данные повышает общую безопасность облачных операций вашей команды. Дополнительным преимуществом использования исключительно федеративных удостоверений для предоставления доступа к AWS является то, что доступ отменяется, как только учетные данные ADFS, привязанные к удостоверению, перестают существовать. Так что, если кто-то уйдет из компании, вы не оставите себе шанса забыть очистить список пользователей IAM и случайно оставить брешь в безопасности вашей инфраструктуры!

Спасибо, что прочитали эту статью! Если вы хотите видеть больше подобного контента в будущем, оставьте лайк и поделитесь этой статьей. До следующего раза!