Безопасный DevOps. Часть 1 - защита облачной инфраструктуры
https://t.me/w2hackInto
Ценим и применяем рецепты безопасности для облачной среды DevOps взятых их книги "Безопасный DevOps. Эффективная эксплуатация систем" автор Джульен Вехен.

Конфигурируем опции безопасности deployer
На данный момент конвейер предоставляет собой размещаемый в Docker Hub контейнер, который проходит полное тестирование и оказывается готовым для развертывания в среде эксплуатации. Перед развертыванием контейнера вы хотите проверить состояние безопасности инфраструктуры и убедиться в том, что ни одно из внесенных вручную изменений не нарушило мер безопасности. Работа приложения deployer будет состоять в том, чтобы проверять безопасность и по завершении тестов запускать развертывание приложения. На рис. 4.1 отображены четыре шага CD-конвейера.

□ Контейнер приложения отправляется в репозиторий контейнера.
□ Репозиторий контейнера вызывает URL веб-хука, размещенного приложением deployer, чтобы проинформировать: новая версия контейнера приложения готова к развертыванию.
□ Deployer проводит серию тестов над различными частями инфраструктуры.
□ Если тесты проходят успешно, то платформе Elastic Beanstalk приходит указание развернуть новый контейнер приложения на экземпляре ЕС2 в инфраструктуре, что позволит эффективно обновлять среду invoicer до последней версии приложения.
Настройка deployer
Deployer — это небольшое приложение на Go с открытой конечной НТТР-точкой для получения уведомлений веб-хука от Docker Hub. Ему не нужна база данных, только экземпляр ЕС2 и распределитель нагрузки. Запустить эту инфраструктуру в Elastic Beanstalk еще проще, чем invoicer, поэтому мы пропустим установочные шаги. Если вы хотите активизировать собственный экземпляр в тестовой среде, то скрипт create_ebs_env.sh в репозитории deployer автоматизирует создание ЕВ-среды на уровне бесплатного пользования AWS. В листинге 4.1 показано, как запустить этот скрипт.
Листинг 4.1. Автоматизация установки deployer в AWS Elastic Beanstalk
$ ./create_ebs_env.sh
Creating EBS application deployer201608090943 default vpc is vpc-c3a636a4
ElasticBeanTalk application created
API environment e-3eirqeiqqm is being created make_bucket: s3://deployer201608090943/
upload: ./app-version.json to s3://deployer201608090943/app-version.json waiting for environment
Environment is being deployed. Public endpoint is http://deployer-api.mdvsuts2jw.us-east-1.elasticbeanstalk.com
Листинг 4.2. Конечная точка возвращает JSON-документ с информацией о версии
$ curl \
http://deployer-api.mdvsuts2jw.us-east-1.elasticbeanstalk.com/______________ version___
{
“source": "https://github.com/Securing-DevOps/deployer", "version": "20160522.0-ea0ae7b",
"commit": ”ea0ae7blfaabd4e511dl6d75142d97c683d64646",
"build": "https://circleci.com/gh/Securing-DevOps/deployer/"
}
Настройка уведомлений между Docker Hub и deployer
Delpoyer предоставляет одну конечную точку POST /dockerhub, предназначенную для получения уведомлений веб-хука из Docker Hub при появлении новой версии invoicer, готовой к развертыванию. Уведомления веб-хука соответствуют шагу 2 на рис. 4.1. Docker Hub сможет автоматически высылать уведомления deployer, добавив его открытую конечную точку на вкладку Webhoks (Веб-хуки) в репозитории invoicer на hub.docker.com.
При получении уведомления deployer вызывает Docker Hub, чтобы проверить аутентификацию уведомления. Этот вызов предотвращает выполнение процессов развертывания, запрашиваемых вредоносными уведомлениями у сторонних ресурсов. Если Docker Hub распознает уведомление (возвращая HTTP 200 ОК на запрос обратного вызова), то deployer переходит к шагу 3 и выполняет набор скриптов, которые тестируют инфраструктуру.
Тестирование инфраструктуры
Исполнение тестовых скриптов во время развертывания — главная цель deployer. Эти скрипты (листинг 4.3) находятся в папке deploymentTests в репозитории deployer.
Листинг 4.3. Тестовые скрипты, запускаемые deployer
deployer/deploymentTests/
1— 1-echotest.sh
Сейчас у вас только один скрипт в каталоге. Это простой bash-скрипт с командой echo (листинг 4.4), он предназначен для того, чтобы проверить, насколько хорошо функционируют настройки. Мы будем добавлять скрипты по мере продвижения по этой главе.
Листинг 4.4. Написание скрипта echotest
#!/usr/bin/env sh echo This is a test script that should always return successfully
Скрипт echotest выполняется deployer при получении уведомления от Docker Hub. Вы можете проверить это, запустив повторную сборку Circled для invoicer, результатом чего будет отправка контейнера в Docker Hub (шаг У), отправка уведомления deployer (шаг 2), выполнение скрипта и отображение вывода в журналах (шагЗ). Листинг 4.5 показывает образец извлеченного из Elastic Beanstalk журнала, который демонстрирует успешное выполнение.
Листинг 4.5. Образец журнала из deployer, показывающий выполнение скрипта echotest
2016/07/25 03:12:34 Received webhook notification
2016/07/25 03:12:34 Verified notification authenticity
2016/07/25 03:12:34 Executing test /app/deploymentTests/l-echotest.sh
2016/07/25 03:12:34 Test /app/deploymentTests/l-echotest.sh succeeded: This is a test script that should always return successfully
deployer запрограммирован проверять код, возвращаемый скриптом. Если скрипт возвращает нуль, то предполагается, что все прошло успешно. Любое другое значение остановит процесс развертывания. В случае со скриптом echotest команда echo возвращает нуль, что позволяет deployer перейти к шагу 4 и обновить приложение.
Обновление среды invoicer
В предыдущих главах вы использовали консольный инструмент AWS для запуска команды update-environment. Теперь нужно, чтобы эта операция выполнялась самим deployer и внедрялась в код приложения с помощью AWS Go SDK1. В листинге 4.6 показано, как операция update-environment вызывается в исходном коде deployer.
Листинг 4.6. Go-код, который развертывает invoicer в Elastic Beanstalk
Создает API-сессию в той области AWS, func deploy () { в которой размещается Invoicer
svc := elasticbeanstalk.New(
session.New(), -----------------------
Saws.Config{Region: aws.String(’'us-east-l")}>
)
Определяет параметры для указания того, какая среда должна обновиться
params := &elasticbeanstalk.UpdateEnvironmentInput{ ApplicationName: aws.String("invoicer201605211320"), Environmentld: aws.String("e-curu6awket"), VersionLabel: aws.String("invoicer-api"), }
log.Printin("Deploying EBS application:", params)
Функция deploy () вызывается, если все тесты пройдены успешно. Ее исполнение потребует доступа к AWS API, который можно обеспечить для deployer с помощью определения ключа доступа в переменных окружения AWS_ACCESS_KEY и AWS_SECRET_ KEY (в главе 6 мы обсудим другой способ предоставления доступа, при котором не требуется ручное генерирование входных данных).
Этим завершается установка deployer, который автоматизирует CD-конвейер и реализует TDS на уровне инфраструктуры, deployer пока не несет в себе полезных проверок, но вы будете добавлять их по мере внедрения защиты на различные уровни инфраструктуры. Следующий раздел начинается с разговора об ограничении сетевого доступа с помощью групп безопасности AWS.
AWS SDK, доступный по адресу https://aws.amazon.com/sdk-for-go/, позволит реализовать несложное внедрение функциональностей AWS в Go-программы. Подобные библиотеки существуют для Java, Python и большинства распространенных языков.
Ограничение сетевого доступа
В данном разделе мы вернемся к группам безопасности invoicer и убедимся в том, что они ограничивают сетевой доступ так, как требуется.

Рисунок 4.3 напоминает о трехуровневой архитектуре из главы 2 и показывает группы безопасности, которые защищают каждый из уровней. Чтобы усилить сетевую безопасность, нужно отладить группы так, чтобы каждая из них принимала соединения только из предшествующей группы.
□ Распределитель нагрузки должен принимать соединения из всего Интернета на порт 443.
□ Экземпляр ЕС2 с invoicer должен принимать соединения от распределителя нагрузки на порт 80.
□ База данных RDS должна принимать соединения от invoicer на порт 5432.
В традиционной инфраструктуре можно было бы реализовать эти ограничения с помощью правил межсетевого экрана и IP-адреса каждого из серверов. Но мы в облаке, и вы можете заметить, что настройка инфраструктуры обошлась без какого- либо упоминания об IP-адресе. По сути, нам таким очевидным казалось физическое представление инфраструктуры, что мы даже не знаем, сколько виртуальных машин, не говоря уже о физических серверах, вовлечено в обслуживание приложения.
IaaS позволяет размышлять об инфраструктуре и сервисах на уровне, на котором не существует физических ограничений. Вместо установления сетевой политики для invoicer, которая определит правила взаимодействия IP-адресов, мы поднимемся на уровень выше и дадим возможность группам безопасности взаимодействовать между собой.
Группа безопасности — это защищенная область, в которой входящий и исходящий трафик проверяется на наличие разрешения, как в межсетевом экране, только это более гибкое решение. Смысл существования групп безопасности — это управление разграничением доступа между группами безопасности, а не экземплярами IP-адресов.
Группы безопасности позволяют системным администраторам добавлять, удалять и изменять экземпляры из инфраструктуры, оставляя неизменными правила в группах безопасности. Физическое воплощение инфраструктуры не влияет на политику безопасности, и это заметное улучшение, по сравнению с традиционным межсетевым экраном, который крепко привязан к сетевой адресации инфраструктуры.
Теоретически количество компонентов, содержащихся в группе безопасности, не ограничено. Один компонент, например экземпляр ЕС2, может принадлежать к одной или нескольким группам безопасности.
Тестирование групп безопасности
Перед тем как перейти к реализации, поговорим о тестировании. Высокоуровневый взгляд на сетевую политику для трех групп безопасности invoicer показан на рис. 4.3. Чтобы протестировать эту политику, вам нужен инструмент, который сравнивает содержание групп безопасности с отдельно хранящимся справочным документом, pineapple — это средство проверки сетевой политики, написанное на Go, которое предоставляет основные функции для этой оценки. Его можно найти на https:// github.com/jvehent/pineapple, установить его вы можете с помощью команды go get (листинг 4.7).
Листинг 4.7. Установка pineapple на локальную машину
$ go get github.com/jvehent/pineapple
$ $GOPATH/bin/pineapple -V 20160808.0-8d430b0
pineapple проверяет реализацию сетевой политики в AWS. Если преобразовать сетевую политику, представленную на рис. 4.3, в YAML-синтаксис pineapple, то вы сможете проверить ее реализацию. В листинге 4.8 показан раздел правил с конфигурацией, которая описывает сетевую политику invoicer.

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

И, как обычно, целью является выполнение тестов deployer. Для того чтобы этого добиться, добавьте новый скрипт к тестам развертывания, который вызывает pineapple с конфигурацией, раскрытой в листинге 4.9. Назовите файл securitygroups.sh и внесите в него содержание листинга 4.10. Также убедитесь в том, что указанные регион AWS и номер аккаунта соответствуют данным вашего аккаунта, как упоминается в README-файле pineapple.
Листинг 4.10. deployer запускает pineapple, чтобы протестировать группы безопасности
#!/bin/bash
go get -u github.com/jvehent/pineapple $GOPATH/bin/pineapple -c /app/invoicer_sg_tests.yaml
Отправьте этот тест в инфраструктуру среды эксплуатации и запустите сборку invoicer. Журналы deployer, демонстрирующие итоги работы pineapple, показаны в листинге 4.11.
Листинг 4.11. Результаты теста, показывающие неудачное прохождение проверки на соответствие правилу базы данных
2016/08/15 01:15 building map of security groups for all 3 components
2016/08/15 01:15 "awseb-e-c-AWSEBLoa-lVXVTQLSGGMG5" matches tags elasticbeanstalk environment-name:invoicer-api
2016/08/15 01:15 "i-7bdad5fc" matches tags elasticbeanstalk:environmentname: invoicer-api
2016/08/15 01:15 "arn:aws:rds:us-east-l:9:db:invoicer201605211320" matches tags environment-name:invoicer-api
2016/08/15 01:15 rule 0 between ”0.0.0.0/0" and "load-balancer" was found 2016/08/15 01:15 rule 1 between "load-balancer" and "application" was found 2016/08/15 01:15 FAILURE: rule 2 between "application" and "database" was NOT found
Тест провален, как и ожидалось, так как правил взаимодействия между приложением и базой данных не было найдено. Как говорилось в главе 2, мы открыли группу безопасности всему Интернету, вместо того чтобы сделать это только для ЕС2-экземпляров invoicer. Это и вызвало неудачу, и вы должны настроить группу безопасности базы данных так, чтобы она соответствовала вашей сетевой политике.
Налаживание доступа между группами безопасности
Чтобы изменить политику предоставления доступа к группе безопасности базы данных, необходимо знать идентификаторы групп безопасности (SGID) экземпляров ЕС2 базы данных и приложения invoicer. SGID базы данных можно получить с помощью вызова describe-db-instances из консольного инструмента AWS, в результате чего вернется JSON-документ, который вы парсите с помощью jq (листинг 4.12).
Листинг 4.12. Получение SGID у RDS базы данных с помощью консольного инструмента AWS
$ aws rds describe-db-instances --db-instance-identifier invoicer201605211320 | jq -r '.DBInstances[0],VpcSecurityGroups[0].VpcSecurityGroupId'
sg-35ca6d4e
Получить SGID экземпляра EC2 приложения invoicer немного сложнее, так как информация хранится в недрах Elastic Beanstalk. Сначала нужно получить ID для ЕВ-среды, затем ID экземпляра и, наконец, SGID. В листинге 4.13 показаны все три операции.
Листинг 4.13. Получение SGID экземпляра через Elastic Beanstalk
$ aws elasticbeanstalk describe-environments \ --environment-names invoicer-api | \ jq -r ' .Environments[0].Environments’ e-curu6awket
$ aws elasticbeanstalk describe-environment-resources \ --environment-id e-curu6awket | \
jq -г '.EnvironmentResources.Instances[0J.Id' i-7bdad5fc
$ aws ec2 describe-instances --instance-ids i-7bdad5fc | \ jq -r '.Reservations[0].lnstances[0].SecurityGroups[0].Groupld' sg-6ec86fl5
Эти команды передают информацию, необходимую для обновления группы безопасности: вам нужно позволить SGID sg-6ec86fl5 соединиться с PostgreSQL SGID sg-35ca6d4e через порт 5432. Операция осуществляется следующим образом (листинг 4.14).

Вам также следует избавиться от уже ненужного правила, которое открывало всем доступ к базе данных (листинг 4.15).
Листинг 4.15. Удаление правила RDS, которое разрешало всем соединяться с базой данных

Эти две команды формируют вашу политику безопасности в соответствии с ранее описанными тестами. Теперь вы можете заново выполнить сборку invoicer и проверить, что правило 2 успешно исполняется (листинг 4.16).
Листинг 4.16. Результаты тестов теперь демонстрируют соответствие политике pineapple
2016/08/15 01:43 rule 0 between "0.0.0.0/0" and "load-balancer" was found 2016/08/15 01:43 rule 1 between "load-balancer” and "application" was found 2016/08/15 01:43 rule 2 between "application" and "database" was found
Крайне важно регулярно тестировать сетевую политику — или только во время развертывания, или с определенной периодичностью, — чтобы поддерживать целостность инфраструктуры. Со временем правила меняются, и в отсутствие регулярных проверок в вашей инфраструктуре станет появляться все больше временных прав доступа, которые не были удалены.
По сравнению с управлением межсетевыми экранами, основанным на IP, метки и группы безопасности обеспечивают большую гибкость и помогают строго контролировать сетевую фильтрацию. Однако таким образом вы полностью лишите доступа к базе данных разработчиков и специалистов по эксплуатации, которым иногда нужно просмотреть данные и исследовать проблемы. В следующем разделе мы обсудим, как заново открыть им доступ через SSH-хост-бастион, который позволяет внедрять многофакторную аутентификацию.
Создание безопасной точки доступа (Бастион)
По ряду причин специалистам по эксплуатации все равно необходим непосредственный доступ к системам: для выявления неисправностей, реагирования на инциденты, извлечения журналов, которые могут быть нецентра- лизованы, настройки параметров перед добавлением их в логику автоматизации и т. д. Сколько бы улучшений ни привносила автоматизация инфраструктуры, все равно будет что-то, что потребует непосредственного доступа к системам и базам данных. Автоматизация освобождает системных администраторов от обыденных задач и позволяет им браться за более сложные вызовы для совершенствования инфраструктуры.
Создание точек доступа — хостов-бастионов — обеспечивает несколько преимуществ.
□ Дополнительную защиту, такую как двухфакторная аутентификация (2FA или MFA), нужно настраивать только на бастионе.
□ Так как все соединения должны проходить через бастион, появляется возможность собрать журнал доступа для отслеживания запросов на доступ к инфраструктуре и уведомлять специалистов по эксплуатации о подозрительных запросах.
□ Интерфейсы администратора могут быть скрыты от общедоступного Интернета, и получить их можно будет, только проходя через бастион.
Бастион не является непосредственной частью сервиса, который он защищает. На самом деле большим инфраструктурам свойственно иметь только пару хостов- бастионов, распределенных на все сервисы. Расположение бастиона в инфраструктуре invoicer показано на рис. 4.4.

В этом разделе мы обсудим внедрение SSH-бастиона в инфраструктуру invoicer в соответствии со следующей схемой.
□ Генерирование пары ключей SSH для использования с новым экземпляром ЕС2. Эта пара ключей нужна вам в первую очередь, потому что AWS автоматически назначит ключ для созданного вами экземпляра ЕС2.
□ Настройка многофакторной аутентификации на SSH-сервисе бастиона с помощью Duo Security — стороннего вендора, специализирующегося на предоставлении сервисов аутентификации.
□ Оценка и улучшение конфигурации SSH-сервиса с помощью инструмента оценки для обеспечения повышенного уровня безопасности.
□ И наконец, настройка взаимодействия групп безопасности между бастионом, серверами и базой данных, а также проверка групп безопасности с помощью pineapple.
Генерирование SSH-ключей
Первая версия SSH-протокола была разработана Тату Улёненом из университета Хельсинки в середине 1990-х годов. Улёнен владел SSH на правах частной собственности, поэтому в конце 1990-х в проекте OpenBSD была разработана общедоступная его версия OpenSSH, которая и по сей день используется повсюду. OpenSSH был создан с применением подхода изначальной защищенности и поддерживал безопасность миллионов серверов на протяжении почти двух десятилетий.
Стандартные возможности SSH были довольно хороши, и администраторы редко их модифицировали. Но все же осторожному администратору стоит предпочесть криптографию на уровне выше среднего, чтобы обезопасить доступ к важным узлам. Одним из наиболее важных аспектов безопасного использования SSH было генерирование надежных ключей и их безопасное хранение. В Mozilla опубликовали следующее руководство генерированием SSH-ключей (http://mng.bz/ aRZX) (листинг 4.17).
Команда создает новую пару файлов с закрытым ключом, размещенным по адресу . ssh/id_rsa_sam_2018-02-31, и открытым ключом в файле с расширением . pub.
Листинг 4.17. Генерирование пары SSH-ключей с помощью RSA-алгоритма
$ ssh-keygen -t rsa \
-f ~/.ssh/id_rsa_$(whoami)_$(date +%Y-%m-%d) \
-C ”$(whoami)'s bastion key"
Generating public/private rsa key pair. (Всегда пользуйтесь кодовой фразой)
Enter passphrase (empty for no passphrase): I_____________ |
Enter same passphrase again:
Your identification has been saved in ~/.ssh/id_rsa_sam_2018-02-31. Your public key has been saved in ~/.ssh/id_rsa_sam_2018-02-31.pub.
Алгоритмы SSH-ключей
Если вы вдобавок работаете с современными SSH-системами, то попробуйте использовать алгоритм ed25519 вместо RSA. Ключи в ed25519 намного меньше, чем в RSA, и они обеспечивают равноценный, если не лучший уровень защиты. К сожалению, большинство SSH-клиентов и серверов сейчас поддерживают только ключи RSA.
Чтобы пользоваться этим открытым ключом, загрузите его в AWS. Команда в листинге 4.18 загружает ключ, но еще не привязывает его к какому-либо экземпляру. Последний шаг вы сделаете, создавая новый экземпляр.
Листинг 4.18. Импорт открытых ключей из RSA в AWS
$ aws ес2 import-key-pair --key-name sam-rsa-20180231 --public-key-material "$(cat .ssh/id_rsa_sam_2018-02-31.pub)’’
{
"KeyFingerprint": "be:d0:f0:lf:a7:4a:7d:2f:dl:f9:24:51:70:75:f7:57", "KeyName": '’sam-rsa-20180231'’
}
Распределение открытых SSH-ключей может оказаться непростой задачей. AWS предоставляет базовый механизм включения открытого ключа в процесс создания экземпляров, но его недостаточно, чтобы обеспечить потребности большой команды. Распространенной ошибкой становится распределение одного SSH-ключа на всю команду специалистов по эксплуатации: из-за этого увеличивается риск утечки закрытого ключа и мы лишаемся полезной информации об аутентификации, получаемой при наличии отдельного ключа у каждого из специалистов.
Правильным подходом будет предоставить экземплярам открытые SSH-ключи в качестве одного из элементов процесса сборки экземпляра обычно с применением таких инструментов, как Puppet, Chef или Ansible. Некоторые предпочитают делать предварительную сборку пользователей и паролей в образе экземпляра (называемую Amazon Machine Image, AMI), что также прекрасно подойдет, если вы имеете возможность регулярно обновлять образ новыми версиями ключей.
В больших организациях поддержка множества открытых ключей пользователей требует участия разработчиков. Лично мне нравится хранить ключи в LDAP и позволять пользователям обслуживать их. Таким образом, инструментам понадобится только получить их из LDAP и поместить в экземпляры. Вы также можете воспользоваться GitHub, чтобы получить нечто подобное. Смысл здесь в том, чтобы убеждаться в регулярной повторной синхронизации открытых ключей на серверах с источником истинного ключа.
Создание хоста-бастиона в ЕС2
В этом разделе нам нужен лишь один экземпляр, но это не вписывается в данную модель, поэтому создайте его сами с помощью ряда команд awsutil.
1. Создайте группу безопасности, которая будет охватывать бастион и предоставит открытый доступ к порту ТСР/22.
2. Создайте экземпляр Ubuntu с открытым IP и SSH-ключом, который вы загрузили ранее.
3. Создав их, вы сможете присоединяться к экземпляру и создать на нем пользователя.
Команды для создания групп безопасности к этому моменту должны казаться знакомыми. В листинге 4.19 показаны две команды, которые формируют группу и открывают к ней SSH-доступ.
Листинг 4.19. Создание группы безопасности для хосга-бастиона
$ aws ес2 create-security-group \ --group-name invoicer-bastion-sg \
--description "Invoicer bastion host"
{
"Groupld": "sg-f14ff48b"
}
$ aws ec2 authorize-security-group-ingress \
--group-name invoicer-bastion-sg \
--protocol tcp \
--port 22 \
--cidr 0.0.0,0/0
Теперь, имея группу безопасности, можно с легкостью создать экземпляр ЕС2 с помощью одной команды, показанной в листинге 4,20, Для команды понадобится параметр image-id, указывающий тип системы, на котором основан образ. В этом примере используйте Ubuntu 16.04 LTS, значение image-id для которого будет ami-81365496. Список AMI на Ubuntu, отсортированных по AWS-региону, можно найти по адресу https://cloud-images.ubuntu.com/locator/ec2.

Листинг 4.21. SSH-соединение с хостом-бастионом
$ ssh -i .ssh/id_rsa_sam_2018-02-31 ubuntu@52.91.225.2 ubuntu@ip-172-31-35-82:~$
При обычной установке вы хотели бы убрать пользователя Ubuntu и создать по Unix-пользователю на каждого из системных администраторов. В листинге 4.22 создается пользователь sam и настраивается файл authorized_keys, чтобы обеспечить SSH-доступ. Как упоминалось ранее, вы наверняка захотите автоматизировать этот процесс с помощью конфигурационных инструментов, таких как Puppet, Chef или Ansible.

Следующим этапом будет настройка двухфакторной аутентификации на SSH- сервере с помощью Duo Security. Когда двухфакторная аутентификация (2FA) будет настроена, мы вернемся к правилам в группах безопасности invoicer, чтобы ограничить сетевой доступ.
Защита от перехвата SSH-агента
SSH-агент — это самый полезный и опасный инструмент в SSH-инвентаре администраторов — резидентная программа, которая работает на локальной машине SSH- клиента и содержит дешифрованные закрытые ключи. Без SSH-агента пользователям придется вводить выражения закрытых ключей каждый раз, когда они запрашивают соединение с удаленным сервером, что очень скоро начинает утомлять. С помощью команды ssh-add пользователи однажды раскрывают свои ключи, загружают их в память агента и пользуются ими, пока он существует. Можно указать внешний параметр -t, чтобы обозначить определенный период их действия (листинг 4.37).
Листинг 4.37. ssh-add дешифрует и загружает закрытые ключи в SSH-агент на шесть часов
$ ssh-add -t 1800 ~/.ssh/id_rsa_sam_2018-02-31
Основное назначение агента — отправка данных для входа в систему по сети. Представьте, что вы хотите войти в приложение invoicer через бастион с помощью ssh. Сначала вам потребуется выполнить ssh-вход в бастион, а затем другое SSH- соединение с invoicer. Для второго соединения понадобится пара ключей, которой не существует в бастионе, но которая хранится на вашей локальной машине. Вы могли бы скопировать закрытый ключ в бастион, но это огромный риск для безопасности. Перенаправление данных SSH-агентом (рис. 4.9) решает проблему, что позволяет провести второе соединение по туннелю через первое соединение и запросить аутентификацию из агента на машине пользователя.

Форвардинг SSH-агента — это мощная техника, популярная у администраторов, но немногие знают о скрытой в ней угрозе безопасности: при форвардинге агента аутентификационные данные пользователя становятся открытыми для всех, кто имеет доступ к агенту. В итоге тот, кто обладает корневым доступом к хосту-бастиону, может получить доступ к агенту пользователя. Так происходит из-за того, что агент создает Unix-сокет в бастионе, который позволяет последующим SSH-соединениям сообщаться с машиной пользователя. Unix-сокет хранится в переменной окружения SSH_AUTH_SOCK и доступен только пользователю (листинг 4.38), но, имея корневой доступ, можно достать идентификационные данные пользователя и получить доступ к сокету.
Листинг 4.38. Расположение и права доступа сокета SSH-агента в бастионе
$ echo $SSH_AUTH_SOCK /tmp/ssh-aUoLbn8rF9/agent.15266
$ Is -al /tmp/ssh-aU0Lbn8rF9/agent.15266 srwxrwxr-x 1 sam sam 0 Sep 3 14:44 /tmp/ssh-aUoLbn8rF9/agent.15266
В таком случае стоит быть осторожнее с применением этого агента: используйте его лишь при необходимости и на надежных инструментах. На практике это означает отключение агента по умолчанию и либо использование параметра -А в командной строке при соединении с сервером, либо включение его на отдельных узлах. В листинге 4.39 показана конфигурация, которая включает агент только для хоста-бастиона.

Лучший вариант — Proxyjump
Если вы применяете современную версию OpenSSH (начиная с версии 7.3), то Proxylump предоставит безопасную альтернативу форвардингу SSH-агента. Вы можете пользоваться Proxy lump из командной строки с помощью флага -1:
$ ssh -1 bastion.securing-devops.com target-server.securing-devops.com
Также можете определить конфигурационный файл, который автоматически использует Proxylump для любого узла под доменом securing-devops.com, следующим образом:
Host *.securing-devops.com
Proxylump bastion.securing-devops.com
Поскольку Proxy lump не раскрывает сокет для промежуточных узлов, он не подвержен тем же уязвимостям, что и SSH-агент. Отдайте ему предпочтение, если ваша инфраструктура поддерживает современный SSH.
На этом мы завершаем обзор SSH-защиты. Ваш бастион теперь имеет наилучшую конфигурацию и готов стать входной точкой для инфраструктуры. В следующем разделе вернемся к управлению сетевым доступом для предотвращения прямого доступа к инфраструктуре invoicer и направления всего трафика через бастион.
Продолжение следует! Берегите себя, своих близких и свои данные! Следите за обновлениями на канале w2hack