Skip to content

Sécurité avant tout

Estimated time to read: 4 minutes

Nous allons gérer les certificats avec cert-manager

Installation

cert-manager fournit un Helm chart, configurons le repo:

helm repo add jetstack https://charts.jetstack.io
helm repo update

Et maintenant nous pouvons installer cert-manager dans notre cluster dans un namespace dédié

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.13.3 \
  --set installCRDs=true

cert-manager est installé

cert-manager v1.13.3 has been deployed successfully! # (1)
  1. ℹ️ La version peut être différente

Maintenant, vérifions que tout est ok:

kubectl get all -n cert-manager
NAME                                         READY   STATUS    RESTARTS   AGE
pod/cert-manager-6856dc897b-k6dks            1/1     Running   0          32s
pod/cert-manager-cainjector-c86f8699-cmc7t   1/1     Running   0          32s
pod/cert-manager-webhook-f8f64cb85-7rjjz     1/1     Running   0          32s

NAME                           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cert-manager           ClusterIP   10.3.242.74    <none>        9402/TCP   33s
service/cert-manager-webhook   ClusterIP   10.3.182.243   <none>        443/TCP    33s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cert-manager              1/1     1            1           33s
deployment.apps/cert-manager-cainjector   1/1     1            1           33s
deployment.apps/cert-manager-webhook      1/1     1            1           33s

NAME                                               DESIRED   CURRENT   READY   AGE
replicaset.apps/cert-manager-6856dc897b            1         1         1       33s
replicaset.apps/cert-manager-cainjector-c86f8699   1         1         1       33s
replicaset.apps/cert-manager-webhook-f8f64cb85     1         1         1       33s

Configuration

cert-manager permet de générer des certificats pour sécuriser nos endpoints. Il supporte plusieurs providers, ici nous allons utiliser le classique mais pratique Let's Encrypt.

Pour cela, nous devons créer un Issuer, ici un ClusterIssuer pour accéder à l'ensemble du cluster

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
  namespace: cert-manager
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <your-email> # (1)
    privateKeySecretRef:
      name: letsencrypt-production # (2)
    solvers:
      - http01:
          ingress:
            class: nginx # (3)
  1. 📧 Un email est nécessaire pour l'appartenance du domaine
  2. 📜 On utilise le serveur de production
  3. 🛜 On précise que l'on répondra au challenge HTTP en utilisant un Ingress de type nginx

Editer le fichier cert-manager/letsencrypt-cluster-issuer.yml pour positionner un email valide.

Créons notre issuer:

kubectl apply -n cert-manager -f cert-manager/letsencrypt-cluster-issuer.yml

Issuer créé

clusterissuer.cert-manager.io/letsencrypt-production created
Utilisation du serveur de staging

Par défaut, on utilise le serveur de production de Let's Encrypt, mais celui à la limitation que si vous avez un nombre de requêtes en échec trop importants, vous pouvez être banni temporairement.

Pour une phase de test, il est possible d'utiliser le serveur de staging de Let's Encrypt qui n'a pas cette limitation.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  namespace: cert-manager
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: <your-email>
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
      - http01:
          ingress:
            class: nginx

Utilisation

Maintenant, on peut sécuriser nos URLs. Il suffit d'updater notre Ingress pour lui configurer le TLS.

Pour cela, il faut mettre à jour le fichier demos/deployment-with-ingress-https-grunty.yml avec votre trigramme.

Déployons ensuite notre nouveau composant:

kubectl apply -f demos/deployment-with-ingress-https-grunty.yml
Pour les curieux, le contenu du manifest deployment-with-ingress-https-grunty.yml

Les lignes surlignées configurent le TLS

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secured-deployment-ingress
  namespace: demos
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-production
spec:
  ingressClassName: nginx
  rules:
    - host: &host secured.<votre_trigramme>.grunty.uk
      http:
        paths:
          - backend:
              service:
                name: new-deployment-service
                port:
                  number: 80
            pathType: Prefix
            path: /
  tls:
    - hosts:
        - *host
      secretName: *host
---

Deployment installé

ingress.networking.k8s.io/secured-deployment-ingress created

On peut voir que cert-manager instancie un Ingress pour gérer les échanges avec Let's Encrypt pour la génération du certificat:

kubectl get ingress -n demos
NAME                         CLASS    HOSTS                                       ADDRESS         PORTS     AGE
cm-acme-http-solver-hmh8t    <none>   secured.<votre_trigramme>.grunty.uk                         80        47s
new-deployment-ingress       nginx    new-deployment.<votre_trigramme>.grunty.uk  57.128.120.31   80        19h
secured-deployment-ingress   nginx    secured.<votre_trigramme>.grunty.uk                         80, 443   50s

Une fois les challanges terminés avec Let's Encrypt, on voit aussi qu'un Certificate a été généré. Il est au statut Ready à False, au bout de quelques secondes, il devrait passer à True

kubectl get certificates -n demos

Certificat généré

NAME                                      READY   SECRET                                    AGE
secured.<votre_trigramme>.grunty.uk-tls   True    secured.<votre_trigramme>.grunty.uk-tls   3m44s
Behind the scene

On peut facilement voir les étapes en observant les events

kubectl get events --sort-by='.lastTimestamp' -n demos

Tout semble ok, on peut vérifier que notre URL est désormais sécurisée : https://secured.{votre_trigramme}.grunty.uk

Site accessible en HTTPs

Mais notre chef de brigade est vraiment pointilleux 😅, notre gestion des données sensibles tels que nos API keys ne lui convient pas.

Alors pimentons un peu tout cela avec une gestion de secrets plus propre ➡️