TLS Termination - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises

Như bài viết trước nói về vấn đề kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises , có thể tham khảo bài trước đó để biết thêm chi tiết. Bài hôm nay là phần bổ trợ thêm đó là cài TLS cho dự án này để đảm bảo tính bảo mật hơn.

Trước tiên để việc với TLS thì cần cần hiểu một số khái niệm khái quát sau, khái quát thôi nhé muốn chuyên sâu về nó thì google thêm, vì nếu không hiểu khái niệm nó là gì thì chỉ thấy chạy lên là vỗ tay bốp bốp mà không hiểu thì cũng không hay lắm. Các khái niệm bên dưới sẽ giúp bạn những thứ bạn có thể đi tiếp, trong bài này chỉ là ví dụ cơ bản nó sẽ không diễn tả hết được, nhưng thông qua các keywork sẽ giúp mườn tượng ra được nhiều thứ hay ho để làm hơn. 

TLS Termination

Là khái niệm chỉ việc kết thúc kết nối TLS ở một thiết bị trung gian thay vì ở điểm cuối.

Client (trình duyệt) thiết lập kết nối TLS tới Load Balancer. 

Load Balancer giải mã dữ liệu TLS và chuyển tiếp dữ liệu đã giải mã tới các backend server (không còn mã hóa). Đây được gọi là TLS termination tại Load Balancer.

Client <===TLS===> Load balancer <===HTTP==> Server app


Mutual TLS

Cho phép cả server và client xác thực lẫn nhau trong quá trình thiết lập kết nối bảo mật.

Client sẽ xác thực danh tính của server bằng cách kiểm tra chứng chỉ (certificate) mà server cung cấp.

Server cũng sẽ xác thực danh tính của client bằng cách yêu cầu client cung cấp chứng chỉ.

Chỉ khi cả hai bên đều xác thực thành công danh tính của nhau, kết nối mới được thiết lập.


Client <===client & server auth ===> Load balancer <===client & server auth ==> Server app


Upstream TLS

Là việc sử dụng TLS ở phía upstream, tức là mã hóa kết nối giữa proxy server (ví dụ Nginx) và backend server (ví dụ API server). Proxy server sẽ mở kết nối TLS với backend server để đảm bảo dữ liệu truyền tải là riêng tư.


TLS Upstream 

Là việc sử dụng TLS ở phía client, tức là mã hóa kết nối giữa client (trình duyệt web, ứng dụng...) và proxy server. Client sẽ mở kết nối TLS với proxy server để đảm bảo dữ liệu truyền tải từ client lên là riêng tư.


Client <===TLS===> Load balancer <===TLS ==> Server app


Cấu hình môi trường thì dùng lại lab bài hôm trước, click vào link trên để xem, giờ có các manifest và kịch bạn theo lý thuyết ở trên sẽ  như sau : 


TLS Termination :

Đối với phần này thì khá đơn giản, copy lại manifest của bài trước, thêm vài thứ vào là xong, phần này khá là nhẹ.

Tạo namespace

kind: Namespace
apiVersion: v1
metadata:
  name: chemgio-project-tls

Tạo cert và tạo secret

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt


~/chemgio-project-tls/certs$ k create secret tls chemgio-secret-project-tls --key=ca.key --cert=ca.crt -n chemgio-project-tls


Tạo deploy


kind: Deployment
apiVersion: apps/v1
metadata:
  name: chemgio-project-tls
  namespace: chemgio-project-tls
spec:
  replicas: 2
  selector:
    matchLabels:
      app: chemgio-project-tls
  template:
    metadata:
      labels:
        app: chemgio-project-tls
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: http
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}


Tạo service

kind: Service
apiVersion: v1
metadata:
  name: chemgio-project-tls
  namespace: chemgio-project-tls
spec:
  selector:
    app: chemgio-project-tls
  ports:
    - port: 80
      targetPort: 80


Tạo HTTPProxy


apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: chemgio-project-tls
  namespace: chemgio-project-tls
spec:
  virtualhost:
    fqdn: chemgio.loc
    tls:
      secretName: chemgio-secret-project-tls
  routes:
    - services:
        - name: chemgio-project-tls
          port: 80


Cuối cùng là xong phần TLS Termination, phần này khá nhẹ nhàng và đơn giản, vì bên trong không bận tâm gì nhiều. :)


TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises



TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises


Upstream TLS :

Tạo Namespace


kind: Namespace
apiVersion: v1
metadata:
  name: demo1-project-tls-upstream


Tạo ConfigMap : Có thể tạo config map từ manifest or import từ default.conf cũng được.


apiVersion: v1
data:
  default.conf: |-
        server {
                listen 80 default_server;
                listen [::]:80 default_server ipv6only=on;
                server_name localhost;

                location / {
                        return 301 https://$host$request_uri;
                }
        }

        server {
                listen 443 ssl;
                listen [::]:443 ssl;
                server_name localhost;

                ssl_certificate /etc/nginx/ssl/tls.crt;
                ssl_certificate_key /etc/nginx/ssl/tls.key;


                root /usr/share/nginx/html;
                index index.html;

                location / {
                        try_files $uri $uri/ =404;
                }
        }

kind: ConfigMap
metadata:
  name: demo1-configmap-tls-upstream
  namespace: demo1-project-tls-upstream


Tạo Secrets : ở đây là môi trường lab, nhằm phục vụ cho môi trường private nên hiện tại đang dùng openssl để giả lập cert, với môi trường thực tế thì thay đổi lại sao cho phù hợp.

openssl genpkey -algorithm RSA -out private.key


openssl rsa -pubout -in private.key -out public.pem


openssl req -new -key private.key -out server.csr


openssl genpkey -algorithm RSA -out ca-private.key


openssl req -new -key ca-private.key -out ca-csr.pem


openssl x509 -req -in ca-csr.pem -signkey ca-private.key -out ca-certificate.pem


openssl x509 -req -in server.csr -CA ca-certificate.pem -CAkey ca-private.key -CAcreateserial -out server-certificate.pem


Sau khi chạy các lệnh trên thì được danh sách file như sau: 


ca-certificate.pem  ca-csr.pem  ca-private.key  private.key  public.pem  server-certificate.pem  server.csr


Sử dụng các file cần thiết như bên dưới để tạo secret, theo dõi bên dưới để biết file nào cần dùng.


Tạo secret private

kubectl create secret tls demo1-secret-tls-upstream-private --key="private.key" --cert="server-certificate.pem" -n demo1-project-tls-upstream

Tạo secret public


kubectl create secret tls demo1-secret-tls-upstream-public --key="ca-private.key" --cert="ca-certificate.pem" -n demo1-project-tls-upstream



Tạo Deployment : Bên dưới là manifest tạo ra deployment và hiện tại đang replicas  tương ứng 2 pod sẽ chạy cho dự án này, cần chú ý rõ phần volumes vì nó dùng để mount các tls chạy nội bộ bên trong.


kind: Deployment
apiVersion: apps/v1
metadata:
  name: demo1-project-tls-upstream
  namespace: demo1-project-tls-upstream
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo1-project-tls-upstream
  template:
    metadata:
      labels:
        app: demo1-project-tls-upstream
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: http
        ports:
        - containerPort: 80
        - containerPort: 443
        volumeMounts:
        - name: demo1-secret-tls-upstream-private
          mountPath: /etc/nginx/ssl
        - name: demo1-project-tls-upstream
          mountPath: /etc/nginx/conf.d
      volumes:
        - name: demo1-secret-tls-upstream-private
          secret:
            secretName: demo1-secret-tls-upstream-private
        - name: demo1-project-tls-upstream
          configMap:
            name: demo1-configmap-tls-upstream


Tạo Service : Sau khi chạy xong service này thì xem như phần bên trong đã hoàn tất, có thể test qua cổng serice thì xem như hoàn tất. Điểm lưu ý là phần annotations nếu muốn Upstream TLS thì bắt buộc phải có https://projectcontour.io/upstream-protocol.tls: "443,https" nếu không có sẽ bị lỗi ngay. Bên dưới sẽ có phần note để có thể hình dung ra.


apiVersion: v1
kind: Service
metadata:
  name: demo1-project-tls-upstream
  namespace: demo1-project-tls-upstream
  annotations:
    projectcontour.io/upstream-protocol.tls: "443,https"
spec:
  ports:
  - name: https
    port: 443
    targetPort: 443
  selector:
    app: demo1-project-tls-upstream

Đây là hình test bên trong trước, đảm bảo pod thông qua service đã hoạt động.


TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises



HTTPProxy : Thông qua cổng service sẽ cấu hình HTTPProxy cho web ra bên ngoài thông qua serice, và kết quả sẽ như sau.


apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: demo1-project-tls-upstream
  namespace: demo1-project-tls-upstream
spec:
  virtualhost:
    fqdn: demo1.loc
    tls:
      secretName: demo1-secret-tls-upstream-public
  routes:
  - services:
    - name: demo1-project-tls-upstream
      port: 443

Kết quả test bên ngoài như sau :


TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises



TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises

Note: Như phần service ở trên nói nếu bỏ annotations  thì sao, vấn đề sẽ xảy ra vì nó sẽ không hiểu và kết quả xảy ra như sau. Bên dưới là sau khi remove và replace force lại sevice.


TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises




TLS Termination  - Upstream TLS - Kubernetes kết hợp với MetalLB và Contour ingress controller trên Kubernetes On-Premises



Ở trên đây là ví dụ cụ thể được follow theo document của project contour, nếu bạn muốn nghiên cứu thêm có thể đọc tài liệu và nghiên cứu thêm, nó khá là nhiều nên cứ từ từ trải nghiệm :)


Nhãn: