Модель транспортной безопасности
etcd поддерживает автоматический TLS и аутентификацию по клиентским сертификатам как для связи клиентов с сервером, так и для связи одноранговых узлов (серверов друг с другом внутри кластера). Обратите внимание: по умолчанию etcd не включает аутентификацию на основе RBAC и аутентификацию на транспортном уровне, чтобы упростить начало работы с базой данных. Кроме того, изменение этого значения по умолчанию нарушило бы совместимость проекта, установленную с 2013 года. Кластер etcd без включённых функций безопасности может открыть свои данные любым клиентам.
Для начала подготовьте сертификат CA и подписанную пару ключей для одного участника. Рекомендуется создавать и подписывать новую пару ключей для каждого участника кластера.
Для удобства инструмент cfssl предоставляет простой интерфейс создания сертификатов; пример его использования приведён здесь . В качестве альтернативы воспользуйтесь руководством по созданию самоподписанных пар ключей .
Из-за продолжающейся разработки приведённый ниже список флагов может быть неактуален. Последние доступные флаги можно получить командой etcd --help или в [справке etcd][].
Базовая настройка
etcd принимает несколько относящихся к сертификатам параметров конфигурации в виде флагов командной строки или переменных окружения:
Связь клиента с сервером:
--cert-file=<path>: сертификат, используемый для соединений SSL/TLS с etcd. При заданном параметре advertise-client-urls может использовать схему HTTPS.
--key-file=<path>: ключ сертификата. Должен быть незашифрованным.
--client-cert-auth: если задан, etcd проверяет во всех входящих запросах HTTPS наличие клиентского сертификата, подписанного доверенным CA; запросы без действительного клиентского сертификата завершаются ошибкой. Если включена аутентификация
, сертификат предоставляет учётные данные для имени пользователя из поля Common Name.
--trusted-ca-file=<path>: доверенный центр сертификации.
--auto-tls: использовать автоматически созданные самоподписанные сертификаты для соединений TLS с клиентами.
Связь одноранговых узлов (между серверами / в кластере):
Параметры одноранговых узлов работают так же, как параметры связи клиента с сервером:
--peer-cert-file=<path>: сертификат для соединений SSL/TLS между одноранговыми узлами. Используется как при прослушивании адреса однорангового узла, так и при отправке запросов другим узлам.
--peer-key-file=<path>: ключ сертификата. Должен быть незашифрованным.
--peer-client-cert-auth: если задан, etcd проверяет во всех входящих запросах одноранговых узлов кластера действительные клиентские сертификаты, подписанные указанным CA.
--peer-trusted-ca-file=<path>: доверенный центр сертификации.
--peer-auto-tls: использовать автоматически созданные самоподписанные сертификаты для соединений TLS между одноранговыми узлами.
Если указан сертификат связи клиента с сервером или одноранговых узлов, необходимо также задать ключ. Все эти параметры конфигурации доступны и через переменные окружения ETCD_CA_FILE, ETCD_PEER_CA_FILE и т. д.
Общие параметры:
--cipher-suites: разделённый запятыми список поддерживаемых наборов шифров TLS между сервером и клиентом, а также между одноранговыми узлами (пустой список автоматически заполняется Go).
--tls-min-version=<version> задаёт минимальную версию TLS, поддерживаемую etcd.
--tls-max-version=<version> задаёт максимальную версию TLS, поддерживаемую etcd. Если не задана, используется максимальная версия, поддерживаемая Go.
keyUsage и extendedKeyUsage сертификата TLS
При создании сертификатов X.509 для защиты транспорта etcd
сертификаты должны содержать подходящие поля keyUsage и
extendedKeyUsage в зависимости от своей роли. Для проверки сертификатов
etcd использует библиотеки Go crypto/tls и crypto/x509, которые
контролируют эти варианты использования во время рукопожатия TLS.
В таблице приведены рекомендуемые варианты использования для распространённых ролей сертификатов:
| Роль сертификата | keyUsage | extendedKeyUsage |
|---|---|---|
| Сервер (клиент — сервер) | digitalSignature, keyEncipherment | serverAuth |
| Клиент | digitalSignature, keyEncipherment | clientAuth |
| Одноранговый узел (сервер — сервер) | digitalSignature, keyEncipherment | serverAuth, clientAuth |
Примечания:
- При включённом
--peer-client-cert-authсертификаты одноранговых узлов используются для взаимного TLS между участниками etcd и поэтому требуют какserverAuth, так иclientAuth. - Клиентские сертификаты, используемые с
--client-cert-auth, должны содержатьclientAuth.
Пример 1: транспортная безопасность между клиентом и сервером с HTTPS
Подготовьте сертификат CA (ca.crt) и подписанную пару ключей (server.crt, server.key).
Настроим простую транспортную безопасность HTTPS в etcd по шагам:
etcd должен успешно запуститься; конфигурацию можно проверить, обратившись к etcd по HTTPS:
Команда должна показать успешное рукопожатие. Поскольку используются самоподписанные сертификаты и собственный центр сертификации, CA необходимо передать curl с параметром --cacert. Другой вариант — добавить сертификат CA в системный каталог доверенных сертификатов (обычно /etc/pki/tls/certs или /etc/ssl/certs).
Пользователям OSX 10.9+: curl 7.30.0 в OSX 10.9+ не распознаёт сертификаты, переданные в командной строке.
Вместо этого импортируйте тестовый ca.crt непосредственно в связку ключей либо добавьте curl флаг -k, чтобы игнорировать ошибки.
Для проверки без флага -k выполните open ./tests/fixtures/ca/ca.crt и следуйте указаниям.
После тестирования удалите этот сертификат!
Если известно обходное решение, сообщите о нём.
Пример 2: аутентификация клиента на сервере с клиентскими сертификатами HTTPS
К этому моменту клиент etcd умеет проверять подлинность сервера и обеспечивает транспортную безопасность. Клиентские сертификаты также позволяют предотвратить несанкционированный доступ к etcd.
Клиенты предъявляют серверу свои сертификаты, а сервер проверяет их подпись указанным CA и решает, обслуживать ли запрос.
Потребуются те же файлы, что и в первом примере, а также пара ключей клиента (client.crt, client.key), подписанная тем же центром сертификации.
Теперь отправьте серверу тот же запрос, что и выше:
Сервер должен отклонить запрос:
Для успешного выполнения нужно передать серверу подписанный CA клиентский сертификат:
Вывод должен содержать:
А также ответ сервера:
Укажите наборы шифров, чтобы заблокировать слабые наборы шифров TLS .
Рукопожатие TLS завершается ошибкой, если приветствие клиента запрошено с недопустимыми наборами шифров.
Например:
После этого клиентские запросы должны указывать один из заданных на сервере наборов шифров:
Пример 3: транспортная безопасность и клиентские сертификаты в кластере
etcd поддерживает ту же описанную выше модель для связи одноранговых узлов, то есть для обмена между участниками etcd в кластере.
Предположим, имеется ca.crt и два участника с собственными парами ключей (member1.crt и member1.key, member2.crt и member2.key), подписанными этим CA. Запустим etcd следующим образом:
Участники etcd образуют кластер, а весь обмен между ними шифруется и аутентифицируется клиентскими сертификатами. Вывод etcd покажет, что адреса подключений используют HTTPS.
Пример 4: автоматическая транспортная безопасность с самоподписанными сертификатами
При указании ClientAutoTLS и PeerAutoTLS срок действия автоматически созданных etcd клиентского сертификата и сертификата однорангового узла составляет только 1 год. Срок действия сертификата в годах можно задать флагом –self-signed-cert-validity.
Если требуется шифрование связи без аутентификации, etcd может шифровать сообщения автоматически созданными самоподписанными сертификатами. Это упрощает развёртывание, поскольку управлять сертификатами и ключами вне etcd не требуется.
Настройте etcd на использование самоподписанных сертификатов для клиентских и одноранговых соединений флагами --auto-tls и --peer-auto-tls:
Самоподписанные сертификаты не подтверждают подлинность, поэтому curl вернёт ошибку:
Чтобы отключить проверку цепочки сертификатов, вызовите curl с флагом -k:
Примечания по DNS SRV
Начиная с v3.1.0 (кроме v3.2.9), начальная инициализация через SRV аутентифицирует ServerName по корневому доменному имени из флага --discovery-srv. Для защиты от атак «человек посередине» с сертификатами требуется, чтобы сертификат содержал совпадающее корневое доменное имя в поле Subject Alternative Name (SAN). Например, etcd --discovery-srv=etcd.local аутентифицирует одноранговые узлы и клиентов, только если предоставленные сертификаты содержат корневой домен etcd.local в поле Subject Alternative Name (SAN)
Примечания для прокси etcd
Прокси etcd терминирует TLS своего клиента, если соединение защищено, а для связи с участниками etcd использует собственные ключ и сертификат прокси, заданные в --peer-key-file и --peer-cert-file.
Прокси связывается с участниками etcd как через --advertise-client-urls, так и через --advertise-peer-urls соответствующего участника. Он пересылает клиентские запросы на объявленные клиентские URL участников etcd и синхронизирует исходную конфигурацию кластера через объявленные URL их одноранговых узлов.
Когда для участника etcd включена аутентификация клиентов, администратор должен убедиться, что сертификат однорангового узла из параметра прокси --peer-cert-file действителен для этой аутентификации. При включённой аутентификации одноранговых узлов сертификат прокси также должен быть действителен для неё.
Примечания по аутентификации TLS
Начиная с v3.2.0 , сертификаты TLS перезагружаются при каждом клиентском соединении . Это позволяет заменять истекающие сертификаты без остановки серверов etcd, перезаписывая старые сертификаты новыми. Обновление сертификатов для каждого соединения не должно создавать значительных накладных расходов, однако в будущем его можно улучшить уровнем кэширования. Примеры тестов находятся здесь .
Начиная с v3.2.0
, сервер отклоняет входящие сертификаты одноранговых узлов с неверным IP в SAN
. Если сертификат однорангового узла содержит IP-адреса в поле Subject Alternative Name (SAN), сервер аутентифицирует узел только при совпадении удалённого IP-адреса с одним из них. Это предотвращает присоединение к кластеру неавторизованных конечных точек. Например, CSR однорангового узла B (созданный с cfssl) имеет вид:
при этом фактический IP-адрес узла B равен 10.138.0.2, а не 10.138.0.27. Когда B пытается присоединиться к кластеру, узел A отклоняет его с ошибкой x509: certificate is valid for 10.138.0.27, not 10.138.0.2, поскольку удалённый IP-адрес B не совпадает с адресом в поле Subject Alternative Name (SAN).
Начиная с v3.2.0
, при проверке SAN сервер разрешает TLS DNSNames
. Если сертификат однорангового узла содержит в поле Subject Alternative Name (SAN) только DNS-имена без IP-адресов, сервер аутентифицирует узел лишь тогда, когда прямое разрешение этих DNS-имён (dig b.com) даёт IP, совпадающий с удалённым адресом. Например, CSR однорангового узла B (созданный с cfssl) имеет вид:
при этом удалённый IP-адрес узла B равен 10.138.0.2. Когда B пытается присоединиться к кластеру, узел A разрешает входящее имя b.com, получая список IP-адресов (например, командой dig b.com). Если список не содержит IP 10.138.0.2, A отклоняет B с ошибкой tls: 10.138.0.2 does not match any of DNSNames ["b.com"].
Начиная с v3.2.2
, при совпадении IP сервер принимает соединение без проверки записей DNS
. Если сертификат однорангового узла содержит в поле Subject Alternative Name (SAN) IP-адреса и DNS-имена, а удалённый IP совпадает с одним из адресов, сервер принимает соединение без дальнейшей проверки DNS-имён. Например, CSR однорангового узла B (созданный с cfssl) имеет вид:
при этом удалённый IP-адрес узла B равен 10.138.0.2, а invalid.domain — недопустимое имя узла. Когда B пытается присоединиться к кластеру, узел A успешно аутентифицирует его, поскольку поле Subject Alternative Name (SAN) содержит действительный совпадающий IP-адрес. Подробнее см. issue#8206
.
Начиная с v3.2.5
, сервер поддерживает обратное разрешение шаблонных DNS SAN
. Если сертификат однорангового узла содержит в поле Subject Alternative Name (SAN) только DNS-имена без IP-адресов, сервер сначала выполняет обратное разрешение удалённого IP и получает список соответствующих ему имён (например, командой nslookup IPADDR). Затем соединение принимается, если одно из имён совпадает с DNS-именем сертификата точно или по шаблону. Если совпадений нет, сервер выполняет прямое разрешение каждой записи DNS сертификата (например, разрешает example.default.svc для записи *.example.default.svc) и принимает соединение, только когда среди разрешённых адресов узла есть IP, совпадающий с удалённым IP однорангового узла. Например, CSR узла B (созданный с cfssl) имеет вид:
при этом удалённый IP-адрес узла B равен 10.138.0.2. Когда B пытается присоединиться к кластеру, узел A выполняет обратное разрешение IP 10.138.0.2 и получает список имён узлов. Затем он точно или по шаблону сопоставляет их с DNS-именами в поле Subject Alternative Name (SAN) сертификата B. Если ни обратное, ни прямое разрешение не дало совпадений, возвращается ошибка "tls: "10.138.0.2" does not match any of DNSNames ["*.example.default.svc","*.example.default.svc.cluster.local"]. Подробнее см. issue#8268
.
В v3.3.0
добавлен флаг etcd --peer-cert-allowed-cn
, поддерживающий аутентификацию соединений одноранговых узлов по CN (Common Name)
. Начальная инициализация TLS в Kubernetes включает создание динамических сертификатов для участников etcd и других системных компонентов (например, сервера API, kubelet и т. д.). Отдельные CA для каждого компонента обеспечивают более строгий контроль доступа к кластеру etcd, но часто неудобны. При заданном флаге –peer-cert-allowed-cn узел может присоединиться только с совпадающим общим именем, даже если CA общий. Сопоставление является точным сравнением строки с полем Common Name (CN) сертификата; шаблоны и префиксы не поддерживаются. При фильтрации по имени узла с –peer-cert-allowed-hostname или –client-cert-allowed-hostname используется x509.Certificate.VerifyHostname() из Go, поддерживающий как точные имена, так и шаблонные записи (например, *.example.com). Например, каждый участник кластера из 3 узлов настраивается со следующими CSR (созданными с cfssl):
При заданном --peer-cert-allowed-cn etcd.local аутентифицируются только одноранговые узлы с совпадающими общими именами. Узлы с другими CN в CSR или другим --peer-cert-allowed-cn отклоняются:
Каждый процесс следует запускать с параметром:
В v3.2.19
и v3.3.4
исправлена перезагрузка TLS, когда поле SAN сертификата содержит только IP-адреса без доменных имён
. Например, участник настраивается со следующим CSR (созданным с cfssl):
В Go сервер вызывает (*tls.Config).GetCertificate для перезагрузки TLS тогда и только тогда, когда поле сервера (*tls.Config).Certificates непусто либо (*tls.ClientHelloInfo).ServerName непусто и содержит действительный SNI клиента. Ранее etcd всегда заполнял (*tls.Config).Certificates при первом клиентском рукопожатии TLS, делая поле непустым. Поэтому клиент всегда должен был передавать совпадающий SNI, чтобы пройти проверку TLS и вызвать (*tls.Config).GetCertificate для перезагрузки ресурсов TLS.
Однако сертификат, поле SAN которого не содержит доменных имён, а только IP-адреса
, запрашивает *tls.ClientHelloInfo с пустым полем ServerName, поэтому при первом рукопожатии TLS перезагрузка не запускается. Это становится проблемой при замене истёкших сертификатов без остановки службы.
Теперь при первом клиентском рукопожатии TLS (*tls.Config).Certificates создаётся пустым, чтобы сначала вызвать (*tls.Config).GetCertificate, а затем заполнять остальные сертификаты при каждом новом соединении TLS, даже если SNI клиента пуст (например, сертификат содержит только IP-адреса).
Примечания по белому списку узлов
Флаг etcd --host-whitelist задаёт допустимые имена узлов из клиентских запросов HTTP. Политика происхождения клиента защищает незащищённые серверы etcd от атак “DNS Rebinding”
. Любой веб-сайт может создать разрешённое DNS-имя и направить DNS на "localhost" или любой другой адрес. Тогда все конечные точки HTTP сервера etcd, слушающего "localhost", становятся доступны и уязвимы для атак повторной привязки DNS. Подробнее см. CVE-2018-5702
.
Политика происхождения клиента работает следующим образом:
- Если клиентское соединение защищено HTTPS, разрешаются любые имена узлов.
- Если клиентское соединение не защищено и
"HostWhitelist"не пуст, разрешаются только запросы HTTP, поле Host которых указано в белом списке.
Для более строгого контроля политика происхождения клиента применяется независимо от того, включена ли аутентификация.
По умолчанию etcd --host-whitelist и embed.Config.HostWhitelist пусты, поэтому разрешены все имена узлов. Обратите внимание: при указании имён адреса обратной петли автоматически не добавляются. Чтобы разрешить интерфейсы обратной петли, внесите их в белый список вручную (например, "localhost", "127.0.0.1" и т. д.).
Часто задаваемые вопросы
При клиентской аутентификации TLS появляется ошибка рукопожатия SSLv3 alert handshake failure?
Пакет crypto/tls языка golang проверяет назначение открытого ключа сертификата перед его использованием.
Чтобы применять открытый ключ сертификата для аутентификации клиента, при его создании нужно добавить clientAuth в Extended Key Usage.
Это выполняется следующим образом:
Добавьте в openssl.cnf следующий раздел:
При создании сертификата обязательно укажите его во флаге -extensions:
При аутентификации сертификата однорангового узла появляется “certificate is valid for 127.0.0.1, not $MY_IP”
Убедитесь, что сертификаты подписаны с Subject Name, содержащим общедоступный IP-адрес участника. Например, инструмент etcd-ca предоставляет параметр --ip= для команды new-cert.
Сертификат должен быть подписан для FQDN участника в Subject Name; для добавления IP-адреса используйте Subject Alternative Names (кратко — IP SAN). Инструмент etcd-ca предоставляет параметр --domain= для команды new-cert, а openssl также умеет это
.
Шифрует ли etcd данные, хранящиеся на дисках?
Нет. etcd не шифрует данные ключей и значений, хранящиеся на дисках. Если данные etcd необходимо шифровать, доступны следующие варианты:
- выполнять шифрование и расшифрование в клиентских приложениях
- использовать функцию нижележащей системы хранения для шифрования сохранённых данных, например dm-crypt
В журнале появляется предупреждение “directory X exist without recommended permission -rwx——”
При создании некоторых новых каталогов etcd задаёт права доступа 700, чтобы по возможности предотвратить непривилегированный доступ. Однако если пользователь уже создал каталог с собственными правами, etcd использует существующий каталог и записывает предупреждение, если права отличаются от 700.