Etcd: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 264: Строка 264:
 
* ext_key_usage="ClientAuth"
 
* ext_key_usage="ClientAuth"
   
  +
==Создание сертификатов для Client SSL==
=Client SSL=
 
  +
В целом полностью аналогично созданию для peer-to-peer за исключением использования других endpoint естественно
  +
  +
<PRE>
  +
export VAULT_ADDR=http://vault.home:8200
  +
export VAULT_TOKEN=...
  +
domain="etcd.az1.k8s.home"
  +
mkdir -p ./client_crt
  +
vault \
  +
write \
  +
-format=json pki_intermediate_ca/issue/etc-az-k8s-home-server-only-crt \
  +
common_name="${domain}" \
  +
ttl="43800h" > ./client_crt/${domain}.crt.json
  +
</PRE>
  +
<PRE>
  +
mkdir -p ./client_only_crt
  +
vault \
  +
write \
  +
-format=json pki_intermediate_ca/issue/etc-az-k8s-home-client-only-crt \
  +
common_name="${domain}" \
  +
ttl="43800h" > ./client_only_crt/${domain}.crt.json
  +
</PRE>
  +
и аналогично с помощью jq достать сами сертификаты и ключи

Версия 13:00, 23 октября 2021

Etcd

Это часть моего изучения k8s the hard way
но может использоваться и отдельно

Требования

  • 3 ноды raspberry pi установленные и настроенные, имеющие коннективити друг с другом
  • установленный и настроенный PKI на основе Hashicorp Vault (в примере - по адресу http://vault.home)
  • Настроенный DNS и созданы записи для всех доменов в примере (в моем случае DNS поднят на MikroTik)

Установка

  • мне НЕ удалось ни найти ни собрать более свежую версию чем была доступна в пакетах дистрибутива
  • установить на всех трех нодах
apt -y install etcd-server etcd-client etcd
dpkg -l | grep etcd
iU  etcd                           3.2.26+dfsg-3                       all          Transitional package for etcd-client and etcd-server
ii  etcd-client                    3.2.26+dfsg-3                       armhf        highly-available key value store -- client
iF  etcd-server                    3.2.26+dfsg-3                       armhf        highly-available key value store -- daemon
  • TODO: проверить кросс-компиляцию для ARM

Подготовка SSL сертификатов

Согласно документации (https://etcd.io/docs/v3.5/op-guide/security/) etcd сертификаты используются в двух независимых настройках:

  • Коммуникация между нодами кластера
  • Коммуникация между кластером и клиентом

Peer-to-peer SSL

Для того что бы настроить SSL потребуются сертификаты для соответствующих доменов. Так как сертификаты во взаимодействии нод кластера используются как клиентские и как серверные, то нужна соответствующая настройка PLI

настройка PKI для peer-to-peer SSL

  • Нужен клиент Vault
  • В примере используется рутовый токен (нужен ТОЛЬКО для создания "роли", но используется везде в примерах)

Для обновления сертификатов будет добавлен пользователь или другой способ авторизации и права будут ограничены

export VAULT_ADDR=http://vault.home:8200
export VAULT_TOKEN=<some-token-here>


vault write pki_intermediate_ca/roles/etc-az-k8s-home-server-crt \
    country="Ukraine" \
    locality="Kharkov" \
    street_address="Lui Pastera st 322 app. 311"\
    postal_code="61172" \
    organization="Home Network" \
    ou="IT" \
    allowed_domains="etcd1.home,etcd2.home,etcd3.home,etcd.home,etcd.az1.k8s.home,etcd.az2.k8s.home,etcd.az3.k8s.home" \
    allow_subdomains=false \
    max_ttl="87600h" \
    key_bits="2048" \
    key_type="rsa" \
    allow_any_name=false \
    allow_bare_domains=true \
    allow_glob_domain=false \
    allow_ip_sans=true \
    allow_localhost=false \
    client_flag=true \
    server_flag=true \
    enforce_hostnames=true \
    key_usage="DigitalSignature,KeyEncipherment" \
    ext_key_usage="ServerAuth,ClientAuth" \
    require_cn=true

В скрипте выще важно следующее

  • etc-az-k8s-home-server-crt имя роли - по сути произвольная строка которая просто определяет endpoint (используется ниже)
  • allowed_domains="etcd1.home,etcd2.home,etcd3.home,etcd.home,etcd.az1.k8s.home,etcd.az2.k8s.home,etcd.az3.k8s.home" - список доменов для которых можно выписывать сертефикаты используя этот endpoint. В моем случае изначально планировалось использовать домены etcdX.home но так как настройка "а-ля мультизонный кластер" то домер решил изменить

ВАЖНО: Домены пречислять через запятую без пробелов иначе не работает (как минимум в моей версии Vault)

  • allow_subdomains=false - не разрешать создавать сабдомены
  • client_flag=true - сертификат может использоваться как клиентский
  • server_flag=true - сертификат может использоваться как серверный
  • ext_key_usage="ServerAuth,ClientAuth" - расширения


Если попробовать создать только серверный сертификат то возникает ошибка SSL которая в общем-то об этом и говорит и ничего не работает


Создание сертификатов для peer-to-peer

Пример для одного домена, для остальных аналогично


export VAULT_ADDR=http://vault.home:8200
export VAULT_TOKEN=<some-token-here>


domain="etcd.az1.k8s.home"
vault \
    write \
    -format=json pki_intermediate_ca/issue/etc-az-k8s-home-server-crt \
    common_name="${domain}" \
    ttl="43800h" > ${domain}.crt.json
  • issue/etc-az-k8s-home-server-crt - имя роли которое указано на предыдущем шаге
  • используется рутовый токен который имеет все права (но это только для примера что бы пропустить "лишние" шаги)

Полученный файл etcd.az1.k8s.home.crt.json:

{
  "request_id": "0454e996-7bbc-d3ca-8830-cc2d544b2763",
  "lease_id": "",
  "lease_duration": 0,
  "renewable": false,
  "data": {
    "ca_chain": [
      "-----BEGIN CERTIFICATE----- пропущено -----END CERTIFICATE-----"
    ],
    "certificate": "-----BEGIN CERTIFICATE----- пропущено -----END CERTIFICATE-----",
    "expiration": 1792583899,
    "issuing_ca": "-----BEGIN CERTIFICATE----- пропущено -----END CERTIFICATE-----",
    "private_key": "-----BEGIN RSA PRIVATE KEY----- пропущено -----END RSA PRIVATE KEY-----",
    "private_key_type": "rsa",
    "serial_number": "3b:f4:6d:6d:b8:47:38:9f:7b:4d:dc:11:89:d9:63:ff:74:e6:fd:ed"
  },
  "warnings": null
}

Из полученного файла подготовить отдельно файлы сертификатов:

#!/bin/bash

domain="etcd.az1.k8s.home"

mkdir -p /etc/etcd/certs/server

cat \
    ${domain}.crt.json \
    | jq -r '.data.private_key' > /etc/etcd/certs/server/${domain}.key

cat \
    ${domain}.crt.json \
    | jq -r '.data.certificate' > /etc/etcd/certs/server/${domain}.pem

cat \
    ${domain}.crt.json \
    | jq -r '.data.ca_chain[]' >> /etc/etcd/certs/server/${domain}.pem

Обратить внимание: так как сертефикат подписан НЕ корневым а промежуточным центром сертефикации то в файл сертификата требуется добавить промежуточный сертефикат (поле '.data.ca_chain[]' в json)


Тестовый запуск

В целом этого достаточно что бы запустить etcd (но клиентские соединения будут нешифрованными и без авторизации)
Скрипт запуска (на всех трех нодах отличаются домены и адреса):

export ETCD_UNSUPPORTED_ARCH=arm

/usr/bin/etcd \
  --debug \
  --name=etcd-az-1 \
  --listen-peer-urls=https://10.240.1.2:2380 \
  --listen-client-urls=http://10.240.1.2:2379,http://127.0.0.1:2379 \
  --advertise-client-urls=http://etcd.az1.k8s.home:2379 \
  --initial-advertise-peer-urls=https://etcd.az1.k8s.home:2380 \
  --initial-cluster-token=etcd.az1.k8s.home \
  --initial-cluster etcd-az-1=https://etcd.az1.k8s.home:2380,etcd-az-2=https://etcd.az2.k8s.home:2380,etcd-az-3=https://etcd.az3.k8s.home:2380 \
  --initial-cluster-state=new \
  --data-dir=/var/lib/etcd \
  --peer-client-cert-auth \
  --peer-cert-file=/etc/etcd/certs/server/etcd.az1.k8s.home.pem \
  --peer-key-file=/etc/etcd/certs/server/etcd.az1.k8s.home.key \
  --peer-trusted-ca-file=/etc/etcd/certs/rootCA.pem

Запускать на всех трех нодах!

Проверка подключения клиента без SSL

ETCDCTL_API=3 etcdctl --debug --endpoints=http://etcd.az1.k8s.home:2379 member list

Вывод команды разбит на 2 части - дебаг и собственно вывод
из вывода команды видно что все три ноды в кластере

INFO: 2021/10/22 15:50:14 parsed scheme: ""
INFO: 2021/10/22 15:50:14 scheme "" not registered, fallback to default scheme
INFO: 2021/10/22 15:50:14 ccResolverWrapper: sending new addresses to cc: [{etcd.az1.k8s.home:2379 0  <nil>}]
INFO: 2021/10/22 15:50:14 balancerWrapper: got update addr from Notify: [{etcd.az1.k8s.home:2379 <nil>}]
INFO: 2021/10/22 15:50:14 clientv3/balancer: pin "etcd.az1.k8s.home:2379"
INFO: 2021/10/22 15:50:14 balancerWrapper: got update addr from Notify: [{etcd.az1.k8s.home:2379 <nil>}]
b7a875ba8d83c06,  started, etcd-az-3, https://etcd.az3.k8s.home:2380, http://etcd.az3.k8s.home:2379
489c4054ed342d1a, started, etcd-az-2, https://etcd.az2.k8s.home:2380, http://etcd.az2.k8s.home:2379
db4ea93d7a019672, started, etcd-az-1, https://etcd.az1.k8s.home:2380, http://etcd.az1.k8s.home:2379

Client SSL

Следующий шаг - добавить шифрование клиентских соединений
Тут есть путаница - "клиентский-серверный" и "совсем клиентский" сертефикаты

  • "клиентский-серверный" - тот что устанавливается на сервере ETCD для того что бы обеспечить SSL клиентам
  • "совсем клиентский" - тот с которым авторизуются клиенты

настройка PKI для Client SSL

Со стороны ETCD сетрефикаты - "серверные", со стороны клиентов - "клиентские", по тому требуется создать в Vault PKI два дополнительных endpoint


  • Для сертефиката который будет "клиентский-серверный":
vault write pki_intermediate_ca/roles/etc-az-k8s-home-server-only-crt \
    country="Ukraine" \
    locality="Kharkov" \
    street_address="Lui Pastera st 322 app. 311"\
    postal_code="61172" \
    organization="Home Network" \
    ou="IT" \
    allowed_domains="etcd1.home,etcd2.home,etcd3.home,etcd.home,etcd.az1.k8s.home,etcd.az2.k8s.home,etcd.az3.k8s.home" \
    allow_subdomains=false \
    max_ttl="87600h" \
    key_bits="2048" \
    key_type="rsa" \
    allow_any_name=false \
    allow_bare_domains=true \
    allow_glob_domain=false \
    allow_ip_sans=true \
    allow_localhost=false \
    client_flag=false \
    server_flag=true \
    enforce_hostnames=true \
    key_usage="DigitalSignature,KeyEncipherment" \
    ext_key_usage="ServerAuth" \
    require_cn=true

Обратить внимаене что это чисто серверный сертефикат:

  • client_flag=false
  • ext_key_usage="ServerAuth"


"совсем клиентский":

vault write pki_intermediate_ca/roles/etc-az-k8s-home-client-only-crt \
    country="Ukraine" \
    locality="Kharkov" \
    street_address="Lui Pastera st 322 app. 311"\
    postal_code="61172" \
    organization="Home Network" \
    ou="IT" \
    allowed_domains="etcd1.home,etcd2.home,etcd3.home,etcd.home,etcd.az1.k8s.home,etcd.az2.k8s.home,etcd.az3.k8s.home" \
    allow_subdomains=false \
    max_ttl="87600h" \
    key_bits="2048" \
    key_type="rsa" \
    allow_any_name=true \
    allow_bare_domains=false \
    allow_glob_domain=false \
    allow_ip_sans=false \
    allow_localhost=false \
    client_flag=true \
    server_flag=false \
    enforce_hostnames=false \
    key_usage="DigitalSignature" \
    ext_key_usage="ClientAuth" \
    require_cn=true

Тут - только клиентский сертефикат

  • client_flag=true
  • server_flag=false
  • ext_key_usage="ClientAuth"

Создание сертификатов для Client SSL

В целом полностью аналогично созданию для peer-to-peer за исключением использования других endpoint естественно

export VAULT_ADDR=http://vault.home:8200
export VAULT_TOKEN=...
domain="etcd.az1.k8s.home"
mkdir -p ./client_crt
vault \
    write \
    -format=json pki_intermediate_ca/issue/etc-az-k8s-home-server-only-crt \
    common_name="${domain}" \
    ttl="43800h" > ./client_crt/${domain}.crt.json
mkdir -p ./client_only_crt
vault \
    write \
    -format=json pki_intermediate_ca/issue/etc-az-k8s-home-client-only-crt \
    common_name="${domain}" \
    ttl="43800h" > ./client_only_crt/${domain}.crt.json

и аналогично с помощью jq достать сами сертификаты и ключи