Lorsqu’on souhaite déployer un service sur Kubernetes et le protéger via TLS, la méthode la plus simple est généralement de s’appuyer sur la solution d’ingress controller existante sur le cluster.

Mais dans certains cas on doit intervenir sur des clusters qui sont gérés par d’autres équipes et sur lequels aucune solution d’ingress n’est mise en place pour gérer le traffic entrant. De plus sur ce type de cluster on n’a pas forcément la lattitude de pouvoir faire ce qui nous plaît faute de droits suffisants.

Dans ce cas, une solution est de déployer soi-même un pod Nginx et de le configurer pour qu’il porte la terminaison TLS de notre service.

Gestion des certificats

Première étape, créons notre autorité de certification :

openssl genrsa -out rootCA.key 4096
openssl req -x509 -sha256 -new -nodes -key rootCA.key -days 3650 -out rootCA.crt

Puis le certificat pour notre service :

openssl req -new -newkey rsa:4096 -nodes -keyout cert.key -out cert.csr -subj "/C=FR/O=Xian-Labs/CN=mon-service.example.com"
openssl x509 -req -sha256 -days 365 -in cert.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out cert.crt

Vérifions le certificat produit :

openssl x509 -in cert.crt -text -noout

Configuration Nginx

Nous utilisons le fichier de configuration suivant pour Nginx :

default.conf ouvrir

server {
    listen       80;
    return 301 https://$host$request_uri;
}

server {

    listen        443 ssl;
    server_name   localhost;

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

    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    access_log            /var/log/nginx/access.log;

    proxy_set_header        Host $host:8443;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;

    location / {
        proxy_pass http://mon-service;
    }
}

Ce fichier nous permet de définir l’emplacement des certificats TLS ainsi que le service vers lequel nous souhaitons proxifier le traffic via la directive :

proxy_pass http://mon-service

Nous allons ensuite créer les élements de configuration pour notre Pod Nginx :

  1. un Secret qui contiendra les certificats TLS

    kubectl create secret tls mon-service-tls --cert cert.crt --key cert.key
    
  2. un ConfigMap qui contiendra le fichier de configuration Nginx décrit ci-dessus

    kubectl create configmap mon-service-tls --from-file default.conf
    

Déploiement du reverse proxy Nginx

Nous déclarons un Deployment ainsi qu’un Service Kubernetes de type NodePort :

nginx-tls.deployment.yaml ouvrir

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-service-tls
  namespace: xian
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mon-service-tls
  template:
    metadata:
      labels:
        app: mon-service-tls
    spec:
      containers:
      - name: nginx
        image: nginx:1.23.1-alpine
        volumeMounts:
          - name: nginx-conf
            mountPath: /etc/nginx/conf.d/default.conf
            subPath: default.conf
            readOnly: true
          - name: certs
            mountPath: /etc/nginx/certs

      volumes:
        - name: nginx-conf
          configMap:
            name: mon-service-tls
        - name: certs
          secret:
            secretName: mon-service-tls

nginx-tls.service.yaml ouvrir

apiVersion: v1
kind: Service
metadata:
  name: mon-service-tls
  namespace: xian
spec:
  ports:
  - nodePort: 32352
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: mon-service-tls
  type: NodePort
kubectl apply -f nginx-tls.deployment.yaml
kubectl apply -f nginx-tls.service.yaml

Et voilà, notre service est protégé avec TLS ;-)