Esercitazione: Creare un'app a più livelli sicura nel servizio app Azure
Molte applicazioni hanno più di un singolo componente. Ad esempio, potrebbe essere disponibile un front-end accessibile pubblicamente e si connette a un'API back-end o a un'app Web che a sua volta si connette a un database, a un account di archiviazione, a un insieme di credenziali delle chiavi, a un'altra macchina virtuale o a una combinazione di queste risorse. Questa architettura costituisce un'applicazione a più livelli. È importante progettare applicazioni di questo tipo per proteggere al massimo le risorse back-end.
Questa esercitazione illustra come distribuire un'applicazione a più livelli sicura con un'app Web front-end che si connette a un'altra app Web isolata dalla rete. Tutto il traffico è isolato all'interno dell'Rete virtuale di Azure usando Rete virtuale endpoint privati e di integrazione. Per indicazioni più complete che includono altri scenari, vedere:
Architettura dello scenario
Il diagramma seguente illustra l'architettura che verrà creata durante questa esercitazione.
- La rete virtuale contiene due subnet, una è integrata con l'app Web front-end e l'altra ha un endpoint privato per l'app Web back-end. La rete virtuale blocca tutto il traffico di rete in ingresso, ad eccezione dell'app front-end integrata con essa.
- App Web front-end Integrata nella rete virtuale e accessibile dalla rete Internet pubblica.
- App Web back-end Accessibile solo tramite l'endpoint privato nella rete virtuale.
- L'endpoint privato si integra con l'app Web back-end e rende l'app Web accessibile con un indirizzo IP privato.
- zona DNS privato Consente di risolvere un nome DNS nell'indirizzo IP dell'endpoint privato.
Nota
L'integrazione della rete virtuale e gli endpoint privati sono disponibili fino al livello Basic in servizio app. Il livello Gratuito non supporta queste funzionalità. Con questa architettura:
- Il traffico pubblico verso l'app back-end è bloccato.
- Il traffico in uscita da servizio app viene instradato alla rete virtuale e può raggiungere l'app back-end.
- servizio app è in grado di eseguire la risoluzione DNS all'app back-end.
Questo scenario illustra uno dei possibili scenari a più livelli in servizio app. È possibile usare i concetti trattati in questa esercitazione per creare app più complesse a più livelli.
Contenuto dell'esercitazione:
- Creare una rete virtuale e subnet per l'integrazione della rete virtuale servizio app.
- Creare zone DNS private.
- Creare endpoint privati.
- Configurare l'integrazione della rete virtuale in servizio app.
- Disabilitare l'autenticazione di base nel servizio app.
- Distribuire continuamente in un'app Web back-end bloccata.
Prerequisiti
L'esercitazione usa due app di esempio Node.js ospitate in GitHub. Se non si ha già un account GitHub, creare gratuitamente un account.
Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.
Per completare questa esercitazione:
Usare l'ambiente Bash in Azure Cloud Shell. Per altre informazioni, vedere Avvio rapido per Bash in Azure Cloud Shell.
Se si preferisce eseguire i comandi di riferimento dell'interfaccia della riga di comando in locale, installare l'interfaccia della riga di comando di Azure. Per l'esecuzione in Windows o macOS, è consigliabile eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker. Per altre informazioni, vedere Come eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker.
Se si usa un'installazione locale, accedere all'interfaccia della riga di comando di Azure con il comando az login. Per completare il processo di autenticazione, seguire la procedura visualizzata nel terminale. Per altre opzioni di accesso, vedere Accedere con l'interfaccia della riga di comando di Azure.
Quando richiesto, installare l'estensione dell'interfaccia della riga di comando di Azure al primo uso. Per altre informazioni sulle estensioni, vedere Usare le estensioni con l'interfaccia della riga di comando di Azure.
Eseguire az version per trovare la versione e le librerie dipendenti installate. Per eseguire l'aggiornamento alla versione più recente, eseguire az upgrade.
1. Creare due istanze di un'app Web
Sono necessarie due istanze di un'app Web, una per il front-end e una per il back-end. È necessario usare almeno il livello Basic per usare l'integrazione della rete virtuale e gli endpoint privati. L'integrazione della rete virtuale e altre configurazioni verranno configurate in un secondo momento.
Creare un gruppo di risorse per gestire tutte le risorse create in questa esercitazione.
# Save resource group name and region as variables for convenience groupName=myresourcegroup region=eastus az group create --name $groupName --location $region
Creare un piano di servizio app. Sostituire
<app-service-plan-name>
con un nome univoco. Modificare il--sku
parametro se è necessario usare uno SKU diverso. Assicurarsi di non usare il livello gratuito perché tale SKU non supporta le funzionalità di rete necessarie.# 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
Creare le app Web. Sostituire
<frontend-app-name>
e<backend-app-name>
con due nomi univoci globali (i caratteri validi sonoa-z
,0-9
e-
). Per questa esercitazione vengono fornite app di esempio Node.js. Se vuoi usare le tue app, modifica il--runtime
parametro di conseguenza. Eseguireaz webapp list-runtimes
per l'elenco dei runtime disponibili.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. Creare un'infrastruttura di rete
Verranno create le risorse di rete seguenti:
- Una rete virtuale.
- Una subnet per l'integrazione della rete virtuale servizio app.
- Una subnet per l'endpoint privato.
- Una zona DNS privata.
- Endpoint privato.
Crea una rete virtuale. Sostituire
<virtual-network-name>
con un nome univoco.# 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
Creare una subnet per l'integrazione della rete virtuale servizio app.
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
Per servizio app, è consigliabile che la subnet di integrazione della rete virtuale abbia almeno un blocco CIDR.
/26
/24
è più che sufficiente.--delegations Microsoft.Web/serverfarms
specifica che la subnet è delegata per l'integrazione della rete virtuale servizio app.Creare un'altra subnet per gli endpoint privati.
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
Per le subnet degli endpoint privati, è necessario disabilitare i criteri di rete degli endpoint privati impostando su
--disable-private-endpoint-network-policies
true
.Creare la zona DNS privata.
az network private-dns zone create --resource-group $groupName --name privatelink.azurewebsites.net
Per altre informazioni su queste impostazioni, vedere Configurazione DNS dell'endpoint privato di Azure.
Nota
Se si crea l'endpoint privato usando il portale, viene creata automaticamente una zona DNS privata e non è necessario crearla separatamente. Per coerenza con questa esercitazione, si crei la zona DNS privata e l'endpoint privato separatamente usando l'interfaccia della riga di comando di Azure.
Collegare la zona DNS privato alla rete virtuale.
az network private-dns link vnet create --resource-group $groupName --name myDnsLink --zone-name privatelink.azurewebsites.net --virtual-network $vnetName --registration-enabled False
Nella subnet dell'endpoint privato della rete virtuale creare un endpoint privato per l'app Web back-end. Sostituire
<backend-app-name>
con il nome dell'app Web back-end.# 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
Collegare l'endpoint privato alla zona DNS privata con un gruppo di zone DNS per l'endpoint privato dell'app Web back-end. Questo gruppo di zone DNS consente di aggiornare automaticamente la zona DNS privata quando è presente un aggiornamento all'endpoint privato.
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
Quando si crea un endpoint privato per un servizio app, l'accesso pubblico viene disabilitato in modo implicito. Se si tenta di accedere all'app Web back-end usando l'URL predefinito, l'accesso viene negato. Da un browser passare a per confermare
<backend-app-name>.azurewebsites.net
questo comportamento.Per altre informazioni sulle restrizioni di accesso servizio app con endpoint privati, vedere app Azure Restrizioni di accesso al servizio.
3. Configurare l'integrazione della rete virtuale nell'app Web front-end
Abilitare l'integrazione della rete virtuale nell'app. Sostituire <frontend-app-name>
con il nome dell'app Web front-end.
az webapp vnet-integration add --resource-group $groupName --name <frontend-app-name> --vnet $vnetName --subnet vnet-integration-subnet
L'integrazione della rete virtuale consente al traffico in uscita di fluire direttamente nella rete virtuale. Per impostazione predefinita, solo il traffico IP locale definito in RFC-1918 viene instradato alla rete virtuale, ovvero ciò che serve per gli endpoint privati. Per indirizzare tutto il traffico alla rete virtuale, vedere Gestire il routing di integrazione della rete virtuale. Il routing di tutto il traffico può essere usato anche se si vuole instradare il traffico Internet attraverso la rete virtuale, ad esempio tramite un nat di Azure Rete virtuale o un Firewall di Azure.
4. Abilitare la distribuzione nell'app Web back-end da Internet
Poiché l'app Web back-end non è accessibile pubblicamente, è necessario consentire allo strumento di distribuzione continua di raggiungere l'app rendendo il sito SCM accessibile pubblicamente. L'app Web principale può continuare a negare tutto il traffico.
Abilitare l'accesso pubblico per l'app Web back-end.
az webapp update --resource-group $groupName --name <backend-app-name> --set publicNetworkAccess=Enabled
Impostare l'azione regola non corrispondente per l'app Web principale per negare tutto il traffico. Questa impostazione nega l'accesso pubblico all'app Web principale anche se l'impostazione generale di accesso alle app è impostata per consentire l'accesso pubblico.
az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Deny
Impostare l'azione regola non corrispondente per il sito di Gestione controllo servizi per consentire tutto il traffico.Set the unmatched rule action for the SCM site to allow all traffic.
az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.scmIpSecurityRestrictionsDefaultAction=Allow
5. Bloccare l'accesso FTP e SCM
Ora che il sito SCM back-end è accessibile pubblicamente, è necessario bloccarlo con una maggiore sicurezza.
Disabilitare l'accesso FTP per le app Web front-end e back-end. Sostituire
<frontend-app-name>
e<backend-app-name>
con i nomi dell'app.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
Disabilitare l'accesso di autenticazione di base alle porte WebDeploy e ai siti degli strumenti SCM/avanzati per entrambe le app Web. Sostituire
<frontend-app-name>
e<backend-app-name>
con i nomi dell'app.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
La disabilitazione dell'autenticazione di base in servizio app limita l'accesso agli endpoint FTP e SCM agli utenti supportati da Microsoft Entra ID, che protegge ulteriormente le app. Per altre informazioni sulla disabilitazione dell'autenticazione di base, tra cui come testare e monitorare gli account di accesso, vedere Disabilitazione dell'autenticazione di base in servizio app.
6. Configurare la distribuzione continua con GitHub Actions
Passare all'app di esempio back-end Node.js. Questa app è una semplice app Hello World.
Selezionare il pulsante Fork in alto a destra nella pagina GitHub.
Selezionare Proprietario e lasciare il nome repository predefinito.
Selezionare Crea fork.
Ripetere lo stesso processo per l'app di esempio front-end Node.js. Questa app è un'app Web di base che accede a un URL remoto.
Creare un'entità servizio. Sostituire
<subscription-id>
,<frontend-app-name>
e<backend-app-name>
con i valori.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
L'output è un oggetto JSON con le credenziali di assegnazione di ruolo che forniscono l'accesso alle app servizio app. Copiare questo oggetto JSON per il passaggio successivo. Include il segreto client, che è visibile solo in questo momento. È sempre consigliabile concedere l'accesso minimo. L'ambito in questo esempio è limitato solo alle app, non all'intero gruppo di risorse.
Per archiviare le credenziali dell'entità servizio come segreti GitHub, passare a uno dei repository di esempio con fork in GitHub e passare a Impostazioni> Sicurezza>segreti e variabili>Azioni.
Selezionare Nuovo segreto del repository e creare un segreto per ognuno dei valori seguenti. I valori sono disponibili nell'output JSON copiato in precedenza.
Nome valore AZURE_APP_ID <application/client-id>
AZURE_PASSWORD <client-secret>
AZURE_TENANT_ID <tenant-id>
AZURE_SUBSCRIPTION_ID <subscription-id>
Ripetere questo processo per l'altro repository di esempio con fork.
Per configurare la distribuzione continua con GitHub Actions, accedere al portale di Azure.
Passare alla pagina Panoramica per l'app Web front-end.
Nel riquadro sinistro selezionare Centro distribuzione. Selezionare quindi Impostazioni.
Nella casella Origine selezionare "GitHub" nelle opzioni CI/CD.
Se si esegue la distribuzione da GitHub per la prima volta, selezionare Autorizza e seguire le istruzioni di autorizzazione. Se si vuole eseguire la distribuzione da un repository utente diverso, selezionare Cambia account.
Se si usa l'app di esempio Node.js copiata tramite fork come parte dei prerequisiti, usare le impostazioni seguenti per Organizzazione, Repository e Ramo.
Impostazione Valore Organization <your-GitHub-organization>
Repository nodejs-frontend Filiale main Seleziona Salva.
Ripetere gli stessi passaggi per l'app Web back-end. Le impostazioni del Centro distribuzione sono indicate nella tabella seguente.
Impostazione Valore Organization <your-GitHub-organization>
Repository nodejs-backend Filiale main
7. Usare un'entità servizio per la distribuzione di GitHub Actions
La configurazione del Centro distribuzione ha creato un file del flusso di lavoro predefinito in ognuno dei repository di esempio, ma usa un profilo di pubblicazione per impostazione predefinita, che usa l'autenticazione di base. Poiché l'autenticazione di base è stata disabilitata, se si seleziona la scheda Log nel Centro distribuzione, si noterà che la distribuzione attivata automaticamente genera un errore. È necessario modificare il file del flusso di lavoro per usare l'entità servizio per l'autenticazione con servizio app. Per i flussi di lavoro di esempio, vedere Aggiungere il file del flusso di lavoro al repository GitHub.
Aprire uno dei repository GitHub con fork e passare alla
<repo-name>/.github/workflows/
directory .Selezionare il file del flusso di lavoro generato automaticamente e quindi selezionare il pulsante "matita" in alto a destra per modificare il file. Sostituire il contenuto con il testo seguente, che presuppone che i segreti gitHub siano stati creati in precedenza per le credenziali. Aggiornare il segnaposto per
<web-app-name>
nella sezione "env" e quindi eseguire il commit direttamente nel ramo main. Questo commit attiva l'esecuzione di GitHub Action e la distribuzione del codice, questa volta usando l'entità servizio per l'autenticazione.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
Ripetere questo processo per il file del flusso di lavoro nell'altro repository GitHub con fork.
I nuovi commit di GitHub attivano un'altra distribuzione per ognuna delle app. Questa volta, la distribuzione dovrebbe avere esito positivo perché il flusso di lavoro usa l'entità servizio per l'autenticazione con i siti SCM delle app.
Per indicazioni dettagliate su come configurare la distribuzione continua con provider come GitHub Actions, vedere Distribuzione continua nel servizio app Azure.
8. Convalidare le connessioni e l'accesso alle app
Passare all'app Web front-end con il relativo URL:
https://<frontend-app-name>.azurewebsites.net
.Nella casella di testo immettere l'URL per l'app Web back-end:
https://<backend-app-name>.azurewebsites.net
. Se si configurano correttamente le connessioni, dovrebbe essere visualizzato il messaggio "Hello from the backend web app!", ovvero l'intero contenuto dell'app Web back-end. Tutto il traffico in uscita dall'app Web front-end viene instradato attraverso la rete virtuale. L'app Web front-end si connette in modo sicuro all'app Web back-end tramite l'endpoint privato. In caso di problemi con le connessioni, l'app Web front-end si arresta in modo anomalo.Provare a passare direttamente all'app Web back-end con il relativo URL:
https://<backend-app-name>.azurewebsites.net
. Dovrebbe essere visualizzato il messaggioWeb App - Unavailable
. Se è possibile raggiungere l'app, assicurarsi di aver configurato l'endpoint privato e che le restrizioni di accesso per l'app siano impostate per negare tutto il traffico per l'app Web principale.Per verificare ulteriormente che l'app Web front-end raggiunga l'app Web back-end tramite collegamento privato, ssh a una delle istanze del front-end. Per SSH, eseguire il comando seguente, che stabilisce una sessione SSH per il contenitore Web dell'app e apre una shell remota nel browser.
az webapp ssh --resource-group $groupName --name <frontend-app-name>
Quando la shell viene aperta nel browser, eseguire
nslookup
per verificare che l'app Web back-end venga raggiunta usando l'indirizzo IP privato dell'app Web back-end. È anche possibile eseguirecurl
per convalidare di nuovo il contenuto del sito. Sostituire<backend-app-name>
con il nome dell'app Web back-end.nslookup <backend-app-name>.azurewebsites.net curl https://<backend-app-name>.azurewebsites.net
Deve
nslookup
essere risolto nell'indirizzo IP privato dell'app Web back-end. L'indirizzo IP privato deve essere un indirizzo dalla rete virtuale. Per confermare l'indirizzo IP privato, passare alla pagina Rete per l'app Web back-end.Ripetere gli stessi
nslookup
comandi ecurl
da un altro terminale (uno che non è una sessione SSH nelle istanze del front-end).Restituisce
nslookup
l'indirizzo IP pubblico per l'app Web back-end. Poiché l'accesso pubblico all'app Web back-end è disabilitato, se si tenta di raggiungere l'indirizzo IP pubblico, viene visualizzato un errore di accesso negato. Questo errore indica che questo sito non è accessibile dalla rete Internet pubblica, ovvero il comportamento previsto. Nonnslookup
risolve l'indirizzo IP privato perché può essere risolto solo dall'interno della rete virtuale tramite la zona DNS privata. Solo l'app Web front-end si trova all'interno della rete virtuale. Se si tenta di eseguirecurl
nell'app Web back-end dal terminale esterno, il codice HTML restituito contieneWeb App - Unavailable
. Questo errore visualizza il codice HTML per la pagina di errore visualizzata in precedenza quando si è tentato di passare all'app Web back-end nel browser.
9. Pulire le risorse
Nei passaggi precedenti sono state create risorse di Azure in un gruppo di risorse. Se si ritiene che queste risorse non saranno necessarie in futuro, eliminare il gruppo di risorse eseguendo questo comando in Cloud Shell.
az group delete --name myresourcegroup
L'esecuzione del comando può richiedere alcuni minuti.
Domande frequenti
- Esiste un'alternativa alla distribuzione usando un'entità servizio?
- Cosa accade quando si configura la distribuzione di GitHub Actions in servizio app?
- È sicuro lasciare accessibile pubblicamente SCM back-end?
- È possibile eseguire la distribuzione senza aprire il sito SCM back-end?
- Come è possibile distribuire questa architettura con ARM/Bicep?
Esiste un'alternativa alla distribuzione usando un'entità servizio?
Poiché in questa esercitazione è stata disabilitata l'autenticazione di base, non è possibile eseguire l'autenticazione con il sito SCM back-end con nome utente e password e non è possibile usare un profilo di pubblicazione. Anziché un'entità servizio, è anche possibile usare OpenID Connessione.
Cosa accade quando si configura la distribuzione di GitHub Actions in servizio app?
Azure genera automaticamente un file del flusso di lavoro nel repository. I nuovi commit nel repository e nel ramo selezionati vengono distribuiti in modo continuo nell'app del servizio app. È possibile tenere traccia dei commit e delle distribuzioni nella scheda Log .
Un file del flusso di lavoro predefinito che usa un profilo di pubblicazione per l'autenticazione per servizio app viene aggiunto al repository GitHub. È possibile visualizzare questo file passando alla <repo-name>/.github/workflows/
directory .
È sicuro lasciare accessibile pubblicamente SCM back-end?
Quando si blocca l'accesso FTP e SCM, garantisce che solo le entità supportate da Microsoft Entra possano accedere all'endpoint SCM anche se è accessibile pubblicamente. Questa impostazione dovrebbe rassicurare l'utente che l'app Web back-end è ancora sicura.
È possibile eseguire la distribuzione senza aprire il sito SCM back-end?
Se si è preoccupati di abilitare l'accesso pubblico al sito SCM o di essere limitati dai criteri, prendere in considerazione altre opzioni di distribuzione servizio app come l'esecuzione da un pacchetto ZIP.
Come è possibile distribuire questa architettura con ARM/Bicep?
Le risorse create in questa esercitazione possono essere distribuite usando un modello ARM/Bicep. Il modello Bicep app connessa a un'app Web back-end consente di creare una soluzione di app a più livelli sicura.
Per informazioni su come distribuire modelli ARM/Bicep, vedere Come distribuire le risorse con Bicep e l'interfaccia della riga di comando di Azure.