Impossibile configurare l'endpoint HTTPS per .net Core Kestral Server nel contenitore Linux in Azure

Oct 28 2020

Ho un'app .net core 3 in esecuzione localmente / sviluppo perfettamente, sia da sola che quando viene eseguita in un contenitore Linux. Quindi prendo l'app e la faccio incorporare in un'immagine finestra mobile all'interno di pipeline azzurre. L'immagine viene caricata nel registro contenitori di Azure.

Infine, ho un'APP Web di Azure per contenitori (Linux) che utilizza l'immagine per l'esecuzione.

A livello locale ho il file docker-compose impostato in questo modo:

    environment:
      - "ASPNETCORE_ENVIRONMENT=Development"
      ...
      - "ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx"
      - "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
    volumes:
      - ~/.aspnet/https:/https:ro

Per la produzione ho quanto segue:

    environment:
      - UseInMemoryDatabase=false
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.pfx
      - "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
    ports:
      - "5000:5000"
      - "5001:5001"
    volumes:
       - fsmount001: /security:/security
       - /var/ssl/private:/https

Ho caricato "mycert" nel portale di Azure e ho aggiunto la sua identificazione personale alle impostazioni di configurazione dell'app in WEBSITE_LOAD_CERTIFICATES

Ho usato Open SSL per creare il file mycert e posso usarlo localmente e kestral lo userà, ma con un avviso.

IL PROBLEMA

Quando eseguo l'app con questa immagine, ottengo il seguente errore nei log del docker:

System.InvalidOperationException: impossibile configurare l'endpoint HTTPS. Non è stato specificato alcun certificato del server e il certificato dello sviluppatore predefinito non è stato trovato o non è aggiornato ... in Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps (ListenOptions listenOptions, Action`1 configureOptions)

Ho provato molte varianti di caricamento dei certificati e non riesco a far funzionare nessuna di esse. Questo è un problema che si verifica solo in produzione.

Ho anche provato:

  1. Acquistato un certificato per app Azure e utilizzato il file thumbprint.p12 come:
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/var/ssl/private/<thumbprint>.p12
      - ASPNETCORE_Kestrel__Certificates__Default__Password=""

Non ho usato password perché quando acquisti un certificato non è impostata alcuna password

  1. Scaricato l'App Cert acquistato e utilizzato open ssl per creare un file .pfk collegato alla password e caricato come un'altra chiave privata

  2. Usa il montaggio del file azure e carica i miei file dev cert e fai riferimento ad essi dal montaggio del file come:

      - ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.com.pfx
      - ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
    volumes:
       - fsmount001: /security:/security

EDIT 1: configurazione completa dei file docker-compose e azure

  1. Ecco come ho definito la mia condivisione di file:

C'è una cartella di sicurezza con il file mycert.pfx al suo interno

  1. Ecco come impostare il montaggio del file nella configurazione del servizio app di Azure:

Ho impostato il percorso di montaggio come cartella di sicurezza nella mia condivisione di file

  1. Ecco il file di composizione della finestra mobile completa:
services:
  webui:
    image: ${DOCKER_REGISTRY-}webui
    build:
      context: .
      dockerfile: src/WebUI/Dockerfile
    environment:
      - UseInMemoryDatabase=false
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - "ConnectionStrings__DefaultConnection=****"
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/secure/mycert.pfx
      - ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
    ports:
      - "5000:5000"
      - "5001:5001"
    volumes:
       - fsmount001: /secure
       - ~/var/ssl/private:/https
    restart: always

volumes:
  fsmount001:
    driver: azure_file
    driver_opts:
      share_name: st-*****tus
      storage_account_name: st********001

MODIFICA 2: DOCKERFILE

per ulteriore contesto puoi trovare il mio dockerfile di seguito

tieni presente che sto utilizzando il modello di applicazione open source / framework cleanarchiecture. Puoi vedere che sto cercando di utilizzare la richiesta pull docker per il repository come codice di base. Il mio obiettivo è "dockerize" questo framework di base in azure ci / cd pipeline e distribuirlo nell'app Web azure per contenitori (linux)


FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
ENV ASPNETCORE_URLS=https://+:5001;http://+:5000

WORKDIR /app
EXPOSE 5000 5001 2222

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt install -y nodejs
WORKDIR /src
COPY ["src/WebUI/WebUI.csproj", "src/WebUI/"]
COPY ["src/Application/Application.csproj", "src/Application/"]
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
RUN dotnet restore "src/WebUI/WebUI.csproj"
COPY . .
WORKDIR "/src/src/WebUI"
RUN dotnet build "WebUI.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebUI.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]

Qualcuno può aiutarmi a capire come impostare un certificato per kestral all'interno di un contenitore Linux?

Grazie in anticipo

Risposte

2 jccampanero Nov 02 2020 at 02:39

È possibile che il tuo docker-composefile contenga un errore nella definizione del servizio volumes?

Hai il seguente docker-composeframmento per il tuo servizio:

    environment:
      - UseInMemoryDatabase=false
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.pfx
      - "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
    ports:
      - "5000:5000"
      - "5001:5001"
    volumes:
       - fsmount001: /security:/security
       - /var/ssl/private:/https

Con questa configurazione stai tentando di creare due volumi.

Da un lato, stai mappando il /var/ssl/privatepercorso nel sistema host alla /httpsdestinazione del contenitore. Dovrebbe funzionare bene.

Ma, d'altra parte, penso che tu stia mescolando la sintassi per volumi e volumi con nome in base alla mappatura del percorso.

Per il tuo aggiornamento stai tentando di usare un montaggio di archiviazione file di Azure. Quindi è necessario modificare la volumesdefinizione del servizio come segue:

    environment:
      ...
    ports:
      ...
    volumes:
       - fsmount001:/security
       - /var/ssl/private:/https

Come indicato nella documentazione , è importante capire che il percorso di montaggio corrisponde alla cartella all'interno del contenitore che si vuole montare su Archiviazione di Azure:

L'impostazione del percorso di montaggio corrisponde alla cartella all'interno del contenitore che si desidera montare in Archiviazione di Azure. Impostandolo su "/" si monta l'intero contenitore in Archiviazione di Azure.

Nota anche che il percorso fornito fsmount001nel tuo docker-composefile è lo stesso del percorso di montaggio indicato quando hai creato il montaggio, /securityin questo caso.

Con questa configurazione, è necessario configurare la posizione del certificato in questo modo:

- ASPNETCORE_Kestrel__Certificates__Default__Path=/security/security/mycert.pfx

Il primo /securityper il percorso nel contenitore e il secondo per la directory in cui il tuo pfx è incluso nella condivisione file.

AGGIORNARE

Dopo aver esaminato i tuoi file Dockerfilee docker-composeinsieme, penso che il tuo problema potrebbe essere motivato non per l'effettiva condivisione di file, ma perché le variabili di ambiente richieste per configurare il tuo HTTPS non sono visibili all'interno del contenitore docker perché vengono utilizzate solo nella sua fase di costruzione. Per favore, guarda questa domanda relativa all'overflow dello stack.

È necessario fornire queste informazioni sull'ambiente direttamente Dockerfileo indirettamente utilizzando ARGs nel docker-composefile.

Ad esempio, modifica il tuo docker-composefile come segue: in pratica, cambia la tua environmentvoce per args:

services:
  webui:
    image: ${DOCKER_REGISTRY-}webui
    build:
      context: .
      dockerfile: src/WebUI/Dockerfile
    args:
      - UseInMemoryDatabase=false
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ConnectionStrings__DefaultConnection=****
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/secure/mycert.pfx
      - ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
    ports:
      - "5000:5000"
      - "5001:5001"
    volumes:
       - fsmount001: /secure
       - ~/var/ssl/private:/https
    restart: always

volumes:
  fsmount001:
    driver: azure_file
    driver_opts:
      share_name: st-*****tus
      storage_account_name: st********001

E modificano il tuo Dockerfileper leggere gli argomenti di build forniti:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base

ARG UseInMemoryDatabase
ENV UseInMemoryDatabase=$UseInMemoryDatabase

ARG ASPNETCORE_ENVIRONMENT
ENV ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT ARG ASPNETCORE_URLS=https://+:5001;http://+:5000 ENV ASPNETCORE_URLS=$ASPNETCORE_URLS

ARG ConnectionStrings__DefaultConnection
ENV ConnectionStrings__DefaultConnection=$ConnectionStrings__DefaultConnection ARG ASPNETCORE_Kestrel__Certificates__Default__Path ENV ASPNETCORE_Kestrel__Certificates__Default__Path=$ASPNETCORE_Kestrel__Certificates__Default__Path

ARG ASPNETCORE_Kestrel__Certificates__Default__Password
ENV ASPNETCORE_Kestrel__Certificates__Default__Password=$ASPNETCORE_Kestrel__Certificates__Default__Password

WORKDIR /app
EXPOSE 5000 5001 2222

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt install -y nodejs
WORKDIR /src
COPY ["src/WebUI/WebUI.csproj", "src/WebUI/"]
COPY ["src/Application/Application.csproj", "src/Application/"]
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
RUN dotnet restore "src/WebUI/WebUI.csproj"
COPY . .
WORKDIR "/src/src/WebUI"
RUN dotnet build "WebUI.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebUI.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]

Per favore, modificalo come ritieni appropriato. Prestare attenzione soprattutto nel momento in cui i diversi ARGs ed ENVe dovrebbero essere definiti perché hanno l'ambito per fase di compilazione e non verranno conservati nella fase successiva. Puoi provare così com'è, oppure puoi definire ARGs in basee ENVs in final, poiché una si estende dall'altra le ARGvariabili s dovrebbero essere visibili in entrambi.