Självstudie: Skapa en säker n-nivåapp i Azure App Service

Många program har mer än en enda komponent. Du kan till exempel ha en klientdel som är offentligt tillgänglig och ansluter till ett serverdels-API eller en webbapp som i sin tur ansluter till en databas, ett lagringskonto, ett nyckelvalv, en annan virtuell dator eller en kombination av dessa resurser. Den här arkitekturen utgör ett N-nivåprogram. Det är viktigt att program som detta utformas för att skydda serverdelsresurser i största möjliga utsträckning.

I den här självstudien får du lära dig hur du distribuerar ett säkert N-nivåprogram med en klientwebbapp som ansluter till en annan nätverksisolerad webbapp. All trafik isoleras i ditt virtuella Azure-nätverk med integrering av virtuella nätverk och privata slutpunkter. Mer omfattande vägledning som innehåller andra scenarier finns i:

Scenariots arkitektur

Följande diagram visar den arkitektur som du skapar under den här självstudien.

Architecture diagram of an n-tier App Service.

  • Virtuellt nätverk Innehåller två undernät, ett är integrerat med klientdelswebbappen och det andra har en privat slutpunkt för serverdelswebbappen. Det virtuella nätverket blockerar all inkommande nätverkstrafik, förutom klientdelsappen som är integrerad med den.
  • Klientwebbappen integrerad i det virtuella nätverket och tillgänglig från det offentliga Internet.
  • ServerdelswebbappEn är endast tillgänglig via den privata slutpunkten i det virtuella nätverket.
  • Privat slutpunkt Integreras med serverdelswebbappen och gör webbappen tillgänglig med en privat IP-adress.
  • Privat DNS zon Gör att du kan matcha ett DNS-namn till den privata slutpunktens IP-adress.

Kommentar

Integrering av virtuella nätverk och privata slutpunkter är tillgängliga hela vägen ned till Basic-nivån i App Service. Den kostnadsfria nivån stöder inte dessa funktioner. Med den här arkitekturen:

  • Offentlig trafik till serverdelsappen blockeras.
  • Utgående trafik från App Service dirigeras till det virtuella nätverket och kan nå serverdelsappen.
  • App Service kan utföra DNS-matchning till serverdelsappen.

Det här scenariot visar ett av de möjliga N-nivåscenarierna i App Service. Du kan använda de begrepp som beskrivs i den här självstudien för att skapa mer komplexa N-nivåappar.

Detta får du får lära dig:

  • Skapa ett virtuellt nätverk och undernät för integrering av virtuella App Service-nätverk.
  • Skapa privata DNS-zoner.
  • Skapa privata slutpunkter.
  • Konfigurera integrering av virtuella nätverk i App Service.
  • Inaktivera grundläggande autentisering i App Service.
  • Distribuera kontinuerligt till en låst serverdelswebbapp.

Förutsättningar

Självstudien använder två exempel Node.js appar som finns på GitHub. Om du inte redan har ett GitHub-konto skapar du ett konto kostnadsfritt.

Om du inte har en Azure-prenumeration skapar du ett kostnadsfritt Azure-konto innan du börjar.

För att slutföra den här kursen behöver du:

1. Skapa två instanser av en webbapp

Du behöver två instanser av en webbapp, en för klientdelen och en för serverdelen. Du måste använda minst Basic-nivån för att kunna använda integrering av virtuella nätverk och privata slutpunkter. Du konfigurerar integreringen av det virtuella nätverket och andra konfigurationer senare.

  1. Skapa en resursgrupp för att hantera alla resurser som du skapar i den här självstudien.

    # Save resource group name and region as variables for convenience
    groupName=myresourcegroup
    region=eastus
    az group create --name $groupName --location $region
    
  2. Skapa en App Service-plan. Ersätt <app-service-plan-name> med ett unikt namn. Ändra parametern --sku om du behöver använda en annan SKU. Se till att du inte använder den kostnadsfria nivån eftersom den SKU:n inte stöder de nätverksfunktioner som krävs.

    # Save App Service plan name as a variable for convenience
    aspName=<app-service-plan-name>
    az appservice plan create --name $aspName --resource-group $groupName --is-linux --location $region --sku P1V3
    
  3. Skapa webbapparna. Ersätt <frontend-app-name> och <backend-app-name> med två globalt unika namn (giltiga tecken är a-z, 0-9och -). I den här självstudien får du exempel på Node.js appar. Om du vill använda dina egna appar ändrar du parametern i enlighet med detta --runtime . Kör az webapp list-runtimes för listan över tillgängliga körningar.

    az webapp create --name <frontend-app-name> --resource-group $groupName --plan $aspName --runtime "NODE:18-lts"
    az webapp create --name <backend-app-name> --resource-group $groupName --plan $aspName --runtime "NODE:18-lts"
    

2. Skapa nätverksinfrastruktur

Du skapar följande nätverksresurser:

  • Ett virtuellt nätverk.
  • Ett undernät för integrering av det virtuella nätverket i App Service.
  • Ett undernät för den privata slutpunkten.
  • En privat DNS-zon.
  • En privat slutpunkt.
  1. Skapa ett virtuellt nätverk. Ersätt <virtual-network-name> med ett unikt namn.

    # Save vnet name as variable for convenience
    vnetName=<virtual-network-name>
    az network vnet create --resource-group $groupName --location $region --name $vnetName --address-prefixes 10.0.0.0/16
    
  2. Skapa ett undernät för integreringen av det virtuella Nätverket i App Service.

    az network vnet subnet create --resource-group $groupName --vnet-name $vnetName --name vnet-integration-subnet --address-prefixes 10.0.0.0/24 --delegations Microsoft.Web/serverfarms --disable-private-endpoint-network-policies false
    

    För App Service rekommenderar vi att det virtuella nätverksintegreringsundernätet har ett CIDR-block /26 på minst. /24 är mer än tillräckligt. --delegations Microsoft.Web/serverfarms anger att undernätet är delegerat för integrering av virtuella App Service-nätverk.

  3. Skapa ett annat undernät för de privata slutpunkterna.

    az network vnet subnet create --resource-group $groupName --vnet-name $vnetName --name private-endpoint-subnet --address-prefixes 10.0.1.0/24 --disable-private-endpoint-network-policies true
    

    För privata slutpunktsundernät måste du inaktivera nätverksprinciper för privata slutpunkter genom att ange --disable-private-endpoint-network-policies till true.

  4. Skapa den privata DNS-zonen.

    az network private-dns zone create --resource-group $groupName --name privatelink.azurewebsites.net
    

    Mer information om de här inställningarna finns i DNS-konfiguration för privata slutpunkter i Azure.

    Kommentar

    Om du skapar den privata slutpunkten med hjälp av portalen skapas en privat DNS-zon automatiskt åt dig och du behöver inte skapa den separat. För att få konsekvens med den här självstudien skapar du den privata DNS-zonen och den privata slutpunkten separat med hjälp av Azure CLI.

  5. Länka den privata DNS-zonen till det virtuella nätverket.

    az network private-dns link vnet create --resource-group $groupName --name myDnsLink --zone-name privatelink.azurewebsites.net --virtual-network $vnetName --registration-enabled False
    
  6. Skapa en privat slutpunkt för serverdelswebbappen i det privata undernätet för det virtuella nätverket. Ersätt <backend-app-name> med namnet på serverdelswebbappen.

    # Get backend web app resource ID
    resourceId=$(az webapp show --resource-group $groupName --name <backend-app-name> --query id --output tsv)
    az network private-endpoint create --resource-group $groupName --name myPrivateEndpoint --location $region --connection-name myConnection --private-connection-resource-id $resourceId --group-id sites --vnet-name $vnetName --subnet private-endpoint-subnet
    
  7. Länka den privata slutpunkten till den privata DNS-zonen med en DNS-zongrupp för den privata serverdelswebbappens privata slutpunkt. Den här DNS-zongruppen hjälper dig att automatiskt uppdatera den privata DNS-zonen när det finns en uppdatering av den privata slutpunkten.

    az network private-endpoint dns-zone-group create --resource-group $groupName --endpoint-name myPrivateEndpoint --name myZoneGroup --private-dns-zone privatelink.azurewebsites.net --zone-name privatelink.azurewebsites.net
    
  8. När du skapar en privat slutpunkt för en App Service inaktiveras den offentliga åtkomsten implicit. Om du försöker komma åt serverdelswebbappen med dess standard-URL nekas din åtkomst. Från en webbläsare går du till för att <backend-app-name>.azurewebsites.net bekräfta det här beteendet.

    Screenshot of 403 error when trying to access backend web app directly.

    Mer information om åtkomstbegränsningar för App Service med privata slutpunkter finns i Åtkomstbegränsningar för Azure App Service.

3. Konfigurera integrering av virtuella nätverk i klientdelswebbappen

Aktivera integrering av virtuella nätverk i din app. Ersätt <frontend-app-name> med klientdelswebbappens namn.

az webapp vnet-integration add --resource-group $groupName --name <frontend-app-name> --vnet $vnetName --subnet vnet-integration-subnet

Med integrering av virtuella nätverk kan utgående trafik flöda direkt till det virtuella nätverket. Som standard dirigeras endast lokal IP-trafik som definieras i RFC-1918 till det virtuella nätverket, vilket är vad du behöver för de privata slutpunkterna. Information om hur du dirigerar all trafik till det virtuella nätverket finns i Hantera routning för integrering av virtuella nätverk. Routning av all trafik kan också användas om du vill dirigera Internettrafik via ditt virtuella nätverk, till exempel via en NAT för virtuellt Azure-nätverk eller en Azure-brandvägg.

4. Aktivera distribution till serverdelswebbapp från Internet

Eftersom serverdelswebbappen inte är offentligt tillgänglig måste du låta verktyget för kontinuerlig distribution nå din app genom att göra SCM-webbplatsen offentligt tillgänglig. Själva huvudwebbappen kan fortsätta att neka all trafik.

  1. Aktivera offentlig åtkomst för serverdelswebbappen.

    az webapp update --resource-group $groupName --name <backend-app-name> --set publicNetworkAccess=Enabled
    
  2. Ange den omatchade regelåtgärden för huvudwebbappen för att neka all trafik. Den här inställningen nekar offentlig åtkomst till huvudwebbappen även om den allmänna inställningen för appåtkomst är inställd på att tillåta offentlig åtkomst.

    az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Deny
    
  3. Ange den omatchade regelåtgärden för SCM-webbplatsen så att all trafik tillåts.

    az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.scmIpSecurityRestrictionsDefaultAction=Allow
    

5. Lås FTP- och SCM-åtkomst

Nu när SCM-webbplatsen för serverdelen är offentligt tillgänglig måste du låsa den med bättre säkerhet.

  1. Inaktivera FTP-åtkomst för både klient- och serverdelswebbappar. Ersätt <frontend-app-name> och <backend-app-name> med dina appnamn.

    az resource update --resource-group $groupName --name ftp --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<frontend-app-name> --set properties.allow=false
    az resource update --resource-group $groupName --name ftp --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<backend-app-name> --set properties.allow=false
    
  2. Inaktivera grundläggande autentiseringsåtkomst till WebDeploy-portarna och SCM/avancerade verktygswebbplatser för båda webbapparna. Ersätt <frontend-app-name> och <backend-app-name> med dina appnamn.

    az resource update --resource-group $groupName --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<frontend-app-name> --set properties.allow=false
    az resource update --resource-group $groupName --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/<backend-app-name> --set properties.allow=false
    

Om du inaktiverar grundläggande autentisering i App Service begränsas åtkomsten till FTP- och SCM-slutpunkterna till användare som backas upp av Microsoft Entra-ID, vilket ytterligare skyddar dina appar. Mer information om hur du inaktiverar grundläggande autentisering, inklusive hur du testar och övervakar inloggningar, finns i Inaktivera grundläggande autentisering i App Service.

6. Konfigurera kontinuerlig distribution med GitHub Actions

  1. Gå till exempelappen Node.js serverdel. Den här appen är en enkel Hello World-app.

  2. Välj knappen Förgrening längst upp till höger på GitHub-sidan.

  3. Välj Ägare och lämna standardnamnet för lagringsplatsen.

  4. Välj Skapa förgrening.

  5. Upprepa samma process för Node.js klientdelsexempelapp. Den här appen är en grundläggande webbapp som har åtkomst till en fjärr-URL.

  6. Skapa ett huvudnamn för tjänsten. Ersätt <subscription-id>, <frontend-app-name>och <backend-app-name> med dina värden.

    az ad sp create-for-rbac --name "myApp" --role contributor --scopes /subscriptions/<subscription-id>/resourceGroups/$groupName/providers/Microsoft.Web/sites/<frontend-app-name> /subscriptions/<subscription-id>/resourceGroups/$groupName/providers/Microsoft.Web/sites/<backend-app-name> --sdk-auth
    

    Utdata är ett JSON-objekt med autentiseringsuppgifterna för rolltilldelning som ger åtkomst till dina App Service-appar. Kopiera det här JSON-objektet för nästa steg. Den innehåller din klienthemlighet, som bara visas just nu. Det är alltid en bra idé att bevilja minsta möjliga åtkomst. Omfånget i det här exemplet är begränsat till bara apparna, inte hela resursgruppen.

  7. Om du vill lagra tjänstens huvudnamns autentiseringsuppgifter som GitHub-hemligheter går du till en av de förgrenade exempellagringsplatserna i GitHub och går till Inställningar> Säkerhetshemligheter>>och variabler Åtgärder.

  8. Välj Ny lagringsplatshemlighet och skapa en hemlighet för vart och ett av följande värden. Värdena finns i json-utdata som du kopierade tidigare.

    Name Värde
    AZURE_APP_ID <application/client-id>
    AZURE_PASSWORD <client-secret>
    AZURE_TENANT_ID <tenant-id>
    AZURE_SUBSCRIPTION_ID <subscription-id>
  9. Upprepa den här processen för den andra förgrenade exempellagringsplatsen.

  10. Om du vill konfigurera kontinuerlig distribution med GitHub Actions loggar du in på Azure-portalen.

  11. Gå till sidan Översikt för klientwebbappen.

  12. I den vänstra rutan väljer du Distributionscenter. Välj sedan Inställningar.

  13. I rutan Källa väljer du "GitHub" från CI/CD-alternativen.

    Screenshot that shows how to choose the deployment source.

  14. Om du distribuerar från GitHub för första gången väljer du Auktorisera och följer auktoriseringsanvisningarna. Om du vill distribuera från en annan användares lagringsplats väljer du Ändra konto.

  15. Om du använder den Node.js exempelapp som förgrenades som en del av förhandskraven använder du följande inställningar för Organisation, Lagringsplats och Gren.

    Inställning Värde
    Organisation <your-GitHub-organization>
    Lagringsplats nodejs-frontend
    Filial huvud-
  16. Välj Spara.

  17. Upprepa samma steg för serverdelswebbappen. Inställningarna för Distributionscenter anges i följande tabell.

    Inställning Värde
    Organisation <your-GitHub-organization>
    Lagringsplats nodejs-backend
    Filial huvud-

7. Använda tjänstens huvudnamn för GitHub Actions-distribution

Konfigurationen av Distributionscenter har skapat en standardarbetsflödesfil i var och en av dina exempellagringsplatser, men den använder en publiceringsprofil som standard, som använder grundläggande autentisering. Eftersom du har inaktiverat grundläggande autentisering ser du att den automatiskt utlösta distributionen resulterar i ett fel om du markerar fliken Loggar i Distributionscenter. Du måste ändra arbetsflödesfilen så att tjänstens huvudnamn används för att autentisera med App Service. Exempelarbetsflöden finns i Lägga till arbetsflödesfilen till din GitHub-lagringsplats.

  1. Öppna en av dina förgrenade GitHub-lagringsplatser och gå till <repo-name>/.github/workflows/ katalogen.

  2. Välj den automatiskt genererade arbetsflödesfilen och välj sedan knappen "penna" längst upp till höger för att redigera filen. Ersätt innehållet med följande text, som förutsätter att du skapade GitHub-hemligheterna tidigare för dina autentiseringsuppgifter. Uppdatera platshållaren för <web-app-name> under avsnittet "env" och checka sedan in direkt till huvudgrenen. Den här incheckningen utlöser GitHub-åtgärden för att köras igen och distribuera din kod, den här gången med tjänstens huvudnamn för att autentisera.

    name: Build and deploy Node.js app to Azure Web App
    
    on:
      push:
        branches:
          - main
      workflow_dispatch:
    
    env:
      AZURE_WEBAPP_NAME: <web-app-name>   # set this to your application's name
      NODE_VERSION: '18.x'                # set this to the node version to use
      AZURE_WEBAPP_PACKAGE_PATH: '.'      # set this to the path to your web app project, defaults to the repository root
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v2
    
          - name: Set up Node.js version
            uses: actions/setup-node@v1
            with:
              node-version: ${{ env.NODE_VERSION }}
    
          - name: npm install, build
            run: |
              npm install
              npm run build --if-present
    
          - name: Upload artifact for deployment job
            uses: actions/upload-artifact@v2
            with:
              name: node-app
              path: .
    
      deploy:
        runs-on: ubuntu-latest
        needs: build
        environment:
          url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
    
        steps:
          - name: Download artifact from build job
            uses: actions/download-artifact@v2
            with:
              name: node-app
          - uses: azure/login@v1
            with:
              creds: |
                {
                  "clientId": "${{ secrets.AZURE_APP_ID }}",
                  "clientSecret":  "${{ secrets.AZURE_PASSWORD }}",
                  "subscriptionId": "${{ secrets.AZURE_SUBSCRIPTION_ID }}",
                  "tenantId": "${{ secrets.AZURE_TENANT_ID }}"
                }
    
          - name: 'Deploy to Azure Web App'
            id: deploy-to-webapp
            uses: azure/webapps-deploy@v2
            with:
              app-name: ${{ env.AZURE_WEBAPP_NAME }}
              package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
    
          - name: logout
            run: |
              az logout
    
  3. Upprepa den här processen för arbetsflödesfilen i din andra förgrenade GitHub-lagringsplats.

De nya GitHub-incheckningarna utlöser en annan distribution för var och en av dina appar. Den här gången bör distributionen lyckas eftersom arbetsflödet använder tjänstens huvudnamn för att autentisera med apparnas SCM-webbplatser.

Detaljerad vägledning om hur du konfigurerar kontinuerlig distribution med leverantörer som GitHub Actions finns i Kontinuerlig distribution till Azure App Service.

8. Verifiera anslutningar och appåtkomst

  1. Bläddra till klientwebbappen med dess URL: https://<frontend-app-name>.azurewebsites.net.

  2. I textrutan anger du URL:en för serverdelswebbappen: https://<backend-app-name>.azurewebsites.net. Om du konfigurerar anslutningarna korrekt bör du få meddelandet "Hello from the backend web app!", som är hela innehållet i serverdelswebbappen. All utgående trafik från klientwebbappen dirigeras via det virtuella nätverket. Klientdelswebbappen ansluter säkert till serverdelswebbappen via den privata slutpunkten. Om något är fel med dina anslutningar kraschar klientdelswebbappen.

  3. Prova att navigera direkt till serverdelswebbappen med dess URL: https://<backend-app-name>.azurewebsites.net. Du bör se meddelandet Web App - Unavailable. Om du kan nå appen kontrollerar du att du har konfigurerat den privata slutpunkten och att åtkomstbegränsningarna för din app är inställda på att neka all trafik för huvudwebbappen.

  4. För att ytterligare verifiera att klientdelswebbappen når serverdelswebbappen via privat länk, SSH till en av klientdelens instanser. Kör följande kommando för SSH, som upprättar en SSH-session till webbcontainern för din app och öppnar ett fjärrgränssnitt i webbläsaren.

    az webapp ssh --resource-group $groupName --name <frontend-app-name>
    
  5. När gränssnittet öppnas i webbläsaren kör du nslookup för att bekräfta att serverdelswebbappen nås med hjälp av den privata IP-adressen för serverdelswebbappen. Du kan också köra curl för att verifiera webbplatsinnehållet igen. Ersätt <backend-app-name> med namnet på serverdelswebbappen.

    nslookup <backend-app-name>.azurewebsites.net
    curl https://<backend-app-name>.azurewebsites.net
    

    Screenshot of SSH session showing how to validate app connections.

    Bör nslookup matcha den privata IP-adressen för serverdelswebbappen. Den privata IP-adressen ska vara en adress från ditt virtuella nätverk. Bekräfta din privata IP-adress genom att gå till sidan Nätverk för serverdelswebbappen.

    Screenshot of App Service Networking page showing the inbound IP of the app.

  6. Upprepa samma nslookupcurl och kommandon från en annan terminal (en som inte är en SSH-session på klientdelens instanser).

    Screenshot of an external terminal doing a nslookup and curl of the back-end web app.

    nslookup Returnerar den offentliga IP-adressen för serverdelswebbappen. Eftersom offentlig åtkomst till serverdelswebbappen är inaktiverad får du ett felmeddelande om nekad åtkomst om du försöker nå den offentliga IP-adressen. Det här felet innebär att den här webbplatsen inte är tillgänglig från det offentliga Internet, vilket är det avsedda beteendet. Matchar nslookup inte den privata IP-adressen eftersom det bara kan matchas inifrån det virtuella nätverket via den privata DNS-zonen. Endast klientdelswebbappen finns i det virtuella nätverket. Om du försöker köra curl på serverdelswebbappen från den externa terminalen innehåller Web App - UnavailableHTML-koden som returneras . Det här felet visar HTML för felsidan som du såg tidigare när du försökte navigera till serverdelswebbappen i webbläsaren.

9. Rensa resurser

I de föregående stegen skapade du Azure-resurser i en resursgrupp. Om du inte tror att du behöver dessa resurser i framtiden tar du bort resursgruppen genom att köra följande kommando i Cloud Shell.

az group delete --name myresourcegroup

Det kan ett par minuter att köra kommandot.

Vanliga frågor och svar

Finns det något alternativ till distribution med hjälp av ett huvudnamn för tjänsten?

Eftersom du i den här självstudien har inaktiverat grundläggande autentisering kan du inte autentisera med SCM-webbplatsen i serverdelen med ett användarnamn och lösenord, och du kan inte heller använda en publiceringsprofil. I stället för tjänstens huvudnamn kan du också använda OpenID-Anslut.

Vad händer när jag konfigurerar GitHub Actions-distribution i App Service?

Azure genererar automatiskt en arbetsflödesfil på lagringsplatsen. Nya incheckningar i den valda lagringsplatsen och grenen distribueras nu kontinuerligt till din App Service-app. Du kan spåra incheckningar och distributioner på fliken Loggar .

En standardarbetsflödesfil som använder en publiceringsprofil för att autentisera till App Service läggs till på din GitHub-lagringsplats. Du kan visa den här filen genom att gå till <repo-name>/.github/workflows/ katalogen.

Är det säkert att lämna serverdels-SCM offentligt tillgänglig?

När du låser FTP- och SCM-åtkomsten säkerställer det att endast Microsoft Entra-säkerhetskopierade huvudkonton kan komma åt SCM-slutpunkten även om den är offentligt tillgänglig. Den här inställningen bör försäkra dig om att serverdelswebbappen fortfarande är säker.

Finns det något sätt att distribuera utan att öppna serverdels-SCM-platsen alls?

Om du är orolig för att aktivera offentlig åtkomst till SCM-platsen, eller om du är begränsad av principen, kan du överväga andra Distributionsalternativ för App Service som att köra från ett ZIP-paket.

Hur distribuerar jag den här arkitekturen med ARM/Bicep?

De resurser som du skapade i den här självstudien kan distribueras med hjälp av en ARM/Bicep-mall. Med den app som är ansluten till en Bicep-mall för serverdelswebbappen kan du skapa en säker N-nivåapplösning.

Information om hur du distribuerar ARM/Bicep-mallar finns i Distribuera resurser med Bicep och Azure CLI.

Nästa steg