Ativar HTTPS automático com Caddy em um contêiner de sidecar
Este artigo descreve como o Caddy pode ser usado como um contêiner sidecar em um grupo de contêineres e agir como um proxy reverso para fornecer um ponto de extremidade HTTPS gerenciado automaticamente para seu aplicativo.
O Caddy é um servidor web poderoso, pronto para empresas e de código aberto com HTTPS automático escrito em Go e representa uma alternativa ao Nginx.
A automatização de certificados é possível porque o Caddy suporta a API ACMEv2 (RFC 8555) que interage com o Let's Encrypt para emitir certificados.
Neste exemplo, apenas o contêiner Caddy fica exposto nas portas 80/TCP e 443/TCP. O aplicativo por trás do proxy reverso permanece privado. A comunicação de rede entre o Caddy e seu aplicativo acontece via localhost.
Nota
Isso contrasta com a comunicação intra grupo de contêineres conhecida do docker compose, onde os contêineres podem ser referenciados pelo nome.
O exemplo monta o Caddyfile, que é necessário para configurar o proxy reverso, a partir de um compartilhamento de arquivos hospedado em uma conta de Armazenamento do Azure.
Nota
Para implantações de produção, a maioria dos usuários desejará transformar o Caddyfile em uma imagem docker personalizada com base no caddy. Dessa forma, não há necessidade de montar arquivos no contêiner.
Pré-requisitos
Use o ambiente Bash no Azure Cloud Shell. Para obter mais informações, consulte Guia de início rápido para Bash no Azure Cloud Shell.
Se preferir executar comandos de referência da CLI localmente, instale a CLI do Azure. Se estiver a utilizar o Windows ou macOS, considere executar a CLI do Azure num contentor Docker. Para obter mais informações, consulte Como executar a CLI do Azure em um contêiner do Docker.
Se estiver a utilizar uma instalação local, inicie sessão no CLI do Azure ao utilizar o comando az login. Para concluir o processo de autenticação, siga os passos apresentados no seu terminal. Para outras opções de entrada, consulte Entrar com a CLI do Azure.
Quando solicitado, instale a extensão da CLI do Azure na primeira utilização. Para obter mais informações sobre as extensões, veja Utilizar extensões com o CLI do Azure.
Execute o comando az version para localizar a versão e as bibliotecas dependentes instaladas. Para atualizar para a versão mais recente, execute o comando az upgrade.
- Este artigo requer a versão 2.0.55 ou posterior da CLI do Azure. Se estiver usando o Azure Cloud Shell, a versão mais recente já está instalada.
Preparar o Caddyfile
Crie um arquivo chamado Caddyfile
e cole a seguinte configuração. Essa configuração cria uma configuração de proxy reverso, apontando para o contêiner do aplicativo escutando em 5000/TCP.
my-app.westeurope.azurecontainer.io {
reverse_proxy http://localhost:5000
}
É importante notar que a configuração faz referência a um nome de domínio em vez de um endereço IP. O Caddy precisa estar acessível por essa URL para executar a etapa de desafio exigida pelo protocolo ACME e recuperar com sucesso um certificado do Let's Encrypt.
Nota
Para implantação de produção, os usuários podem querer usar um nome de domínio que controlam, por exemplo, e criar um registro CNAME apontando para, por exemplo, api.company.com
my-app.westeurope.azurecontainer.io
. Em caso afirmativo, é necessário garantir que o nome de domínio personalizado também seja usado no Caddyfile, em vez do atribuído pelo Azure (por exemplo, *.westeurope.azurecontainer.io
). Além disso, o nome de domínio personalizado precisa ser referenciado na configuração ACI YAML descrita posteriormente neste exemplo.
Preparar conta de armazenamento
Criar uma conta de armazenamento
az storage account create \
--name <storage-account> \
--resource-group <resource-group> \
--location westeurope
Armazenar a cadeia de conexão em uma variável de ambiente
AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string --name <storage-account> --resource-group <resource-group> --output tsv)
Crie os compartilhamentos de arquivos necessários para armazenar o estado do contêiner e a configuração 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>
Recupere as chaves da conta de armazenamento e anote para uso posterior
az storage account keys list -g <resource-group> -n <storage-account>
Implantar grupo de contêineres
Criar arquivo YAML
Crie um arquivo chamado ci-my-app.yaml
e cole o seguinte conteúdo. Certifique-se de substituir <account-key>
por uma das chaves de acesso recebidas anteriormente e <storage-account>
de acordo.
Este arquivo YAML define dois contêineres reverse-proxy
e my-app
. O reverse-proxy
contêiner monta os três compartilhamentos de arquivos criados anteriormente. A configuração também expõe as portas 80/TCP e 443/TCP do reverse-proxy
contêiner. A comunicação entre ambos os contêineres acontece apenas no localhost.
Nota
É importante notar que a dnsNameLabel
chave define o nome DNS público, sob o qual o grupo de instâncias do contêiner será acessível, ele precisa corresponder ao FQDN definido no Caddyfile
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>"
Implantar o grupo de contêineres
Crie um grupo de recursos com o comando az group create :
az group create --name <resource-group> --location westeurope
Implante o grupo de contêineres com o comando az container create , passando o arquivo YAML como um argumento.
az container create --resource-group <resource-group> --file ci-my-app.yaml
Exibir o estado de implantação
Para exibir o estado da implantação, use o seguinte comando az container show :
az container show --resource-group <resource-group> --name ci-my-app --output table
Verificar a conexão TLS
Antes de verificar se tudo correu bem, dê algum tempo ao grupo de contentores para começar totalmente e para que o Caddy solicite um certificado.
OpenSSL
Podemos usar o s_client
subcomando do OpenSSL para esse fim.
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
Navegador Chrome
Navegue até o https://my-app.westeurope.azurecontainer.io
certificado e verifique-o clicando no cadeado ao lado do URL.
Para ver os detalhes do certificado, selecione "A conexão é segura" seguida de "O certificado é válido".