Установка в Microsoft Azure
Развёртывание ScanSuite Teams в собственной подписке Azure на Container Apps с помощью Terraform, с примерами установки.
ScanSuite Teams можно развернуть не на сервере, а в собственной подписке Azure. Конфигурация Terraform из папки azure репозитория установки создаёт всё одной командой и удаляет другой. Приложение работает в Azure Container Apps вместе с управляемыми сервисами, так что обслуживать виртуальную машину не нужно.
В Container Apps нет демона Docker, поэтому сканеры, которые запускаются отдельными контейнерами, — динамическое сканирование веб-приложений (DAST) и сканирование инфраструктуры — здесь не работают. Анализ кода (SAST), зависимостей (SCA), инфраструктуры как кода, поиск секретов и AI-анализ кода работают полностью. Для динамических сканирований установите ScanSuite на сервер: Установка ScanSuite Teams.
Что создаётся
Всё размещается в одной группе ресурсов, которую создаёт развёртывание. Секреты генерируются при первом развёртывании и хранятся в Key Vault. База данных доступна только изнутри виртуальной сети, а хранилище артефактов — только из подсети Container Apps, без ключей хранилища.
| Часть | Как работает |
|---|---|
| Веб-интерфейс и API | Приложение-контейнер с управляемым TLS; входящий трафик пропускается только с ваших диапазонов адресов. |
| Фоновые воркеры | Приложения-контейнеры: обслуживание и восстановление прерванных сканирований, планировщик, Redis для очереди задач и песочница для AI-проверок proof-of-concept, которая запускается по требованию. |
| Сканирования | Отдельный запуск задания Container Apps на каждое сканирование, 4 vCPU и 8 ГиБ; после сканирования он завершается. |
| Миграция базы данных | Задание Container Apps, которое запускает deploy.sh. |
| База данных | Azure Database for PostgreSQL 16 (Flexible Server), внутренняя, с резервными копиями за семь дней. |
| Артефакты сканирований | Blob Storage, доступ через управляемое удостоверение; прежние версии хранятся 30 дней. |
| Образы | Собственный Azure Container Registry: во время работы установка ничего не загружает из интернета. |
| Журналы и оповещения | Log Analytics с оповещениями об ошибках, неудачных сканированиях и нагрузке на базу данных. |
1. Подготовка
- Подписка Azure, в которой у вас роль Owner или Contributor вместе с Role Based Access Control Administrator: развёртывание создаёт управляемые удостоверения, собственную роль и назначения ролей, поэтому одной роли Contributor недостаточно.
- Инструменты на Linux, macOS или Windows с WSL или Git Bash: Azure CLI (
az) 2.60 или новее, Terraform 1.6 или новее, git и bash. - Из поставки ScanSuite: файл лицензии (
<имя>_<код>.lic; код — это и тег образов), а также имя пользователя и токен доступа к реестру образов — с ними образы копируются в вашу подписку. - Ваш публичный IPv4-адрес или диапазоны, с которых разрешено открывать веб-интерфейс. Запрашивайте именно IPv4, иначе многие подключения покажут IPv6-адрес:
curl -4 -s https://ifconfig.me.
2. Развёртывание
Загрузите файлы установки, добавьте лицензию и перейдите в папку azure:
git clone https://github.com/cepxeo/scansuite.git
cp /path/to/<имя>_<код>.lic scansuite/key/
cd scansuite/azureВойдите в Azure и запишите подписку, в которую будете разворачивать:
az login
az account list -o tableСкопируйте пример настроек и отредактируйте копию. Готовые примеры — в разделе 3.
cp terraform.tfvars.example terraform.tfvars| Параметр | Что указать |
|---|---|
| subscription_id | ID подписки из az account list. |
| location | Регион, например germanywestcentral, swedencentral или northeurope. |
| resource_group_name | Имя новой группы ресурсов. Её создаёт развёртывание, поэтому такой группы ещё не должно быть. |
| web_allowed_cidrs | Диапазоны адресов, с которых открывается интерфейс, например ["203.0.113.10/32"]. |
| image_tag | Код вашей лицензии, <код> в <имя>_<код>.lic. |
| alert_email | Необязательно. Адрес для оповещений. |
Передайте учётные данные реестра через переменные окружения — они нужны только для копирования образов и нигде не сохраняются — и запустите развёртывание:
export DOCKERHUB_USERNAME='<имя пользователя реестра>'
export DOCKERHUB_TOKEN='<токен доступа к реестру>'
./deploy.shПервый запуск занимает 30–40 минут, большую часть из них Azure создаёт среду Container Apps. До того как что-либо создавать, скрипт проверяет инструменты, вход в Azure, лицензию и то, может ли ваша подписка создать PostgreSQL в выбранном регионе. Затем он создаёт сеть, базу данных, Key Vault, хранилище, реестр, среду Container Apps и Redis; копирует образы ScanSuite в ваш реестр; запускает веб-интерфейс и воркеры и выполняет миграцию базы данных. Когда скрипт завершается строкой Done, установка работает, а её адрес — значение вывода url. Повторно вывести значения можно в любой момент командой terraform output.
Если в Docker на этой же машине уже есть образы для кода вашей лицензии, например от установки на сервер, deploy.sh загрузит эти локальные копии вместо копирования из реестра; удалите их заранее, если они могли устареть.
3. Примеры установки
Примеры A и B — готовые файлы terraform.tfvars; C–E — строки, которые добавляются к одному из них. Учётные данные реестра всегда передаются через переменные окружения, как в разделе 2.
A. Пробная установка
Небольшие размеры dev, интерфейс открыт для одного адреса:
subscription_id = "00000000-0000-0000-0000-000000000000"
location = "swedencentral"
resource_group_name = "rg-scansuite-trial"
environment = "dev"
image_tag = "a1b2c3"
web_allowed_cidrs = ["203.0.113.10/32"]
timezone = "Europe/Moscow"
# Холодный старт вместо постоянно прогретого интерфейса: первый вход после
# перерыва ждёт около минуты.
web_min_replicas = 0Когда пробный период закончится, ./destroy.sh удалит всю группу ресурсов.
B. Производственная установка
Зонально-избыточная база данных с резервной копией, зонально-избыточное хранилище, реестр Premium, защита Key Vault от окончательного удаления и выделенный профиль вычислений для сканирований, а также постоянный исходящий адрес и журналы без ограничения объёма:
subscription_id = "00000000-0000-0000-0000-000000000000"
location = "germanywestcentral"
resource_group_name = "rg-scansuite"
environment = "prod"
image_tag = "a1b2c3"
web_allowed_cidrs = ["198.51.100.0/24", "203.0.113.10/32"] # офис и VPN
timezone = "Europe/Moscow"
alert_email = "secops@acme.example"
postgres_sku = "GP_Standard_D2ds_v5"
enable_nat_gateway = true
log_daily_quota_gb = -1Это на несколько сотен долларов в месяц дороже, чем dev. Прежде чем развёртыванием займётся кто-то ещё, перенесите состояние Terraform в Azure Storage, как описано в backend.tf.example.
C. Постоянный исходящий адрес
Иначе исходящий трафик уходит с адреса среды, который может меняться. Если git-сервер или AI-провайдер принимает только адреса из списка, добавьте NAT-шлюз (около 35 долларов в месяц плюс трафик); адрес, который нужно разрешить, будет в выводе egress_ip:
enable_nat_gateway = trueD. Вторая установка в той же подписке
Например, тестовая рядом с производственной. Разворачивайте её из отдельной копии папки, чтобы у неё было своё состояние Terraform (cp -r scansuite/azure scansuite/azure-test), в собственную группу ресурсов. Глобально уникальные имена получают случайный суффикс, так что больше ничего менять не нужно:
resource_group_name = "rg-scansuite-test"E. Регион, где PostgreSQL вам недоступен
Некоторые типы подписок, в том числе Visual Studio, не могут создать PostgreSQL в любом регионе; deploy.sh сообщает об этом, ещё ничего не создав. Выберите другой регион:
location = "swedencentral" # или northeurope, francecentral4. Первый вход
Сразу откройте адрес из вывода url. Новая установка показывает страницу настройки, где создаётся первая учётная запись и задаётся имя команды, — так же, как на сервере, см. Установка ScanSuite Teams. Эта учётная запись достаётся тому, кто первым откроет страницу, поэтому web_allowed_cidrs задаётся до развёртывания.
Затем настройте поставщика ИИ в карточке Системный ИИ раздела Настройки системы → Общие сервисы (или для отдельной команды — в разделе Команды → ИИ → Поставщик ИИ), см. Поставщики ИИ и стоимость. Для Azure OpenAI выберите поставщика OpenAI, укажите адрес v1 вашего ресурса, https://<ресурс>.openai.azure.com/openai/v1, с его ключом API, а в качестве имени модели — имя развёртывания.
5. Повседневная работа
- Изменить настройку: отредактируйте
terraform.tfvarsи снова запустите./deploy.sh. Повторный запуск всегда безопасен, а пока образы не меняются, идущие сканирования продолжаются. - Новый выпуск: положите новый
.licв../key/и удалите старый, задайте вimage_tagновый код, выполнитеgit pull, а затем./deploy.sh. Миграция отменяет незавершённые сканирования, поэтому обновляйтесь, когда сканирований нет. - Прерванные сканирования восстанавливаются сами: сканирование, контейнер которого остановил Azure, 90 минут не показывает прогресса, а затем запускается заново и продолжает AI-анализ с последнего сохранённого этапа.
- Журналы: откройте рабочую область Log Analytics в группе ресурсов, выберите Logs и запросите
ContainerAppConsoleLogs_CLпоContainerAppName_s(например,scansuite-web) илиContainerJobName_s(scansuite-sastдля сканирований). - Экономия, когда установкой не пользуются:
web_min_replicas = 0, а базу данных можно остановить командойaz postgres flexible-server stop; через семь дней Azure запустит её сам. - Берегите состояние Terraform: в
terraform.tfstateхранятся сгенерированные пароли и ваша лицензия. Держите файл в закрытом месте, делайте резервную копию после каждого развёртывания и перенесите его в Azure Storage, прежде чем развёртывать будет второй человек или конвейер CI.
Ориентировочная стоимость в месяц для настроек dev по умолчанию, в долларах США; цены для своего региона уточните в калькуляторе Azure:
| Статья | Ориентировочно |
|---|---|
| Постоянно работающие контейнеры (веб, воркеры, планировщик, Redis) | 120–160 |
| PostgreSQL B_Standard_B1ms, 32 ГБ | 20 |
| Log Analytics, не больше 1 ГБ в день | 0–70 |
| Реестр, Key Vault, хранилище | около 10 |
| Сканирования, по 4 vCPU и 8 ГиБ | около 0,45 за час сканирования |
| NAT-шлюз, если включён | 35 плюс трафик |
6. Удаление
./destroy.shСкрипт просит ввести имя группы ресурсов и примерно за 15 минут удаляет всё, что создало развёртывание, включая базу данных со всеми результатами сканирований; -y отключает вопрос. После этого az group show -n <группа ресурсов> сообщает, что группа не найдена. Если скрипт остановился с сообщением polling support for the Content-Type "" was not implemented, Azure уже удалил то, что в нём названо: запустите скрипт снова, при необходимости два-три раза.
PostgreSQL Flexible Server 16 is not available to this subscription: пример E. ManagedEnvironmentCapacityHeavyUsageError: в регионе сейчас нет места для новой среды; удалите неудавшуюся (az containerapp env delete) и повторите позже или в другом регионе. no licence for image tag: положите .lic в ../key/ и приведите image_tag в соответствие с его кодом. could not import docker.io/appsec4u/...: задайте учётные данные реестра в той же оболочке. Provider produced inconsistent result after apply после повторного создания развёртывания с тем же именем группы ресурсов: возьмите новое имя или подождите 15 минут.
Проверено: 2026-10-01