Почему штатные health checks ломают безопасность AgentCore?
Вы развернули Amazon Bedrock AgentCore за Application Load Balancer, чтобы централизованно контролировать трафик. Всё работает. Потом ставите AWS WAF — и ваш агент перестаёт отвечать. Причина не в WAF как таковом, а в health check'ах: балансировщик стучится на /health, WAF блокирует этот запрос, и target group помечает инстанс как нездоровый. Звучит знакомо?
Проблема в том, что AgentCore Runtime по умолчанию не требует аутентификации на эндпоинте /health. Любой может дёрнуть этот путь. Но если открыть его для всех, WAF теряет смысл. Нужен компромисс: разрешить health checks от балансировщика, но заблокировать всё остальное. Казалось бы, элементарно — добавить allow rule по User-Agent. Но на практике AWS Health Checker использует разные заголовки в зависимости от типа проверки, и документация в этом месте традиционно отстаёт от реальности.
В этой статье мы разберём три уровня защиты: от быстрого «костыля» до архитектурно правильного решения с VPC Lattice и AWS WAF. Все примеры актуальны на июль 2026 года.
Куда именно стучится ALB?
Первое, что нужно понять — какой health check использует ваш Amazon Bedrock AgentCore. Если вы не меняли настройки, ALB по умолчанию шлёт GET на корень "/" или на "/health" — зависит от версии AgentCore Runtime. Начиная с AgentCore v2.1.0 (релиз мая 2026), контейнер отвечает на /health статусом 200 без тела. Это сделано специально, чтобы балансировщик не ждал ответа от генеративной модели — иначе health check зависал бы на 30 секунд.
Заголовки запроса от ALB выглядят так:
GET /health HTTP/1.1
Host: your-alb-123456.elb.amazonaws.com
User-Agent: ELB-HealthChecker/2.0
Accept: */*
Connection: close
Если вы используете Network Load Balancer (NLB) с целевой группой типа IP, health check может приходить с произвольным User-Agent, и тогда опора на заголовок становится ненадёжной. В таком случае единственный вариант — allow по source IP диапазонам AWS Health Checker, но они меняются. AWS публикует их в ip-ranges.json, и вам придётся регулярно обновлять правила.
Не советую разрешать health checks по IP без автоматического обновления — через месяц правила устареют, и ваш ALB начнёт снимать target group. Лучше заморочиться с Lambda-функцией, которая раз в сутки подтягивает свежие диапазоны.
Архитектура: WAF + AgentCore + VPC Endpoint
Правильная схема выглядит так: клиент -> ALB (с WAF ACL) -> Target Group (AgentCore) -> VPC Endpoint (для вызовов Bedrock API). WAF висит на ALB, а AgentCore внутри VPC не имеет публичного доступа. health check от ALB к AgentCore идёт через ту же сеть.
Мы уже писали о том, как затащить AgentCore в VPC. Теперь добавим слой WAF. Ключевой момент: WAF ACL ассоциируется с ALB, а не с AgentCore напрямую. Поэтому все правила, включая allow для health checks, пишутся на уровне балансировщика.
1 Создаём WAF ACL и правило для health checks
Используем Terraform (актуальные провайдеры на июль 2026 — версия ~5.80 для AWS). Правило должно быть с наивысшим приоритетом (0), чтобы WAF не успел заблокировать health check до проверки.
resource "aws_wafv2_web_acl" "bedrock_waf" {
name = "bedrock-agentcore-waf"
scope = "REGIONAL"
default_action {
block {}
}
rule {
name = "allow-health-check"
priority = 0
action {
allow {}
}
statement {
byte_match_statement {
field_to_match {
single_header {
name = "user-agent"
}
}
positional_constraint = "EXACTLY"
search_string = "ELB-HealthChecker/2.0"
text_transformation {
priority = 0
type = "NONE"
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AllowHealthCheck"
sampled_requests_enabled = true
}
}
}
Обратите внимание: мы сравниваем заголовок user-agent регистрозависимо. Если ваш ALB шлёт User-Agent с другим регистром (например, "ELB-HealthChecker/2.0" vs "elb-healthchecker/2.0") — правило не сработает. В AWS консистентность имени заголовка гарантируется, но на всякий случай можно использовать string_match с insensitive.
2 Добавляем правила безопасности для AgentCore
После allow-правила для health checks идут rate-based, IP blacklist, SQLi/XSS фильтры. Важный нюанс: AgentCore принимает JSON-запросы на /invoke, и они могут содержать произвольный текст — high risk срабатывания для body-правил. Рекомендую исключить /invoke из проверки тела запроса, если у вас нет дополнительной валидации.
resource "aws_wafv2_web_acl" "bedrock_waf" {
# ... предыдущий код ...
rule {
name = "rate-limit"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
limit = 5000
aggregate_key_type = "IP"
scope_down_statement {
not_statement {
statement {
byte_match_statement {
field_to_match {
single_header {
name = "user-agent"
}
}
positional_constraint = "EXACTLY"
search_string = "ELB-HealthChecker/2.0"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimit"
sampled_requests_enabled = true
}
}
}
Rate limit в 5000 запросов в минуту с одного IP — разумный порог для агента, который обрабатывает до 80 запросов в секунду. Если ожидаете больше — поднимите.
3 Ассоциируем ACL с ALB
resource "aws_wafv2_web_acl_association" "alb_association" {
resource_arn = aws_lb.bedrock_alb.arn
web_acl_arn = aws_wafv2_web_acl.bedrock_waf.arn
}
Типичные ошибки и как их избежать
- Health check идёт не на /health. Если вы изменили путь в target group — не забудьте отразить это в WAF. Лучше добавить второе правило для allow по path.
- User-Agent меняется. Некоторые AWS сервисы (CloudFront, Global Accelerator) проксируют запросы и меняют User-Agent. Проверьте логи WAF — какой именно заголовок приходит.
- Rate limit срабатывает на health checks. В Terraform выше мы вынесли health checks из скоупа rate limit с помощью scope_down_statement. Без этого WAF заблокирует собственные проверки, как только частота превысит лимит.
- Включён AWS WAF Bot Control. Правило "Common Bot" может заблокировать health check от ALB, если бот-правило имеет более высокий приоритет. Решение: либо отключать Bot Control для пути /health, либо ставить allow-правило по User-Agent с приоритетом ниже, чем у бот-правила.
Мониторинг через CloudWatch
После деплоя обязательно проверьте, что health checks проходят. Для этого используйте метрики WAF: AllowedCount и BlockedCount. Если в AllowedCount нет запросов с именем правила AllowHealthCheck — что-то пошло не так.
Мы недавно разбирали, как настраивать алерты на CloudWatch метрики для Bedrock. Добавьте алерт на BlockedCount по правилу health check — если он >0, значит что-то блокирует ваши проверки.
Совместимость с Bedrock Guardrails
WAF защищает транспортный уровень, но не контент. Чтобы фильтровать вредоносные промпты и ответы модели, используйте Amazon Bedrock Guardrails. В комбинации с WAF получаете защиту на двух уровнях: сетевой (WAF) и контентный (Guardrails).
Единственное ограничение — Guardrails не работают с запросами к /health, так как там нет промпта. Поэтому health check продолжает быть точкой входа, которую WAF должен пропускать.
Когда WAF не нужен: альтернативы
Если ваш AgentCore работает строго внутри VPC и клиенты обращаются через VPC Endpoint (Interface Endpoint) — WAF на ALB избыточен. Достаточно security groups и network ACLs. Но если вы выставляете агента наружу, WAF обязателен.
В некоторых архитектурах используют AWS CloudFront как прокси с WAF перед ALB. В этом случае health check от CloudFront к ALB имеет User-Agent "Amazon CloudFront" — и правило нужно корректировать. Сценарий редкий, но для высоконагруженных систем оправдан.
Заключительный совет: не кидайте в продакшн не тестируя
Перед тем как ассоциировать WAF с продакшн ALB, создайте тестовый балансировщик и прогоните скрипт, который эмулирует health checks с разными User-Agent. AWS WAF позволяет включить режим "count" для правил — используйте его, чтобы понять, какие запросы проходят, не блокируя их. И только когда все health checks зелёные, переключайте ACL в режим "block".
Помните: сломанный health check может положить весь AgentCore, а WAF об этом не сообщит — он честно заблокирует то, что вы попросили. Лучше потратить час на отладку, чем потом искать причину деградации сервиса.