🔒Налаштування mTLS для вашого додатку

mTLS за допомогою Envoy як контейнера-сайдкара

Огляд

У цьому посібнику я покажу, як налаштувати mTLS для додатку, розгорнутого в Kubernetes, з використанням envoy.

Ми поетапно розгорнемо echo-сервер і захистимо його за допомогою mTLS через envoy як контейнер-сайдкар.

Кроки:

  • Розгорнути echo-сервер.
  • Доступ до echo-сервера через проксі envoy.
  • Додати mTLS до проксі envoy.

🗣 Розгортання echo-сервера

Давайте спершу розгорнемо простий echo-сервер і перевіримо його доступність. Для цього я використовую ealen/echo-server і розгорну його з використанням minikube. Однак ви можете використовувати будь-який інший інструмент, наприклад, kind.

Після налаштування нашого кластера minikube застосуємо наступний yaml файл:

apiVersion: apps/v1  
kind: Deployment  
metadata:  
 name: echoserver-deployment  
 labels:  
 app: echoserver  
spec:  
 replicas: 1  
 selector:  
 matchLabels:  
 app: echoserver  
 template:  
 metadata:  
 labels:  
 app: echoserver  
 spec:  
 containers:  
 - name: echoserver  
 image: ealen/echo-server:latest  
 ports:  
 - containerPort: 80  
 name: http-web-svc  
---  
apiVersion: v1  
kind: Service  
metadata:  
 name: echoserver-direct-service  
 labels:  
 app: echoserver  
spec:  
 type: LoadBalancer  
 selector:  
 app: echoserver  
 ports:  
 - name: http  
 protocol: TCP  
 port: 8082  
 targetPort: http-web-svc

Запустив:

> kubectl apply -f echoserver.yaml  
> minikube tunnel

Ми повинні зуміти зайти на url http://localhost:8082 і побачити відповідь від echo-сервера.

Отже, це поточна налаштування:

pic

Ми можемо безпосередньо отримати доступ до контейнера echo-сервера через порт 8082.

Файли розгортання можна знайти тут: https://github.com/manuelarte/demo-mTLS/tree/master/steps/echoserver-simple

⛩️🗣 Розгортання echo-сервера і проксі envoy

Тепер, замість прямого доступу до echo-сервера, ми введемо проксі envoy.

Отже, ось схема того, що ми хочемо досягти:

pic

У цьому випадку ми не отримуємо доступ до echo-сервера безпосередньо, а робимо це через envoy.
Envoy працює як проксі для нашого сервісу.

Ось файл yaml:

apiVersion: apps/v1  
kind: Deployment  
metadata:  
 name: echoserver-deployment  
 labels:  
 app: echoserver  
spec:  
 replicas: 1  
 selector:  
 matchLabels:  
 app: echoserver  
 template:  
 metadata:  
 labels:  
 app: echoserver  
 spec:  
 containers:  
 - name: echoserver  
 image: ealen/echo-server:latest  
 ports:  
 - containerPort: 80  
 name: http-web-svc  
 - name: sidecar  
 image: envoyproxy/envoy:v1.29-latest  
 ports:  
 - containerPort: 8080  
 name: http-web-envoy  
 volumeMounts:  
 - name: config-envoy-vol  
 mountPath: /etc/envoy  
 volumes:  
 - name: config-envoy-vol  
 configMap:  
 name: config-envoy  
 items:  
 - key: envoy.yaml  
 path: envoy.yaml  
---  
apiVersion: v1  
kind: Service  
metadata:  
 name: echoserver-envoy-service  
 labels:  
 app: echoserver  
spec:  
 type: LoadBalancer  
 selector:  
 app: echoserver  
 ports:  
 - name: http  
 protocol: TCP  
 port: 8080  
 targetPort: 8080

Як ви можете бачити, нам також потрібен ConfigMap з наступним файлом для envoy

static_resources:  
 listeners:  
 - name: echoserver-listener  
 address:  
 socket_address:  
 address: 0.0.0.0  
 port_value: 8080  
 filter_chains:  
 - filters:  
 - name: envoy.filters.network.http_connection_manager  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager  
 http_protocol_options:  
 accept_http_10: true  
 stat_prefix: ingress_http  
 access_log:  
 - name: envoy.access_loggers.stdout  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog  
 route_config:  
 name: echoserver-route  
 virtual_hosts:  
 - name: echoserver  
 domains: ["*"]  
 routes:  
 - match:  
 prefix: "/"  
 route:  
 cluster: echoserver-cluster  
 http_filters:  
 - name: envoy.filters.http.router  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router  

 clusters:  
 - name: echoserver-cluster  
 type: STRICT_DNS  
 lb_policy: ROUND_ROBIN  
 load_assignment:  
 cluster_name: echoserver  
 endpoints:  
 - lb_endpoints:  
 - endpoint:  
 address:  
 socket_address:  
 address: localhost  
 port_value: 80

Файли для розгортання можна знайти тут: https://github.com/manuelarte/demo-mTLS/tree/master/steps/echoserver-proxy

🔒⛩️🗣 Розгортання echo-сервера з envoy та mTLS

Тепер давайте налаштуємо envoy для забезпечення взаємного TLS.

- Генерація сертифікатів авторитету (CA) та серверних сертифікатів

Перше, що потрібно зробити — це згенерувати сертифікати

openssl genrsa -out "ca.key" 4096  
export CA_SUBJECT="/C=NL/ST=North Holland/L=AMS/O=manuelarte/OU=IT/CN=rootCA"  
openssl req -x509 -new -nodes -key "ca.key" -sha256 -days 365 -out "ca.crt" -subj "$CA_SUBJECT"  
# Генерація серверного ключа та сертифікату  
openssl req -nodes -x509 -sha256 -newkey rsa:4096 \  
 -keyout key.pem \  
 -subj /C=NL/ST=NH/O=ING/CN=echoserver-envoy-service \  
 -out cert.pem \  
 -addext subjectAltName=DNS:echoserver-envoy-service

Це згенерує:

  • ca.crt: Корінний сертифікат авторитету.
  • cert.pem: Сертифікат сервера.
  • key.pem: Приватний ключ сервера.

Ми додамо ці серверні сертифікати в envoy.yaml.

- Генерація клієнтських сертифікатів

Тепер згенеруємо клієнтські сертифікати:

# Створення приватного ключа для клієнтського сертифіката  
openssl genrsa -out client.key 4096  
# Генерація запиту на сертифікат для клієнтського сертифіката  
openssl req -new -sha256  
 -out client.csr  
# Підписання запиту з використанням збереженого CA для створення клієнтського сертифіката  
openssl x509 -req \  
 -in client.csr \  
 -CA ca.crt \  
 -CAkey ca.key \  
 -out client.crt \  
 -days 365 -sha256 -CAcreateserial \

-extfile <(printf "subjectAltName=DNS:localhost,DNS:manuelarte")

Це згенерує:

  • client.cert: Клієнтські сертифікати.
  • client.key: Приватний ключ клієнта.

Ці сертифікати можна використовувати, наприклад, у команді cURL.

- Envoy.yaml з конфігурацією mTLS

Ось як виглядає новий файл envoy.yaml:

admin:  
 address:  
 socket_address:  
 address: 0.0.0.0  
 port_value: 9901  
static_resources:  
 listeners:  
 - name: echoserver-listener  
 address:  
 socket_address:  
 address: 0.0.0.0  
 port_value: 8080  
 filter_chains:  
 - filters:  
 - name: envoy.filters.network.http_connection_manager  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager  
 http_protocol_options:  
 accept_http_10: true  
 stat_prefix: ingress_http  
 access_log:  
 - name: envoy.access_loggers.stdout  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog  
 route_config:  
 name: echoserver-route  
 virtual_hosts:  
 - name: echoserver  
 domains: ["*"]  
 routes:  
 - match:  
 prefix: "/"  
 route:  
 cluster: echoserver-cluster  
 http_filters:  
 - name: envoy.filters.http.router  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router  
 transport_socket:  
 name: envoy.transport_sockets.tls  
 typed_config:  
 "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext  
 require_client_certificate: true  
 common_tls_context:  
 validation_context:  
 trusted_ca:  
 filename: /etc/certs/ca.crt  
 tls_certificates:  
 - certificate_chain:  
 filename: /etc/certs/cert.pem  
 private_key:  
 filename: /etc/certs/key.pem  

 clusters:  
 - name: echoserver-cluster  
 type: STRICT_DNS  
 lb_policy: ROUND_ROBIN  
 load_assignment:  
 cluster_name: echoserver  
 endpoints:  
 - lb_endpoints:  
 - endpoint:  
 address:  
 socket_address:  
 address: localhost  
 port_value: 80

Як ви можете бачити, деякі нові додані рядки виглядають так:

"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext  
...

common_tls_context:  
 validation_context:  
 trusted_ca:  
 filename: /etc/certs/ca.crt # сертифікат CA  
 tls_certificates:  
 - certificate_chain:  
 filename: /etc/certs/cert.pem # серверний сертифікат  
 private_key:  
 filename: /etc/certs/key.pem # приватний ключ сервера

(Не забудьте змінити deployment.yaml, щоб включити обсяг /etc/certs/ і додати відповідні файли до цього шляху. Якщо ви хочете побачити всю конфігурацію yaml, перевірте https://github.com/manuelarte/demo-mTLS/tree/master/echoserver).

Тепер, якщо ми спробуємо перейти на https://localhost:8080, ми не отримаємо жодної відповіді.

Але ми можемо використати команду cURL з клієнтськими сертифікатами:

> curl -k -v --cacert /echoserver/certs/ca.crt --cert /echoserver/certs/client.crt --key /echoserver/certs/client.key https://localhost:8080

(Не забудьте змінити ).

щоб отримати правильну відповідь від echo.

Перекладено з: 🔒Configuring mTLS For Your App

Leave a Reply

Your email address will not be published. Required fields are marked *