Руководство. Создание безопасного n-уровня приложения в службе приложение Azure
Многие приложения имеют более одного компонента. Например, у вас может быть интерфейс, который является общедоступным и подключается к внутреннему API или веб-приложению, который, в свою очередь, подключается к базе данных, учетной записи хранения, хранилищу ключей, другому виртуальной машине или сочетанию этих ресурсов. Эта архитектура состоит из N-уровня приложения. Важно, чтобы такие приложения были архитекторами для защиты внутренних ресурсов в наибольшей степени.
В этом руководстве вы узнаете, как развернуть безопасное N-уровень приложения с интерфейсным веб-приложением, которое подключается к другому сетевому веб-приложению. Весь трафик изолирован в виртуальная сеть Azure с помощью интеграции виртуальная сеть и частных конечных точек. Более подробные рекомендации, которые включают другие сценарии, см. в следующих статье:
Архитектура сценария
На следующей схеме показана архитектура, которую вы создадите в рамках этого руководства.
- Виртуальная сеть содержит две подсети, одна интегрирована с интерфейсным веб-приложением, а другая — частной конечной точкой для внутреннего веб-приложения. Виртуальная сеть блокирует весь входящий сетевой трафик, кроме интерфейсного приложения, интегрированного с ним.
- Интерфейсное веб-приложение интегрировано в виртуальную сеть и доступно из общедоступного Интернета.
- Серверное веб-приложение доступно только через частную конечную точку в виртуальной сети.
- Частная конечная точка интегрируется с серверным веб-приложением и делает веб-приложение доступным с частным IP-адресом.
- зона Частная зона DNS Позволяет разрешить DNS-имя в IP-адрес частной конечной точки.
Примечание.
Интеграция виртуальной сети и частные конечные точки доступны вплоть до уровня "Базовый" в Служба приложений. Уровень "Бесплатный " не поддерживает эти функции. С этой архитектурой:
- Общедоступный трафик к внутреннему приложению заблокирован.
- Исходящий трафик из Служба приложений направляется в виртуальную сеть и может получить доступ к внутреннему приложению.
- Служба приложений может выполнять разрешение DNS в серверном приложении.
В этом сценарии показан один из возможных сценариев N-уровня в Служба приложений. Основные понятия, описанные в этом руководстве, можно использовать для создания более сложных приложений уровня N.
Из этого руководства вы узнаете, как выполнять такие задачи:
- Создайте виртуальную сеть и подсети для интеграции Служба приложений виртуальной сети.
- Создайте частные зоны DNS.
- Создание частных конечных точек.
- Настройте интеграцию виртуальной сети в Служба приложений.
- Отключите базовую проверку подлинности в службе приложений.
- Непрерывное развертывание в заблокированном серверном веб-приложении.
Необходимые компоненты
В этом руководстве используется два примера Node.js приложения, размещенные на сайте GitHub. Если у вас еще нет учетной записи GitHub, создайте бесплатную учетную запись.
Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начинать работу.
Для работы с этим руководством:
Используйте среду Bash в Azure Cloud Shell. Дополнительные сведения см . в кратком руководстве по Bash в Azure Cloud Shell.
Если вы предпочитаете выполнять справочные команды CLI локально, установите Azure CLI. Если вы работаете в Windows или macOS, Azure CLI можно запустить в контейнере Docker. Дополнительные сведения см. в статье Как запустить Azure CLI в контейнере Docker.
Если вы используете локальную установку, выполните вход в Azure CLI с помощью команды az login. Чтобы выполнить аутентификацию, следуйте инструкциям в окне терминала. Сведения о других возможностях, доступных при входе, см. в статье Вход с помощью Azure CLI.
Установите расширение Azure CLI при первом использовании, когда появится соответствующий запрос. Дополнительные сведения о расширениях см. в статье Использование расширений с Azure CLI.
Выполните команду az version, чтобы узнать установленную версию и зависимые библиотеки. Чтобы обновиться до последней версии, выполните команду az upgrade.
1. Создание двух экземпляров веб-приложения
Вам потребуется два экземпляра веб-приложения, один для внешнего интерфейса и один для серверной части. Для использования интеграции виртуальной сети и частных конечных точек необходимо использовать по крайней мере уровень "Базовый ". Вы настроите интеграцию виртуальной сети и другие конфигурации позже.
Создайте группу ресурсов для управления всеми создаваемыми ресурсами в этом руководстве.
# Save resource group name and region as variables for convenience groupName=myresourcegroup region=eastus az group create --name $groupName --location $region
Создание плана службы приложений. Замените
<app-service-plan-name>
уникальным именем. Измените параметр,--sku
если необходимо использовать другой номер SKU. Убедитесь, что вы не используете бесплатный уровень, так как этот номер SKU не поддерживает необходимые сетевые функции.# 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
Создайте веб-приложения. Замените
<frontend-app-name>
и<backend-app-name>
двумя глобально уникальными именами (допустимыми символами являютсяa-z
,0-9
и-
). В этом руководстве приведены примеры приложений Node.js. Если вы хотите использовать собственные приложения, измените--runtime
параметр соответствующим образом. Запуститеaz webapp list-runtimes
список доступных сред выполнения.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. Создание сетевой инфраструктуры
Вы создадите следующие сетевые ресурсы:
- Виртуальная сеть.
- Подсеть для интеграции Служба приложений виртуальной сети.
- Подсеть для частной конечной точки.
- Частная зона DNS.
- Частная конечная точка.
Создайте виртуальную сеть. Замените
<virtual-network-name>
уникальным именем.# 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
Создайте подсеть для интеграции Служба приложений виртуальной сети.
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
Для Служба приложений подсеть интеграции виртуальной сети рекомендуется иметь блок
/26
CIDR как минимум. Варианта/24
более чем достаточно.--delegations Microsoft.Web/serverfarms
указывает, что подсеть делегирована для интеграции с виртуальной сетью Службы приложений.Создайте другую подсеть для частных конечных точек.
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
Для подсетей частной конечной точки необходимо отключить политики сети частной конечной точки, установив для него
--disable-private-endpoint-network-policies
значениеtrue
.Создайте частную зону DNS.
az network private-dns zone create --resource-group $groupName --name privatelink.azurewebsites.net
Дополнительные сведения об этих параметрах см. в разделе "Конфигурация DNS частной конечной точки Azure".
Примечание.
Если вы создаете частную конечную точку с помощью портала, частная зона DNS создается автоматически, и ее не нужно создавать отдельно. Для обеспечения согласованности с этим руководством вы создаете частную зону DNS и частную конечную точку отдельно с помощью Azure CLI.
Создайте связь между частной зоной DNS и виртуальной сетью.
az network private-dns link vnet create --resource-group $groupName --name myDnsLink --zone-name privatelink.azurewebsites.net --virtual-network $vnetName --registration-enabled False
В подсети частной конечной точки виртуальной сети создайте частную конечную точку для внутреннего веб-приложения. Замените
<backend-app-name>
на имя внутреннего веб-приложения.# 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
Свяжите частную конечную точку с частной зоной DNS с группой зон DNS для частной конечной точки внутреннего веб-приложения. Эта группа зон DNS помогает автоматически обновлять частную зону DNS при обновлении частной конечной точки.
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
При создании частной конечной точки для Служба приложений общедоступный доступ неявно отключается. Если вы пытаетесь получить доступ к внутреннему веб-приложению с помощью своего URL-адреса по умолчанию, ваш доступ запрещен. В браузере перейдите к
<backend-app-name>.azurewebsites.net
подтверждению этого поведения.Дополнительные сведения об ограничениях доступа Служба приложений с частными конечными точками см. в разделе приложение Azure Ограничения доступа к службе.
3. Настройка интеграции виртуальной сети в интерфейсном веб-приложении
Включение интеграции с виртуальной сетью в приложении. Замените <frontend-app-name>
имя внешнего веб-приложения.
az webapp vnet-integration add --resource-group $groupName --name <frontend-app-name> --vnet $vnetName --subnet vnet-integration-subnet
Интеграция с виртуальной сетью позволяет исходящему трафику поступать непосредственно в виртуальную сеть. По умолчанию в виртуальную сеть направляется только локальный IP-трафик, определенный в RFC-1918 — это то, что необходимо для частных конечных точек. Сведения о маршрутизации всего трафика в виртуальную сеть см. в разделе Управление маршрутизацией при интеграции с виртуальной сетью. Маршрутизацию всего трафика можно также использовать в ситуации, если через виртуальную сеть, например через NAT виртуальных сетей Azure или Брандмауэр Azure, требуется маршрутизировать интернет-трафик.
4. Включение развертывания в серверное веб-приложение из Интернета
Так как серверный веб-приложение не является общедоступным, необходимо разрешить вашему приложению непрерывное развертывание, сделав сайт SCM общедоступным. Основное веб-приложение может продолжать отрицать весь трафик.
Включите общедоступный доступ для внутреннего веб-приложения.
az webapp update --resource-group $groupName --name <backend-app-name> --set publicNetworkAccess=Enabled
Задайте для основного веб-приложения несоответветное действие правила, чтобы запретить весь трафик. Этот параметр запрещает общедоступный доступ к основному веб-приложению, даже если для общего параметра доступа к приложению задано разрешение общедоступного доступа.
az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Deny
Задайте для сайта SCM несоответсвованное действие правила, чтобы разрешить весь трафик.
az resource update --resource-group $groupName --name <backend-app-name> --namespace Microsoft.Web --resource-type sites --set properties.siteConfig.scmIpSecurityRestrictionsDefaultAction=Allow
5. Блокировка доступа FTP и SCM
Теперь, когда внутренний сайт SCM является общедоступным, необходимо заблокировать его с более эффективной безопасностью.
Отключите ftp-доступ для внешних и внутренних веб-приложений. Замените
<frontend-app-name>
имена приложений и<backend-app-name>
их именами.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
Отключите базовый доступ к портам WebDeploy и сайтам средств SCM/advanced tool для обоих веб-приложений. Замените
<frontend-app-name>
имена приложений и<backend-app-name>
их именами.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
Отключение базовой проверки подлинности на Служба приложений ограничивает доступ к конечным точкам FTP и SCM пользователям, которые поддерживаются идентификатором Microsoft Entra ID, что дополнительно защищает ваши приложения. Дополнительные сведения об отключении базовой проверки подлинности, включая тестирование и мониторинг имен входа, см. в разделе "Отключение базовой проверки подлинности в Служба приложений".
6. Настройка непрерывного развертывания с помощью GitHub Actions
Перейдите к примеру приложения Node.js серверной части. Это простое приложение Hello World.
Нажмите кнопку Вилка в правом верхнем углу на странице GitHub.
Выберите владельца и оставьте имя репозитория по умолчанию.
Щелкните Создать вилку.
Повторите тот же процесс для Node.js интерфейсного приложения. Это базовое веб-приложение, которое обращается к удаленный URL-адрес.
Создайте субъект-службу. Замените
<subscription-id>
,<frontend-app-name>
а также<backend-app-name>
значениями.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
Выходные данные — это объект JSON с учетными данными назначения ролей, предоставляющими доступ к приложениям Служба приложений. Скопируйте этот объект JSON для следующего шага. Он включает секрет клиента, который отображается только в настоящее время. Рекомендуется всегда предоставлять минимальные разрешения доступа. Область в этом примере ограничена только приложениями, а не всей группой ресурсов.
Чтобы сохранить учетные данные субъекта-службы в качестве секретов GitHub, перейдите к одному из вилочных репозиториев в GitHub и перейдите к разделу "Параметры секретов>безопасности>и переменных>Actions".
Выберите новый секрет репозитория и создайте секрет для каждого из следующих значений. Значения можно найти в выходных данных JSON, скопированных ранее.
Имя. Значение AZURE_APP_ID <application/client-id>
AZURE_PASSWORD <client-secret>
AZURE_TENANT_ID <tenant-id>
AZURE_SUBSCRIPTION_ID <subscription-id>
Повторите этот процесс для другого вилированного репозитория примера.
Чтобы настроить непрерывное развертывание с помощью GitHub Actions, войдите в портал Azure.
Перейдите на страницу обзора для веб-приложения внешнего интерфейса.
В области слева выберите Центр развертывания. Затем выберите Параметры.
В поле "Источник" выберите "GitHub" в параметрах CI/CD.
При первом развертывании из GitHub выберите Авторизовать и следуйте запросам авторизации. Если требуется выполнить развертывание из другого пользовательского репозитория, выберите Изменить учетную запись.
Если вы используете Node.js пример приложения, которое было вилировано в рамках предварительных требований, используйте следующие параметры для организации, репозитория и ветви.
Параметр Значение Организация <your-GitHub-organization>
Репозиторий nodejs-frontend Филиал main Выберите Сохранить.
Повторите те же действия для внутреннего веб-приложения. Параметры Центра развертывания приведены в следующей таблице.
Параметр Значение Организация <your-GitHub-organization>
Репозиторий nodejs-backend Филиал main
7. Использование субъекта-службы для развертывания GitHub Actions
Конфигурация Центра развертывания создала файл рабочего процесса по умолчанию в каждом из примеров репозиториев, но по умолчанию использует профиль публикации, который использует базовую проверку подлинности. Так как вы отключили базовую проверку подлинности, при проверке вкладки "Журналы " в Центре развертывания вы увидите, что автоматически активируемое развертывание приводит к ошибке. Необходимо изменить файл рабочего процесса, чтобы использовать субъект-службу для проверки подлинности с помощью Служба приложений. Примеры рабочих процессов см. в разделе "Добавление файла рабочего процесса в репозиторий GitHub".
Откройте один из вложенных репозиториев GitHub и перейдите в
<repo-name>/.github/workflows/
каталог.Выберите автоматически созданный файл рабочего процесса и нажмите кнопку "карандаш" в правом верхнем углу, чтобы изменить файл. Замените содержимое следующим текстом, который предполагает, что вы создали секреты GitHub ранее для учетных данных. Обновите заполнитель в
<web-app-name>
разделе "env", а затем зафиксируйте его непосредственно в главной ветви. Эта фиксация активирует действие GitHub для повторного выполнения и развертывания кода, на этот раз с помощью субъекта-службы для проверки подлинности.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
Повторите этот процесс для файла рабочего процесса в другом вилке репозитория GitHub.
Новая фиксация GitHub активирует другое развертывание для каждого приложения. На этот раз развертывание должно завершиться успешно, так как рабочий процесс использует субъект-службу для проверки подлинности на сайтах SCM приложений.
Подробные инструкции по настройке непрерывного развертывания с поставщиками, такими как GitHub Actions, см. в статье "Непрерывное развертывание в службе приложение Azure".
8. Проверка подключений и доступа к приложению
Перейдите к веб-приложению внешнего интерфейса с его URL-адресом:
https://<frontend-app-name>.azurewebsites.net
В текстовом поле введите URL-адрес для внутреннего веб-приложения:
https://<backend-app-name>.azurewebsites.net
Если вы правильно настроили подключения, необходимо получить сообщение "Hello из внутреннего веб-приложения!", которое является всем содержимым внутреннего веб-приложения. Весь исходящий трафик из интерфейсного веб-приложения направляется через виртуальную сеть. Интерфейсный веб-приложение безопасно подключается к внутреннему веб-приложению через частную конечную точку. Если что-то не так с подключениями, интерфейсное веб-приложение завершает работу.Попробуйте перейти непосредственно к внутреннему веб-приложению с его URL-адресом:
https://<backend-app-name>.azurewebsites.net
Отобразится сообщениеWeb App - Unavailable
. Если вы можете получить доступ к приложению, убедитесь, что вы настроили частную конечную точку и что ограничения доступа для приложения будут запрещены для всего трафика для основного веб-приложения.Для дальнейшего проверки того, что интерфейсное веб-приложение достигает серверного веб-приложения по приватной ссылке, SSH к одному из экземпляров внешнего интерфейса. Для SSH выполните следующую команду, которая устанавливает сеанс SSH в веб-контейнер приложения и открывает удаленную оболочку в браузере.
az webapp ssh --resource-group $groupName --name <frontend-app-name>
Когда оболочка откроется в браузере, запустите
nslookup
, чтобы убедиться, что серверное веб-приложение достигается с помощью частного IP-адреса внутреннего веб-приложения. Вы также можете выполнитьcurl
проверку содержимого сайта еще раз. Замените<backend-app-name>
на имя внутреннего веб-приложения.nslookup <backend-app-name>.azurewebsites.net curl https://<backend-app-name>.azurewebsites.net
Необходимо
nslookup
разрешить частный IP-адрес внутреннего веб-приложения. Частный IP-адрес должен быть адресом из виртуальной сети. Чтобы подтвердить частный IP-адрес, перейдите на страницу "Сеть " для внутреннего веб-приложения.Повторите те же
nslookup
команды иcurl
команды из другого терминала (один из них не является сеансом SSH в экземплярах внешнего интерфейса).Возвращает
nslookup
общедоступный IP-адрес для внутреннего веб-приложения. Так как общедоступный доступ к внутреннему веб-приложению отключен, если вы пытаетесь получить общедоступный IP-адрес, вы получите ошибку отказа в доступе. Эта ошибка означает, что этот сайт недоступен из общедоступного Интернета, что является предполагаемым поведением. Неnslookup
разрешается частный IP-адрес, так как его можно разрешить только из виртуальной сети через частную зону DNS. Только интерфейсное веб-приложение находится в виртуальной сети. Если вы попытаетесь запуститьcurl
серверное веб-приложение из внешнего терминала, html-код, который возвращаетсяWeb App - Unavailable
. Эта ошибка отображает HTML-код страницы ошибок, который вы видели ранее при попытке перейти к внутреннему веб-приложению в браузере.
9. Очистка ресурсов
На предыдущем шаге вы создали ресурсы Azure в группе ресурсов. Если эти ресурсы вам не понадобятся в будущем, вы можете удалить группу ресурсов, выполнив приведенную ниже команду в Cloud Shell.
az group delete --name myresourcegroup
Выполнение этой команды может занять несколько минут.
Часто задаваемые вопросы
- Существует ли альтернатива развертыванию с помощью субъекта-службы?
- Что происходит при настройке развертывания GitHub Actions в Служба приложений?
- Безопасно ли оставить внутренний SCM общедоступным?
- Существует ли способ развертывания без открытия внутреннего сайта SCM вообще?
- Как развернуть эту архитектуру с помощью ARM/Bicep?
Существует ли альтернатива развертыванию с помощью субъекта-службы?
Так как в этом руководстве вы отключили базовую проверку подлинности, вы не можете пройти проверку подлинности с помощью внутреннего сайта SCM с именем пользователя и паролем, и вы не можете использовать профиль публикации. Вместо субъекта-службы можно также использовать OpenID Connect.
Что происходит при настройке развертывания GitHub Actions в Служба приложений?
Azure автоматически создает файл рабочего процесса в репозитории. Новые фиксации в выбранном репозитории в приложении Службы приложений будут непрерывно развертываться. Фиксации и развертывания можно отслеживать на вкладке Журналы.
Файл рабочего процесса по умолчанию, использующий профиль публикации для проверки подлинности в Служба приложений, добавляется в репозиторий GitHub. Этот файл можно просмотреть, перейдя в <repo-name>/.github/workflows/
каталог.
Безопасно ли оставить внутренний SCM общедоступным?
При блокировке доступа ПО FTP и SCM гарантируется, что доступ к конечной точке SCM может получить только поддерживаемые субъекты Microsoft Entra, даже если он является общедоступным. Этот параметр должен убедиться, что серверные веб-приложения по-прежнему защищены.
Существует ли способ развертывания без открытия внутреннего сайта SCM вообще?
Если вы обеспокоены включением общедоступного доступа к сайту SCM или вы ограничены политикой, рассмотрите другие варианты развертывания Служба приложений, такие как запуск из ZIP-пакета.
Как развернуть эту архитектуру с помощью ARM/Bicep?
Ресурсы, созданные в этом руководстве, можно развернуть с помощью шаблона ARM/Bicep. Приложение, подключенное к шаблону Bicep внутреннего веб-приложения, позволяет создавать безопасное решение для приложений уровня N.
Сведения о развертывании шаблонов ARM/Bicep см. в статье "Развертывание ресурсов с помощью Bicep и Azure CLI".