Abilitare un endpoint TLS in un contenitore sidecar

Questo articolo illustra come creare un gruppo di contenitori con un contenitore dell'applicazione e un contenitore sidecar che esegue un provider TLS/SSL. Configurando un gruppo di contenitori con un endpoint TLS separato, si abilitano le connessioni TLS per l'applicazione senza modificare il codice dell'applicazione.

Si configura un gruppo di contenitori di esempio costituito da due contenitori:

  • Contenitore di applicazioni che esegue una semplice app Web usando l'immagine microsoft aci-helloworld pubblica.
  • Contenitore sidecar che esegue l'immagine Nginx pubblica, configurata per l'uso di TLS.

In questo esempio, il gruppo di contenitori espone solo la porta 443 per Nginx con il relativo indirizzo IP pubblico. Nginx instrada le richieste HTTPS all'app Web complementare, in ascolto internamente sulla porta 80. È possibile adattare l'esempio per le applicazioni contenitore in ascolto su altre porte.

Vedere Passaggi successivi per altri approcci all'abilitazione di TLS in un gruppo di contenitori.

Prerequisiti

  • Questo articolo richiede la versione 2.0.55 o successiva dell'interfaccia della riga di comando di Azure. Se si usa Azure Cloud Shell, la versione più recente è già installata.

Creare un certificato autofirmato

Per configurare Nginx come provider TLS, è necessario un certificato TLS/SSL. Questo articolo illustra come creare e configurare un certificato TLS/SSL autofirmato. Per gli scenari di produzione, è necessario ottenere un certificato da un'autorità di certificazione.

Per creare un certificato TLS/SSL autofirmato, usare lo strumento OpenSSL disponibile in Azure Cloud Shell e molte distribuzioni Linux oppure usare uno strumento client paragonabile nel sistema operativo.

Creare prima una richiesta di certificato (file .csr) in una directory di lavoro locale:

openssl req -new -newkey rsa:2048 -nodes -keyout ssl.key -out ssl.csr

Seguire le istruzioni per aggiungere le informazioni di identificazione. In Nome comune immettere il nome host associato al certificato. Quando viene richiesta una password, premere INVIO senza digitare per ignorare l'aggiunta di una password.

Eseguire il comando seguente per creare il certificato autofirmato (file con estensione crt) dalla richiesta di certificato. Ad esempio:

openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt

Nella directory dovrebbero essere visualizzati tre file: la richiesta di certificato (ssl.csr), la chiave privata (ssl.key) e il certificato autofirmato (ssl.crt). Si usano ssl.key e ssl.crt nei passaggi successivi.

Configurare Nginx per l'uso di TLS

Creare un file di configurazione Nginx

In questa sezione viene creato un file di configurazione per Nginx per l'uso di TLS. Per iniziare, copiare il testo seguente in un nuovo file denominato nginx.conf. In Azure Cloud Shell è possibile usare Visual Studio Code per creare il file nella directory di lavoro:

code nginx.conf

In locationassicurarsi di impostare proxy_pass con la porta corretta per l'app. In questo esempio viene impostata la porta 80 per il aci-helloworld contenitore.

# nginx Configuration File
# https://wiki.nginx.org/Configuration

# Run as a less privileged user for security reasons.
user nginx;

worker_processes auto;

events {
  worker_connections 1024;
}

pid        /var/run/nginx.pid;

http {

    #Redirect to https, using 307 instead of 301 to preserve post data

    server {
        listen [::]:443 ssl;
        listen 443 ssl;

        server_name localhost;

        # Protect against the BEAST attack by not using SSLv3 at all. If you need to support older browsers (IE6) you may need to add
        # SSLv3 to the list of protocols below.
        ssl_protocols              TLSv1.2;

        # Ciphers set to best allow protection from Beast, while providing forwarding secrecy, as defined by Mozilla - https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx
        ssl_ciphers                ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK;
        ssl_prefer_server_ciphers  on;

        # Optimize TLS/SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive TLS/SSL handshakes.
        # The handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connection.
        # By enabling a cache (of type "shared between all Nginx workers"), we tell the client to re-use the already negotiated state.
        # Further optimization can be achieved by raising keepalive_timeout, but that shouldn't be done unless you serve primarily HTTPS.
        ssl_session_cache    shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions
        ssl_session_timeout  24h;


        # Use a higher keepalive timeout to reduce the need for repeated handshakes
        keepalive_timeout 300; # up from 75 secs default

        # remember the certificate for a year and automatically connect to HTTPS
        add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';

        ssl_certificate      /etc/nginx/ssl.crt;
        ssl_certificate_key  /etc/nginx/ssl.key;

        location / {
            proxy_pass http://localhost:80; # TODO: replace port if app listens on port other than 80

            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
}

File di configurazione e segreti con codifica Base64

Codifica Base64 del file di configurazione Nginx, del certificato TLS/SSL e della chiave TLS. Nella sezione successiva immettere il contenuto codificato in un file YAML usato per distribuire il gruppo di contenitori.

cat nginx.conf | base64 > base64-nginx.conf
cat ssl.crt | base64 > base64-ssl.crt
cat ssl.key | base64 > base64-ssl.key

Distribuire un gruppo di contenitori

Distribuire ora il gruppo di contenitori specificando le configurazioni del contenitore in un file YAML.

Creare un file YAML

Copiare il codice YAML seguente in un nuovo file denominato deploy-aci.yaml. In Azure Cloud Shell è possibile usare Visual Studio Code per creare il file nella directory di lavoro:

code deploy-aci.yaml

Immettere il contenuto dei file con codifica Base64, dove indicato in secret. Ad esempio, cat ognuno dei file con codifica Base64 per visualizzarne il contenuto. Durante la distribuzione, questi file vengono aggiunti a un volume segreto nel gruppo di contenitori. In questo esempio il volume segreto viene montato nel contenitore Nginx.

api-version: 2019-12-01
location: westus
name: app-with-ssl
properties:
  containers:
  - name: nginx-with-ssl
    properties:
      image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
      ports:
      - port: 443
        protocol: TCP
      resources:
        requests:
          cpu: 1.0
          memoryInGB: 1.5
      volumeMounts:
      - name: nginx-config
        mountPath: /etc/nginx
  - name: my-app
    properties:
      image: mcr.microsoft.com/azuredocs/aci-helloworld
      ports:
      - port: 80
        protocol: TCP
      resources:
        requests:
          cpu: 1.0
          memoryInGB: 1.5
  volumes:
  - secret:
      ssl.crt: <Enter contents of base64-ssl.crt here>
      ssl.key: <Enter contents of base64-ssl.key here>
      nginx.conf: <Enter contents of base64-nginx.conf here>
    name: nginx-config
  ipAddress:
    ports:
    - port: 443
      protocol: TCP
    type: Public
  osType: Linux
tags: null
type: Microsoft.ContainerInstance/containerGroups

Distribuire il gruppo di contenitori

Creare un gruppo di risorse con il comando az group create:

az group create --name myResourceGroup --location westus

Distribuire il gruppo di contenitori con il comando az container create , passando il file YAML come argomento.

az container create --resource-group <myResourceGroup> --file deploy-aci.yaml

Visualizzare lo stato della distribuzione

Per visualizzare lo stato della distribuzione, usare il comando az container show seguente:

az container show --resource-group <myResourceGroup> --name app-with-ssl --output table

Per una distribuzione corretta, l'output è simile al seguente:

Name          ResourceGroup    Status    Image                                                    IP:ports             Network    CPU/Memory       OsType    Location
------------  ---------------  --------  -------------------------------------------------------  -------------------  ---------  ---------------  --------  ----------
app-with-ssl  myresourcegroup  Running   nginx, mcr.microsoft.com/azuredocs/aci-helloworld        52.157.22.76:443     Public     1.0 core/1.5 gb  Linux     westus

Verificare la connessione TLS

Usare il browser per passare all'indirizzo IP pubblico del gruppo di contenitori. L'indirizzo IP illustrato in questo esempio è 52.157.22.76, quindi l'URL è https://52.157.22.76. È necessario usare HTTPS per visualizzare l'applicazione in esecuzione, a causa della configurazione del server Nginx. I tentativi di connessione tramite HTTP hanno esito negativo.

Screenshot del browser che mostra l'applicazione in esecuzione in un'istanza di contenitore di Azure

Nota

Poiché questo esempio usa un certificato autofirmato e non uno da un'autorità di certificazione, nel browser viene visualizzato un avviso di sicurezza durante la connessione al sito tramite HTTPS. Potrebbe essere necessario accettare l'avviso o modificare le impostazioni del browser o del certificato per passare alla pagina. Si tratta di un comportamento previsto.

Passaggi successivi

Questo articolo ha illustrato come configurare un contenitore Nginx per abilitare le connessioni TLS a un'app Web in esecuzione nel gruppo di contenitori. È possibile adattare questo esempio per le app in ascolto su porte diverse dalla porta 80. È anche possibile aggiornare il file di configurazione Nginx per reindirizzare automaticamente le connessioni server sulla porta 80 (HTTP) per usare HTTPS.

Anche se questo articolo usa Nginx nel sidecar, è possibile usare un altro provider TLS, ad esempio Caddy.

Se si distribuisce il gruppo di contenitori in una rete virtuale di Azure, è possibile prendere in considerazione altre opzioni per abilitare un endpoint TLS per un'istanza del contenitore back-end, tra cui: