Vault PKI Intermediate CAs for ALL SERVICES Kubernetes the hard way v2: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 98: | Строка 98: | ||
* <code>--tls-cert-file</code> |
* <code>--tls-cert-file</code> |
||
* <code>--tls-private-key-file</code> |
* <code>--tls-private-key-file</code> |
||
− | Этот сертификат выпускается |
+ | Этот сертификат выпускается <code>k8s_pki_intermediate_ca_for_service_kube_apiserver_tls/<code> |
==<code>kube-controller-manager</code> TLS CA== |
==<code>kube-controller-manager</code> TLS CA== |
Версия 11:52, 15 ноября 2022
Эта страница - часть большой статьи про CA используемые в k8s: Vault_PKI_Kubernetes_the_hard_way_v2
Некоторые термины
CA
: certificate authority или certification authority ( на русском это звучит как Центр Сертефикации)
В контексте документа может иметь несколько возможных значений - как собственно центр выпуска сертификатов, так и сам корневой (или промежуточный сертификат) этого центра. По сути, сертификат СА, который используется для подписания клиентских и серверных сертификатом не только не является секретным, но наоборот должен быть доступен для доступа так как именно он используется для проверки валидности выпущенных сертификатов
В случае с PKI на основе Vault
СA доступны для скачивания без авторизации.
Есть 2 типа сертификатов (конечно их больше но в K8s используется 2 типа). Потому в целом (кроме etcd
) есть разделение СА в том числе и по типу выпускаемых сертификатов
client_auth
- этот суффикс у СА используется в значении "сертификаты используются для авторизации" (другими словами - не используются для организацииhttp
)tls
- этот суффикс у СА используется в значении "сертификаты используются для организацииhttps/TLS
"
Создание СА для работы кластера K8s
K8s
использует СА для выписывания сертификатов 2 типов
- "Обычные" серверные сертификаты (
CN = domain
) - Сертификаты используемые для авторизации - клиентские (
CN=username
,O=groupname
)
Всего в Vault настроены такие СА:
k8s_pki_intermediate_ca_for_service_etcd/ pki pki_13a87e77 PKI Intermediate CA for ETCd service k8s_pki_intermediate_ca_for_service_kube_apiserver_client_auth/ pki pki_622072da PKI Intermediate CA for K8S: kube-apiserver CLIENT_AUTH k8s_pki_intermediate_ca_for_service_kube_apiserver_tls/ pki pki_d8737474 PKI Intermediate CA for K8S: kube-apiserver TLS k8s_pki_intermediate_ca_for_service_kube_controller_manager_tls/ pki pki_34a63553 PKI Intermediate CA for K8S: kube-controller-manager TLS k8s_pki_intermediate_ca_for_service_kube_scheduler_tls/ pki pki_5b5f53f5 PKI Intermediate CA for K8S: kube-scheduler TLS k8s_pki_intermediate_ca_for_service_kubelet_client_auth/ pki pki_4f1df8fd PKI Intermediate CA for K8S: kubelet CLIENT_AUTH k8s_pki_intermediate_ca_for_service_kubelet_tls/ pki pki_47e7182a PKI Intermediate CA for K8S: kubelet TLS k8s_pki_root_ca/ pki pki_8b6cae1e PKI k8s Root CA
Полный список СА
(промежуточных СА!)
Всего существует 8 СА которые используются в этой инсталляции (один из них - корневой СА).
Если верить документации, то это не предел - каждый файл с CA в настройках сервисов может содержать
более одного сертификата, другими словами 2 процесса kube-apiserver
вполне могут использовать разные CA
В частных случаях можно упростить настройку, и вообще использовать 1 СА
Эта инсталляция подразумевает настойку PKI средней сложности, что бы не переусложнять.
k8s_pki_intermediate_ca_for_service_etcd/
k8s_pki_intermediate_ca_for_service_etcd/
- используется для клиентских и серверных сертификатов etcd
. Строго говоря, не является частью k8s и настраивается отдельно (Настройка PKI для etcd
)
- для шифрования endpoints
- для авторизации клиентов
k8s_pki_intermediate_ca_for_service_kube_apiserver_client_auth/
k8s_pki_intermediate_ca_for_service_kube_apiserver_tls/
k8s_pki_intermediate_ca_for_service_kube_apiserver_client_auth/
- используется для клиентских сертефикатовkube-apiserver
, по которым API проверяет права пользователей.k8s_pki_intermediate_ca_for_service_kube_apiserver_tls/
Используется для обеспечения https при подключении кkube-apiserver
. При этом происходит двухсторонняя проверка- Все клиенты (как сервисы, часть k8s, например kube-controller-manager, kube-scheduler так и kubectl для администрирования) должны обладать CA (который как и прочие СА не является секретным), для того что бы иметь возможность проверить кластер, другими словами быть уверенным в том что подключаются туда куда ожидают.
- Все клиенты (как сервисы, часть k8s, например kube-controller-manager, kube-scheduler так и kubectl для администрирования) должны обладать CA (который как и прочие СА не является секретным), для того что бы иметь возможность проверить кластер, другими словами быть уверенным в том что подключаются туда куда ожидают.
Часть kubeconfig
отвечающая за этот сертификат:
clusters: - cluster: certificate-authority: /etc/k8s/shared/certs/CA/k8s_pki_intermediate_ca_for_service_kube_apiserver_tls.pem server: https://kube-apiserver.k8s.cluster.home:443
- Со своей стороны сервер проверяет как то что сертефикат клиента подписан правильным СА (
k8s_pki_intermediate_ca_for_service_kube_apiserver_client_auth/
), так и поляCN
O
в сертификате, которые используются как имя пользователя и группа. Имена групп выбраны не случайно - для них уже есть (или можно создать свои!)ClusterRoleBindings
- Со своей стороны сервер проверяет как то что сертефикат клиента подписан правильным СА (
k8s_pki_intermediate_ca_for_service_kube_controller_manager_tls/
k8s_pki_intermediate_ca_for_service_kube_controller_manager_tls/
- используется для обеспечения https, серверные сетефикаты
k8s_pki_intermediate_ca_for_service_kube_scheduler_tls/
k8s_pki_intermediate_ca_for_service_kube_scheduler_tls/
- используется для обеспечения https, серверные сетефикаты
k8s_pki_intermediate_ca_for_service_kubelet_client_auth/
k8s_pki_intermediate_ca_for_service_kubelet_tls/
k8s_pki_intermediate_ca_for_service_kubelet_client_auth/
kubelet в целом устроен аналогично kube-api серверу, и использует 2 СА - один для авторизации клиентов (в случае с kubelet клиентом выступает kube-apiserver), а второй используется для обеспечения https- У
kube-apiserver
есть настройка--kubelet-certificate-authority
- это файлс СА дляk8s_pki_intermediate_ca_for_service_kubelet_tls/
, таким образомkube-apiserver
может точно знать что он обращается к нужномуkubelet
, так как его серверный сертефикат подписан этим СА --kubelet-client-certificate
--kubelet-client-key
содрежат сертификат, выписанный помощью САk8s_pki_intermediate_ca_for_service_kubelet_client_auth/
и содержат имя пользователя и группу с которымиkube-apiserver авторизуется
уkubelet
- У
Например: O = system:masters
, OU = system
, CN = kube-apiserver-to-kubelet
При этом по-умолчанию соответствующие ClustetRoleBinding
отсутствуют, и перед подключением kubele
их требуется создать дополнительно. (эта часть настройки выполняется при конфигурировании kube-apiserver
k8s_pki_intermediate_ca_for_service_kubelet_tls/
- используется для обеспечения https, серверные сетефикаты
k8s_pki_root_ca/
k8s_pki_root_ca/
- это корневой СА которым подписаны все промежуточные СА, и его сертификат СА обязательно требуется распространить по всем хостам так как он является полностью доверенным (в пределах этой инсталляции, конечно)
TLS CA
Для того что бы предоставлять API по https нужны следующие СА
kube-apiserver
TLS CA
Для обеспечения https
доступа к API используются 2 параметра - файл сертефиката и файл ключа
--tls-cert-file
--tls-private-key-file
Этот сертификат выпускается k8s_pki_intermediate_ca_for_service_kube_apiserver_tls/
kube-controller-manager
TLS CA
--tls-cert-file
--tls-private-key-file
kube-scheduler
TLS CA
--tls-cert-file
--tls-private-key-file
kubelet
TLS CA
tlsCertFile
tlsPrivateKeyFile
This parameter should be set via the config file specified by the Kubelet's --config
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
...
tlsCertFile: "/etc/k8s/kubelet/tls/kubelet.az1.k8s.home.pem"
tlsPrivateKeyFile: "/etc/k8s/kubelet/tls/kubelet.az1.k8s.home.key"
authorizationMode: Node,RBAC
Client CA
СА для TLS
Отдельный СА (промежуточный СА!)
Переменные вынесены в отдельный файл
env
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN="s.Yb1J2VamFyYoav3VVE2YQQ88"
export PKI_PATH="k8s_pki_intermediate_ca_for_service_kube_apiserver_tls"
export N='kube-apiserver'
Настройка СА
#!/bin/bash
source ../env
vault \
secrets \
enable \
-path=${PKI_PATH} \
-description="PKI Intermediate CA for K8S kube-apiserver API endpoints" \
-max-lease-ttl="175200h" \
pki
#!/bin/bash
source ../env
vault \
write \
-format=json \
${PKI_PATH}/intermediate/generate/exported \
common_name="Intermediate CA for service kube-api-server API endpoints" \
country="Ukraine" \
locality="Kharkov" \
street_address="Lui Pastera st. 322 app. 131" \
postal_code="61172" \
organization="K8s The Hardest Way Labs" \
ou="IT" \
ttl="175200h" > ${PKI_PATH}.json
cat ${PKI_PATH}.json | jq -r '.data.csr' > ${PKI_PATH}_intermediate_ca.csr
cat ${PKI_PATH}.json | jq -r '.data.private_key' > ${PKI_PATH}_intermediate_ca.key
#!/bin/bash
source ../env
vault \
write \
-format=json \
k8s_pki_root_ca/root/sign-intermediate \
csr=@${PKI_PATH}_intermediate_ca.csr \
country="Ukraine" \
locality="Kharkov" \
street_address="Lui Pastera st. 322 app. 131" \
postal_code="61172" \
organization="K8s The Hardest Way Labs" \
ou="IT" \
format=pem_bundle \
ttl="175200h" > ${PKI_PATH}_intermediate_ca_pem_bundle.json
cat ${PKI_PATH}_intermediate_ca_pem_bundle.json | jq -r '.data.certificate' > ${PKI_PATH}_intermediate_ca_pem.crt
cat ${PKI_PATH}_intermediate_ca_pem_bundle.json | jq -r '.data.issuing_ca' > k8s_root_certificate.pem
#!/bin/bash
source ../env
openssl \
verify \
-verbose \
-CAfile k8s_root_certificate.pem \
${PKI_PATH}_intermediate_ca_pem.crt
#!/bin/bash
source ../env
vault \
write \
${PKI_PATH}/intermediate/set-signed \
certificate=@${PKI_PATH}_intermediate_ca_pem.crt \
key=@${PKI_PATH}_intermediate_ca.key
Права, пользователи, роли
Далее назначить права на пользователей для каждого экземпляра сервера
#!/bin/bash
source ../env
N='kube-apiserver'
for AZ in $(seq 1 3);
do
DOMAIN="${N}.az${AZ}.k8s.cluster.home"
BALANCER_DOMAIN="${N}.k8s.cluster.home"
NAME_SERVER="${DOMAIN}-server"
NAME_CLIENT="${DOMAIN}-client"
vault \
write \
${PKI_PATH}/roles/${NAME_SERVER}-role \
country="Ukraine" \
locality="Kharkov" \
street_address="Lui Pastera st 322 app. 311"\
postal_code="61172" \
organization="Home Network" \
ou="IT" \
allowed_domains="${DOMAIN},${BALANCER_DOMAIN}" \
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" \
require_cn=true
vault \
write \
${PKI_PATH}/roles/${NAME_CLIENT}-role \
country="Ukraine" \
locality="Kharkov" \
street_address="Lui Pastera st 322 app. 311"\
postal_code="61172" \
organization="Home Network" \
ou="IT" \
allow_subdomains=false \
max_ttl="87600h" \
key_bits="2048" \
key_type="rsa" \
allow_any_name=true \
allow_bare_domains=true \
allow_glob_domain=false \
allow_ip_sans=true \
allow_localhost=false \
client_flag=true \
server_flag=false \
enforce_hostnames=true \
key_usage="DigitalSignature,KeyEncipherment" \
ext_key_usage="ClientAuth" \
require_cn=true
done
#!/bin/bash
source ../env
N='kube-apiserver'
for AZ in $(seq 1 3);
do
DOMAIN="${N}.az${AZ}.k8s.cluster.home"
NAME_SERVER="${DOMAIN}-server"
NAME_CLIENT="${DOMAIN}-client"
cat << EOF > ${NAME_SERVER}-policy.hlc
path "${PKI_PATH}/issue/${NAME_SERVER}-role"
{
capabilities = ["read", "create", "list", "update"]
}
EOF
vault \
policy \
write \
${NAME_SERVER}-policy \
${NAME_SERVER}-policy.hlc
vault \
write \
auth/userpass/users/${NAME_SERVER}-user \
password=${NAME_SERVER}-password \
policies=" ${NAME_SERVER}-policy,default"
cat << EOF > ${NAME_CLIENT}-policy.hlc
path "${PKI_NAME}/issue/${NAME_CLIENT}-role"
{
capabilities = ["read", "create", "list", "update"]
}
EOF
vault \
policy \
write \
${NAME_CLIENT}-policy \
${NAME_CLIENT}-policy.hlc
vault \
write \
auth/userpass/users/${NAME_CLIENT}-user \
password=${NAME_CLIENT}-password \
policies=" ${NAME_CLIENT}-policy,default"
done
#!/bin/bash
source ../env
echo "---------ROLES---------------------"
vault \
list \
${PKI_PATH}/roles
echo "---------USERS---------------------"
vault \
list \
auth/userpass/users
echo "------------------------------"
for AZ in $(seq 1 3);
do
echo "------ AZ ${AZ} -----"
DOMAIN="${N}.az${AZ}.k8s.cluster.home"
NAME_SERVER="${DOMAIN}-server"
NAME_CLIENT="${DOMAIN}-client"
vault \
policy \
read \
${NAME_SERVER}-policy
vault \
policy \
read \
${NAME_CLIENT}-policy
vault \
read \
auth/userpass/users/${NAME_SERVER}-user
vault \
read \
auth/userpass/users/${NAME_SERVER}-user
done
Пример получения сертефикатов
на конечных нодах используя имя пользователя и пароль а так же переменную AZ определнную на нодах индивидуально (Сертефикаты для kube-apiserver
--tls-cert-file
и --tls-private-key-file
)
#!/bin/bash
set -eu${DEBUG:+x}
PKI_NAME="k8s_pki_intermediate_ca_for_service_kube_apiserver_tls"
CERTS_PATH="/etc/k8s/kube-apiserver/certs/tls"
mkdir -p ${CERTS_PATH}
N='kube-apiserver'
#AZ=1
DOMAIN="${N}.az${AZ}.k8s.cluster.home"
NAME_SERVER="${DOMAIN}-server"
NAME_CLIENT="${DOMAIN}-client"
BALANCER_DOMAIN="${N}.k8s.cluster.home"
IP="10.0.${AZ}2.1"
vault \
login \
-method=userpass \
username="${NAME_SERVER}-user" \
password="${NAME_SERVER}-password"
DATE=$(date +%Y%m%dT%H%M)
USERNAME="${N}-${AZ}-tls"
echo "========"
vault \
write \
-format=json \
${PKI_NAME}/issue/${NAME_SERVER}-role \
common_name="${DOMAIN}" \
alt_names="${DOMAIN},${BALANCER_DOMAIN}" \
ip_sans="${IP}" \
ca=false \
ttl="43800h" \
> ${CERTS_PATH}/${USERNAME}.crt.json
cat \
${CERTS_PATH}/${USERNAME}.crt.json \
| jq -r '.data.private_key' > ${CERTS_PATH}/${USERNAME}-${DATE}.key
cat \
${CERTS_PATH}/${USERNAME}.crt.json \
| jq -r '.data.certificate' > ${CERTS_PATH}/${USERNAME}-${DATE}.pem
cat \
${CERTS_PATH}/${USERNAME}.crt.json \
| jq -r '.data.ca_chain[]' >> ${CERTS_PATH}/${USERNAME}-${DATE}.pem
ln -sf ${CERTS_PATH}/${USERNAME}-${DATE}.key ${CERTS_PATH}/${N}-tls.key
ln -sf ${CERTS_PATH}/${USERNAME}-${DATE}.pem ${CERTS_PATH}/${N}-tls.pem
СA для клиентов kube-apiserver