Настойка TLS-шифрования в Consul на сервере Ubuntu 14.04

Consul – это распределенная, высокодоступная система обнаружения и конфигурирования сервисов. Consul может представить сервисы и ноды в гибком и мощном интерфейсе, который позволяет клиентам всегда иметь актуальный вид инфраструктуры, в которую они входят.

В предыдущем мануале вы узнали, как подготовить Consul к работе в среде производства: создавать конфигурационные файлы для загрузки и скрипты upstart для инициализации сервисов.

Эта конфигурация готова к работе, но недостаточно защищена – она шифруется простыми встроенными ключами, а связь RPC по-прежнему полностью незашифрована. Чтобы решить эту проблему, Consul поддерживает TLS-шифрование, о котором мы поговорим в этом руководстве. Чтобы реализовать его, нужно будет создать центр сертификации, подписать и передать ключи на ноды.

Требования и цели

Предполагается, что вы выполнили предыдущий мануал, Настройка Consul в среде производства на сервере Ubuntu 14.04. Следовательно, у вас есть такие серверы:

Имя хоста IP-адрес Роль
server1.example.com 192.0.2.1 Загрузочный сервер consul
server2.example.com 192.0.2.2 Сервер consul
server3.example.com 192.0.2.3 Сервер consul
agent1.example.com 192.0.2.50 Клиент consul

Для работы мы используем 64-битные серверы Ubuntu 14.04, но любой современный дистрибутив Linux будет работать аналогичным образом.

Все эти серверы используют один домен. Это позволит вам использовать wildcard SSL-сертификат.

В этом мануале вы научитесь создавать ценры сертификации TLS для подписывания сертификатов каждого из серверов. Это позволит компонентам consul проверить подлинность сервера и шифровать трафик. Мы немного модифицируем файлы конфигурации, чтобы ноды могли шифровать трафик.

Создание структуры SSL

Сначала нужно создать базовые файлы и каталоги для хранения ключей.

Все действия нужно выполнять в оболочке root или с привилегиями sudo.

Повторите этот раздел на всех нодах кластера. Создайте каталог ssl в каталоге /etc/consul.d. Здесь будут храниться файлы для шифрования трафика RPC.

mkdir /etc/consul.d/ssl

На сервере, который будет работать как центр сертификации, создайте подкаталог для хранения всех необходимых файлов для подписи сертификатов. Сервером ЦС может стать любая нода, в данном случае мы используем для этого server1.

Создайте на этом сервере подкаталог CA:

mkdir /etc/consul.d/ssl/CA

В нем будут храниться конфиденциальные данные, недоступные для других пользователей. Для этого заблокируйте каталог:

chmod 0700 /etc/consul.d/ssl/CA

Перейдите в этот каталог:

cd /etc/consul.d/ssl/CA

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

Чтобы сделать это, выделите значение 000a:

echo "000a" > serial

Также нужно создать файл, в котором ЦС сможет записывать сертификаты, которые он подписал.

touch certindex

Создание самоподписанного сертификата ЦС

Для начала нужно создать самоподписанный сертификат. Для этого есть команда openssl, которая идет на машинах Ubuntu по умолчанию.

Чтобы создать сертификат, введите:

openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -out ca.cert

  • req: этот аргумент указывает на то, что вам нужен сертификат PKCS#10.
  • -x509: этот аргумент указывает, что вам нужен самоподписанный сертификат, а не запрос сертификата. Это обычно делается для корневых сертификатов ЦС.
  • -newkey rsa:2048: позволяет openssl сгенерировать новый запрос сертификата и закрытый ключ. Передайте ему аргумент, указывающий, что вам нужен 2048-битный ключ RSA.
  • -days 3650: срок действия сертификата. Значение 3650 создаст сертификат, действительный в течение 10 лет.
  • -nodes: указывает, что сгенерированный закрытый ключ не будет зашифрован DES, для которого требуется пароль. Это позволяет избежать этого требования.
  • -out ca.cert: устанавливает имя файла, который будет использоваться для сгенерированного сертификата.

Во время создания сертификата вам будет предложено ввести информацию о хосте. Вы можете заполнить эту форму любой необходимой информацией о сервере:

. . .
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:ConsulCA
Email Address []:admin@example.com

Поле Common Name будет важно в других сертификатах. Тут же можно указать в нем что угодно.

Когда вы закончите, у вас должен быть файл сертификата ca.cert, а также связанный с ним ключ, privkey.pem.

Создание запроса на подпись wildcard сертификата

Теперь, когда у вас есть корневой сертификат ЦС, можно создать запрос на подпись сертификата для клиентских машин.

В данном случае все машины consul – клиентские, включая сервер, на котором вы работаете сейчас. Чтобы не создавать уникальный сертификат для каждой из них, вы можете создать wildcard-сертификат, валидный для нескольких хостов под одним доменом.

Общий формат команды:

openssl req -newkey rsa:1024 -nodes -out consul.csr -keyout consul.key

Она почти не отличается от предыдущей, но пара отличий все же есть:

  • Нет флага -x509: чтобы сгенерировать запрос на подпись сертификата вместо самоподписанного сертификата, он не нужен.
  • -out consul.csr: полученный файл не является самим сертификатом, а только запросом на подпись сертификата.
  • -keyout consul.key: имя ключа, связанного с запросом на подпись сертификата.

Опять же, вам будет предложено указать данные для запроса на подпись сертификата (CSR). Это более важно, чем при создании самоподписанного сертификата CA. Здесь нужно использовать Common Name с wildcard, чтобы сертификат мог считаться действительным для каждого из наших хостов:

. . .
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*.example.com
Email Address []:admin@example.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

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

Создание конфигурационного файла ЦС

Теперь у вас есть самоподписанный сертификат ЦС и запрос на подпись  wildcard-сертификата, который отвечает всем хостам в домене. Прежде чем вы сможете подписать запрос, вам необходимо создать файл конфигурации, который будет контролировать процесс подписи.

Создайте файл myca.conf, который будет содержать информацию о ЦС.

nano /etc/consul.d/ssl/CA/myca.conf

Этот файл использует формат INI, который состоит из разделов. Первый раздел – это ca. Добавьте в него такую строку:

[ ca ]
default_ca = myca

Затем создайте раздел, на который вы только что ссылались. Он будет содержать основную часть конфигурации ЦС.

Укажите, что информация, введенная в запросы, не обязательно должна быть уникальной. Затем укажите расположение всех файлов, которые необходимы для процесса подписи. Затем сообщите openssl, что разместить новые сертификаты нужно в текущем каталоге.

Также нужно выбрать значения по умолчанию, которые будут использоваться, если в командной строке не указано другое. Сделайте подписанные сертификаты действительными в течение 10 лет и настройте алгоритм sha1. Затем укажите другие разделы, предназначенные для определения дополнительной информации:

[ myca ]
unique_subject = no
new_certs_dir = .
certificate = ca.cert
database = certindex
private_key = privkey.pem
serial = serial
default_days = 3650
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions

Теперь давайте сосредоточимся на первом разделе, который используется для определения информации, которая должна быть предоставлена в CSR. Некоторые поля нужно пометить как обязательные, а другие – как опциональные.

[ myca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional

Последний раздел определит расширения x509, которые нужно использовать при подписи.

Во-первых, нужно указать, что подписываемый сертификат не является сертификатом CA. Используйте стандартное значение hash в subjectKeyIdentifier.

В authorityKeyIdentifier установите значение keyid, чтобы скопировать идентификатор из родительского сертификата. Также нужно указать, что ключи могут использоваться в качестве подписи или с протоколом, который шифрует ключи. Расширенное использование ключей может включать аутентификацию сервера и клиента.

[ myca_extensions ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth

В целом файл будет иметь такой вид:

[ ca ]
default_ca = myca
[ myca ]
unique_subject = no
new_certs_dir = .
certificate = ca.cert
database = certindex
private_key = privkey.pem
serial = serial
default_days = 3650
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions
[ myca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional
[ myca_extensions ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth

Сохраните и закройте файл. Теперь у ЦС есть конфигурация, которая позволяет ему подписывать запросы.

Подпись сертификата

Теперь все необходимые компоненты готовы. Вы можете подписать запрос и сгенерировать сертификат. Для этого нужно только сослаться на конфигурационный файл и передать CSR.

openssl ca -batch -config myca.conf -notext -in consul.csr -out consul.cert

  • ca: запускает функцию ЦС.
  • -batch: включает режим batch, который подписывает все поступившие запросы.
  • -config myca.conf: передает конфигурационный файл ЦС.
  • -notext: не выводить текстовую форму сертификата.

Остальные параметры определяют входные и выходные файлы.

Это создаст файл consul.cert в текущем каталоге и новые версии файлов serial и certindex, перемещая старые версии в резервные файлы.

Также у вас появится файл .pem на основе серийного номера из файла serial.

Перемещение файлов

Теперь нужно переместить файлы в правильное расположение. Сейчас они находятся в /etc/consul.d/ssl/CA. Скопируйте их и поместите в /etc/consul.d/ssl.

cp ca.cert consul.key consul.cert ..

На сервере server1, который является ЦС, необходимый сертификат и файлы ключей находятся в правильном месте.

Чтобы добавить их на друге машины в вашей инфраструктуре, используйте scp. Из каталога /etc/consul.d/ssl на server1 вы можете переместить необходимые файлы на другие серверы, набрав:

cd /etc/consul.d/ssl
scp ca.cert consul.key consul.cert root@192.0.2.2:/etc/consul.d/ssl
scp ca.cert consul.key consul.cert root@192.0.2.3:/etc/consul.d/ssl
scp ca.cert consul.key consul.cert root@192.0.2.50:/etc/consul.d/ssl

Укажите IP-адреса своих машин.

Изменение конфигурации Consul

Теперь, когда у вас есть сертификаты и ключи, вы можете изменить конфигурации consul, чтобы сослаться на эти сертификаты.

Откройте каждый из конфигурационных файлов consul на своих серверах. Для сервера server1 начните с файла конфигурации начальной загрузки:

nano /etc/consul.d/bootstrap/config.json
{
"bootstrap": true,
"server": true,
"datacenter": "nyc2",
"data_dir": "/var/consul",
"encrypt": "pmsKacTdVOb4x8/Vtr9PWw==",
"log_level": "INFO",
"enable_syslog": true
}

С помощью параметров consul определите каждый новый файл. Параметр ca_file ссылается на расположение сертификата ЦС. Параметры cert_file и key_file – на сертификат и ключ клиента.

Поместите эти параметры после параметра encrypt:

{
"bootstrap": true,
"server": true,
"datacenter": "nyc2",
"data_dir": "/var/consul",
"encrypt": "pmsKacTdVOb4x8/Vtr9PWw==",
"ca_file": "/etc/consul.d/ssl/ca.cert",
"cert_file": "/etc/consul.d/ssl/consul.cert",
"key_file": "/etc/consul.d/ssl/consul.key",
"log_level": "INFO",
"enable_syslog": true
}

Теперь вы определили расположение этих файлов. Но также consul должен проверить подлинность каждого из хостов, используя эти файлы. Для этого включите проверку входящих и исходящих соединений:

{
"bootstrap": true,
"server": true,
"datacenter": "nyc2",
"data_dir": "/var/consul",
"encrypt": "pmsKacTdVOb4x8/Vtr9PWw==",
"ca_file": "/etc/consul.d/ssl/ca.cert",
"cert_file": "/etc/consul.d/ssl/consul.cert",
"key_file": "/etc/consul.d/ssl/consul.key",
"verify_incoming": true,
"verify_outgoing": true,
"log_level": "INFO",
"enable_syslog": true
}

Сохраните и закройте файл.

Повторите эти действия на всех машинах кластера.

На server1 изменить нужно /etc/consul.d/bootstrap/config.json и /etc/consul.d/server/config.json.

На остальных серверах нужно изменить только /etc/consul.d/server/config.json, а на клиентах — /etc/consul.d/client/config.json.

Перезапуск серверов

Чтобы включить поддержку шифрования, теперь нужно перезапустить кластер.

Каждую машину инфраструктуры нужно остановить и снова запустить:

stop consul && sleep 5 && start consul

Если вы сделаете это на каждой машине consul, они переключатся на использование SSL для шифрования трафика RPC. Когда переключились только некоторые из них, у вас ненадолго могут возникнуть некоторые проблемы связи, поскольку незашифрованный трафика будет сбрасываться.

Когда все участники кластера перезапустятся, трафик RPC должен быть полностью зашифрован.

Tags: , , ,