Activer le protocole HTTPS automatique avec Caddy dans un conteneur side-car
Cet article décrit comment Caddy peut être utilisé comme conteneur side-car dans un groupe de conteneurs et faire office de proxy inverse pour fournir un point de terminaison HTTPS géré automatiquement pour votre application.
Caddy est un serveur web puissant, prêt pour l’entreprise, open source avec https automatique écrit en Go et représente une alternative à Nginx.
L’automatisation des certificats est possible, car Caddy prend en charge l’API ACMEv2 (RFC 8555) qui interagit avec Let’s Encrypt pour émettre des certificats.
Dans cet exemple, seul le conteneur Caddy est exposé sur les ports 80/TCP et 443/TCP. L’application derrière le proxy inverse reste privée. La communication réseau entre Caddy et votre application s’effectue via localhost.
Notes
Cela contraste avec la communication intra-groupe de conteneurs connue de docker compose, où les conteneurs peuvent être référencés par nom.
L’exemple monte le Caddyfile, qui est nécessaire pour configurer le proxy inverse, à partir d’un partage de fichiers hébergé sur un compte stockage Azure.
Notes
Pour les déploiements de production, la plupart des utilisateurs souhaitent intégrer le Caddyfile dans une image Docker personnalisée basée sur caddy. De cette façon, il n’est pas nécessaire de monter des fichiers dans le conteneur.
Prérequis
Utilisez l’environnement Bash dans Azure Cloud Shell. Pour plus d’informations, consultez Démarrage rapide pour Bash dans Azure Cloud Shell.
Si vous préférez exécuter les commandes de référence de l’interface de ligne de commande localement, installez l’interface Azure CLI. Si vous exécutez sur Windows ou macOS, envisagez d’exécuter Azure CLI dans un conteneur Docker. Pour plus d’informations, consultez Guide pratique pour exécuter Azure CLI dans un conteneur Docker.
Si vous utilisez une installation locale, connectez-vous à Azure CLI à l’aide de la commande az login. Pour finir le processus d’authentification, suivez les étapes affichées dans votre terminal. Pour connaître les autres options de connexion, consultez Se connecter avec Azure CLI.
Lorsque vous y êtes invité, installez l’extension Azure CLI lors de la première utilisation. Pour plus d’informations sur les extensions, consultez Utiliser des extensions avec Azure CLI.
Exécutez az version pour rechercher la version et les bibliothèques dépendantes installées. Pour effectuer une mise à niveau vers la dernière version, exécutez az upgrade.
- Cet article nécessite la version 2.0.55 ou une version ultérieure de l’interface Azure CLI. Si vous utilisez Azure Cloud Shell, la version la plus récente est déjà installée.
Préparer le caddyfile
Créez un fichier nommé Caddyfile
et collez la configuration suivante. Cette configuration crée une configuration de proxy inverse, pointant vers votre conteneur d’application à l’écoute sur 5000/TCP.
my-app.westeurope.azurecontainer.io {
reverse_proxy http://localhost:5000
}
Il est important de noter que la configuration fait référence à un nom de domaine au lieu d’une adresse IP. Caddy doit être accessible par cette URL pour effectuer l’étape de défi requise par le protocole ACME et récupérer un certificat à partir de Let’s Encrypt.
Notes
Pour le déploiement en production, les utilisateurs peuvent souhaiter utiliser un nom de domaine qu’ils contrôlent, par exemple, api.company.com
et créer un enregistrement CNAME pointant vers, par exemple my-app.westeurope.azurecontainer.io
. Si c’est le cas, il doit être vérifié que le nom de domaine personnalisé est également utilisé dans le Caddyfile, au lieu de celui attribué par Azure (par exemple, *.westeurope.azurecontainer.io
). En outre, le nom de domaine personnalisé doit être référencé dans la configuration YAML ACI décrite plus loin dans cet exemple.
Préparer le compte de stockage
Créez un compte de stockage.
az storage account create \
--name <storage-account> \
--resource-group <resource-group> \
--location westeurope
Stockez votre chaîne de connexion dans une variable d’environnement
AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string --name <storage-account> --resource-group <resource-group> --output tsv)
Créez les partages de fichiers nécessaires pour stocker l’état du conteneur et la configuration du caddy.
az storage share create \
--name proxy-caddyfile \
--account-name <storage-account>
az storage share create \
--name proxy-config \
--account-name <storage-account>
az storage share create \
--name proxy-data \
--account-name <storage-account>
Récupérer les clés de compte de stockage et prendre note pour une utilisation ultérieure
az storage account keys list -g <resource-group> -n <storage-account>
Déployer le groupe de conteneurs
Créer un fichier YAML
Créez un fichier appelé ci-my-app.yaml
et collez-y le contenu suivant. Veillez à remplacer <account-key>
par l’une des clés d’accès reçues précédemment et <storage-account>
en conséquence.
Ce fichier YAML définit deux conteneurs reverse-proxy
et my-app
. Le reverse-proxy
conteneur monte les trois partages de fichiers créés précédemment. La configuration expose également les ports 80/TCP et 443/TCP du reverse-proxy
conteneur. La communication entre les deux conteneurs se produit uniquement sur localhost.
Notes
Il est important de noter que la dnsNameLabel
clé définit le nom DNS public sous lequel le conteneur instance groupe sera accessible, elle doit correspondre au nom de domaine complet défini dans leCaddyfile
name: ci-my-app
apiVersion: "2021-10-01"
location: westeurope
properties:
containers:
- name: reverse-proxy
properties:
image: caddy:2.6
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
resources:
requests:
memoryInGB: 1.0
cpu: 1.0
limits:
memoryInGB: 1.0
cpu: 1.0
volumeMounts:
- name: proxy-caddyfile
mountPath: /etc/caddy
- name: proxy-data
mountPath: /data
- name: proxy-config
mountPath: /config
- name: my-app
properties:
image: mcr.microsoft.com/azuredocs/aci-helloworld
ports:
- port: 5000
protocol: TCP
environmentVariables:
- name: PORT
value: 5000
resources:
requests:
memoryInGB: 1.0
cpu: 1.0
limits:
memoryInGB: 1.0
cpu: 1.0
ipAddress:
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
type: Public
dnsNameLabel: my-app
osType: Linux
volumes:
- name: proxy-caddyfile
azureFile:
shareName: proxy-caddyfile
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
- name: proxy-data
azureFile:
shareName: proxy-data
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
- name: proxy-config
azureFile:
shareName: proxy-config
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
Déployer le groupe de conteneurs
Créez un groupe de ressources avec la commande az group create :
az group create --name <resource-group> --location westeurope
Déployez le groupe de conteneurs avec la commande az container create, en transmettant le fichier YAML en tant qu’argument.
az container create --resource-group <resource-group> --file ci-my-app.yaml
Visualiser l’état du déploiement
Pour afficher l’état du déploiement, utilisez la commande az container show suivante :
az container show --resource-group <resource-group> --name ci-my-app --output table
Vérifier la connexion TLS
Avant de vérifier si tout s’est bien passé, donnez au groupe de conteneurs le temps de démarrer complètement et à Caddy de demander un certificat.
OpenSSL
Nous pouvons utiliser la s_client
sous-commande d’OpenSSL à cet effet.
echo "Q" | openssl s_client -connect my-app.westeurope.azurecontainer.io:443
CONNECTED(00000188)
---
Certificate chain
0 s:CN = my-app.westeurope.azurecontainer.io
i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEgTCCA2mgAwIBAgISAxxidSnpH4vVuCZk9UNG/pd2MA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMzA0MDYxODAzMzNaFw0yMzA3MDUxODAzMzJaMC4xLDAqBgNVBAMT
I215LWFwcC53ZXN0ZXVyb3BlLmF6dXJlY29udGFpbmVyLmlvMFkwEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAEaaN/wGyFcimM+1O4WzbFgO6vIlXxXqp9vgmLZHpFrNwV
aO8JbaB7hE+M5EAg34LDY80RyHgY+Ff4vTh2Z96rVqOCAl4wggJaMA4GA1UdDwEB
/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/
BAIwADAdBgNVHQ4EFgQUoL5DP+4PWiyE79hL5o+v8uymHdAwHwYDVR0jBBgwFoAU
FC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzAB
hhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5p
LmxlbmNyLm9yZy8wLgYDVR0RBCcwJYIjbXktYXBwLndlc3RldXJvcGUuYXp1cmVj
b250YWluZXIuaW8wTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEw
KDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEEBgor
BgEEAdZ5AgQCBIH1BIHyAPAAdgC3Pvsk35xNunXyOcW6WPRsXfxCz3qfNcSeHQmB
Je20mQAAAYdX8+CQAAAEAwBHMEUCIQC9Ztqd3DXoJhOIHBW+P7ketGrKlVA6nPZl
9CiOrn6t8gIgXHcrbBqItemndRMv+UJ3DaBfTkYOqECecOJCgLhSYNUAdgDoPtDa
PvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAYdX8+CAAAAEAwBHMEUCIBJ1
24z44vKFUOLCi1a7ymVuWErkmLb/GtysvcxILaj0AiEAr49hyKfen4BbSTwC8Fg4
/LgZnn2F3uHI+9p+ZMO9xTAwDQYJKoZIhvcNAQELBQADggEBACqxa21eiW3JrZwk
FHgpd6SxhUeecrYXxFNva1Y6G//q2qCmGeKK3GK+ZGPqDtcoASH5t5ghV4dIT4WU
auVDLFVywXzR8PT6QUu3W8QxU+W7406twBf23qMIgrF8PIWhStI5mn1uCpeqlnf5
HpRaj2f5/5n19pcCZcrRx94G9qhPYdMzuy4mZRhxXRqrpIsabqX3DC2ld8dszCvD
pkV61iuARgm3MIQz1yL/x5Bn4nywjnhYZA4KFktC0Ti55cPRh1mkzGQAsYQDdWrq
dVav+U9dOLQ4Sq4suaDmzDzApr+hpQSJhwgRN16+tLMyZ6INAU2JWKDxiyDTdOuH
jz456og=
-----END CERTIFICATE-----
subject=CN = my-app.westeurope.azurecontainer.io
issuer=C = US, O = Let's Encrypt, CN = R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4208 bytes and written 401 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 256 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 20 (unable to get local issuer certificate)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
Session-ID: 85F1A4290F99A0DD28C8CB21EF4269E7016CC5D23485080999A8548057729B24
Session-ID-ctx:
Resumption PSK: 752D438C19A5DBDBF10781F863D5E5D9A8859230968A9EAFFF7BBA86937D004F
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 604800 (seconds)
TLS session ticket:
0000 - 2f 25 98 90 9d 46 9b 01-03 78 db bd 4d 64 b3 a6 /%...F...x..Md..
0010 - 52 c0 7a 8a b6 3d b8 4b-c0 d7 fc 04 e8 63 d4 bb R.z..=.K.....c..
0020 - 15 b3 25 b7 be 64 3d 30-2b d7 dc 7a 1a d1 22 63 ..%..d=0+..z.."c
0030 - 42 30 90 65 6b b5 e1 83-a3 6c 76 c8 f6 ae e9 31 B0.ek....lv....1
0040 - 45 91 33 57 8e 9f 4b 6a-2e 2c 9b f9 87 5f 71 1d E.3W..Kj.,..._q.
0050 - 5a 84 59 50 17 31 1f 62-2b 0e 1e e5 70 03 d9 e9 Z.YP.1.b+...p...
0060 - 50 1c 5d 1f a4 3c 8a 0e-f4 c5 7d ce 9e 5c 98 de P.]..<....}..\..
0070 - e5 .
Start Time: 1680808973
Timeout : 7200 (sec)
Verify return code: 20 (unable to get local issuer certificate)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
Navigateur Chrome
Accédez à https://my-app.westeurope.azurecontainer.io
et vérifiez le certificat en cliquant sur le cadenas en regard de l’URL.
Pour voir les détails du certificat, sélectionnez « La connexion est sécurisée » suivi de « le certificat est valide ».