Configurer le pilote CSI du magasin de secrets pour activer le contrôleur d’entrée NGINX avec TLS
Cet article vous guide tout au long du processus de sécurisation d’un contrôleur d’entrée NGINX avec TLS en utilisant un cluster Azure Kubernetes Service (AKS) et une instance Azure Key Vault (AKV). Pour plus d’informations, consultez TLS dans Kubernetes.
Vous pouvez importer le certificat TLS d’entrée dans le cluster à l’aide de l’une des méthodes suivantes :
- Application : le manifeste de déploiement de l’application déclare et monte le volume du fournisseur. Ce n’est que lorsque vous déployez l’application que le certificat est disponible dans le cluster. Quand vous supprimez l’application, le secret est également supprimé. Ce scénario convient aux équipes de développement responsables de l’infrastructure de sécurité de l’application et de son intégration au cluster.
- Contrôleur d’entrée : le déploiement d’entrée est modifié pour déclarer et monter le volume du fournisseur. Le secret est importé pendant la création des pods d’entrée. Les pods de l’application n’ont pas accès au certificat TLS. Ce scénario convient quand une équipe (par exemple le service informatique) gère et crée les composants de l’infrastructure et du réseau (y compris les certificats TLS HTTPS) et que d’autres équipes gèrent le cycle de vie des applications.
Prérequis
- Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.
- Avant de commencer, vérifiez que votre version d’Azure CLI est >=
2.30.0
ou installez la dernière version. - Un cluster AKS avec le pilote CSI du magasin de secrets configuré.
- Une instance Azure Key Vault.
Générer un certificat TLS
Générez un certificat TLS à l’aide de la commande suivante.
export CERT_NAME=aks-ingress-cert openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -out aks-ingress-tls.crt \ -keyout aks-ingress-tls.key \ -subj "/CN=demo.azure.com/O=aks-ingress-tls"
Importer le certificat dans AKV
Exportez le certificat dans un fichier PFX à l’aide de la commande suivante.
export AKV_NAME="[YOUR AKV NAME]" openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out $CERT_NAME.pfx # skip Password prompt
Importez le certificat à l’aide de la commande
az keyvault certificate import
.az keyvault certificate import --vault-name $AKV_NAME --name $CERT_NAME --file $CERT_NAME.pfx
Déployer une SecretProviderClass
Exportez un nouvel espace de noms à l’aide de la commande suivante.
export NAMESPACE=ingress-basic
Créez l’espace de noms à l’aide de la commande
kubectl create namespace
.kubectl create namespace $NAMESPACE
Sélectionnez un mécanisme pour fournir une identité d’accès et configurez votre YAML de SecretProviderClass en conséquence.
- Veillez à utiliser
objectType=secret
, qui est la seule façon d’obtenir la clé privée et le certificat d’AKV. - Définissez
kubernetes.io/tls
commetype
dans votre sectionsecretObjects
.
Pour obtenir un exemple de ce à quoi peut ressembler votre SecretProviderClass, consultez ce qui suit :
apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-tls spec: provider: azure secretObjects: # secretObjects defines the desired state of synced K8s secret objects - secretName: ingress-tls-csi type: kubernetes.io/tls data: - objectName: $CERT_NAME key: tls.key - objectName: $CERT_NAME key: tls.crt parameters: usePodIdentity: "false" useVMManagedIdentity: "true" userAssignedIdentityID: <client id> keyvaultName: $AKV_NAME # the name of the AKV instance objects: | array: - | objectName: $CERT_NAME objectType: secret tenantId: $TENANT_ID # the tenant ID of the AKV instance
- Veillez à utiliser
Appliquez SecretProviderClass à votre cluster Kubernetes à l’aide de la commande
kubectl apply
.kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
Déployer le contrôleur d’entrée
Ajouter le dépôt de graphiques d’entrée officiel
Ajoutez le référentiel de graphique d’entrée officiel à l’aide des commandes
helm
suivantes.helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update
Configurer et déployer l’entrée NGINX
Selon votre scénario, vous pouvez choisir de lier le certificat à l’application ou au contrôleur d’entrée. Suivez les instructions ci-dessous en fonction de votre sélection :
Lier le certificat à l’application
Liez le certificat à l’application à l’aide de la commande
helm install
. Le déploiement de l’application fait référence au fournisseur Azure Key Vault du pilote CSI du magasin de secrets.helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
Lier le certificat au contrôleur d’entrée
Liez le certificat au contrôleur d’entrée à l’aide de la commande
helm install
. Le déploiement du contrôleur d’entrée fait référence au fournisseur Azure Key Vault du pilote CSI du magasin de secrets.Remarque
Si vous n’utilisez pas l’identité managée de pod Microsoft Entra comme méthode d’accès, supprimez la ligne qui contient
--set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME
.Par ailleurs, la liaison de SecretProviderClass à un pod est nécessaire pour que le pilote CSI du magasin de secrets le monte et génère le secret Kubernetes. Consultez Synchroniser le contenu monté avec un secret Kubernetes.
helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME \ -f - <<EOF controller: extraVolumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" extraVolumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true EOF
Vérifiez que le secret Kubernetes a été créé à l’aide de la commande
kubectl get secret
.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Déployer l’application
Là encore, les instructions changent légèrement en fonction de votre scénario. Suivez les instructions correspondant au scénario que vous avez sélectionné.
Déployer l’application à l’aide d’une référence d’application
Créez un fichier nommé
aks-helloworld-one.yaml
avec le contenu suivant :apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-one spec: replicas: 1 selector: matchLabels: app: aks-helloworld-one template: metadata: labels: app: aks-helloworld-one spec: containers: - name: aks-helloworld-one image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "Welcome to Azure Kubernetes Service (AKS)" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
Créez un fichier nommé
aks-helloworld-two.yaml
avec le contenu suivant :apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-two spec: replicas: 1 selector: matchLabels: app: aks-helloworld-two template: metadata: labels: app: aks-helloworld-two spec: containers: - name: aks-helloworld-two image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "AKS Ingress Demo" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
Appliquez les fichiers YAML à votre cluster à l’aide de la commande
kubectl apply
.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Vérifiez que le secret Kubernetes a été créé à l’aide de la commande
kubectl get secret
.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Déployer l’application à l’aide d’une référence de contrôleur d’entrée
Créez un fichier nommé
aks-helloworld-one.yaml
avec le contenu suivant :apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-one spec: replicas: 1 selector: matchLabels: app: aks-helloworld-one template: metadata: labels: app: aks-helloworld-one spec: containers: - name: aks-helloworld-one image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "Welcome to Azure Kubernetes Service (AKS)" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
Créez un fichier nommé
aks-helloworld-two.yaml
avec le contenu suivant :apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-two spec: replicas: 1 selector: matchLabels: app: aks-helloworld-two template: metadata: labels: app: aks-helloworld-two spec: containers: - name: aks-helloworld-two image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "AKS Ingress Demo" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
Appliquez les fichiers YAML à votre cluster à l’aide de la commande
kubectl apply
.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Déployer une ressource d’entrée qui référence le secret
Nous pouvons à présent déployer une ressource d’entrée Kubernetes qui fait référence au secret.
Créez un fichier
hello-world-ingress.yaml
avec le contenu suivant.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-tls annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx tls: - hosts: - demo.azure.com secretName: ingress-tls-csi rules: - host: demo.azure.com http: paths: - path: /hello-world-one(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80 - path: /hello-world-two(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-two port: number: 80 - path: /(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80
Notez la section
tls
qui fait référence au secret que nous avons créé précédemment et appliquez le fichier à votre cluster à l’aide de la commandekubectl apply
.kubectl apply -f hello-world-ingress.yaml -n $NAMESPACE
Obtenir l’adresse IP externe du contrôleur d’entrée
Obtenez l’adresse IP externe du contrôleur d’entrée à l’aide de la commande
kubectl get service
.kubectl get service --namespace $NAMESPACE --selector app.kubernetes.io/name=ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-1588032400-controller LoadBalancer 10.0.255.157 EXTERNAL_IP 80:31293/TCP,443:31265/TCP 19m nginx-ingress-1588032400-default-backend ClusterIP 10.0.223.214 <none> 80/TCP 19m
Tester l’entrée sécurisée avec TLS
Vérifiez que votre entrée est correctement configurée avec TLS à l’aide de la commande
curl
suivante. Veillez à utiliser l’adresse IP externe de l’étape précédente.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
Aucun autre chemin n’ayant été fourni avec l’adresse, l’itinéraire par défaut du contrôleur d’entrée est /. La première application de démonstration est retournée, comme l’illustre l’exemple de sortie condensée suivant :
[...] <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>Welcome to Azure Kubernetes Service (AKS)</title> [...]
Le paramètre -v figurant dans la commande
curl
fournit en sortie des informations détaillées incluant le certificat TLS reçu. À mi-chemin vers la sortie de la commande curl, vous pouvez vérifier que votre propre certificat TLS a été utilisé. Le paramètre -k continue le chargement de la page même si nous utilisons un certificat auto-signé. L’exemple suivant montre que le certificat issuer: CN=demo.azure.com; O=aks-ingress-tls a été utilisé :[...] * Server certificate: * subject: CN=demo.azure.com; O=aks-ingress-tls * start date: Oct 22 22:13:54 2021 GMT * expire date: Oct 22 22:13:54 2022 GMT * issuer: CN=demo.azure.com; O=aks-ingress-tls * SSL certificate verify result: self signed certificate (18), continuing anyway. [...]
Ajoutez le chemin /hello-world-two à l’adresse, par exemple,
https://demo.azure.com/hello-world-two
, puis vérifiez que la deuxième application de démonstration est correctement configurée.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com/hello-world-two
La deuxième application de démonstration avec le titre personnalisé est retournée, comme l’illustre l’exemple de sortie condensée suivant :
[...] <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>AKS Ingress Demo</title> [...]
Azure Kubernetes Service