メインコンテンツまでスキップ

V2 プライベート環境 (Internal-only CAE + Application Gateway)

概要

V2 環境は、セキュリティを強化したプライベート Container Apps 環境です。

項目V1 (従来)V2 (プライベート)
CAE タイプExternalInternal-only
インターネット公開Container App 直接Application Gateway 経由
WAFなしあり (OWASP 3.2)
ネットワーク共有 VNet専用 VNet (10.1.0.0/16)

アーキテクチャ

Internet


┌─────────────────────────────────────┐
│ Cloudflare (SSL/TLS) │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ Application Gateway + WAF │
│ (Per-tenant, Public IP) │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ Container Apps Environment │
│ (Internal-only, shared-v2) │
│ │
│ ├─ Container App (tenant A) │
│ ├─ Container App (tenant B) │
│ └─ Container App (tenant C) │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ Backend Resources (V1 VNet) │
│ ├─ MySQL Flexible Server │
│ ├─ Redis Cache │
│ └─ Storage Account │
└─────────────────────────────────────┘

新規テナントを V2 で作成

1. config.toml を設定

name = "my-company"
template = "monolith" # または "frontend-backend"
template_version = "v1.0.0"

["environments.prd"]
enabled = true
location = "japaneast"
site_url = "https://app.example.com"
use_shared_v2 = true # ← V2 CAE を使用

["environments.prd.frontend"]
image_name = "my-app"
image_tag = "latest"
# ... 他の設定

["environments.prd.application_gateway"]
enabled = true
min_capacity = 1
max_capacity = 3
waf_mode = "Prevention" # または "Detection"

2. デプロイ

# 環境変数を設定
infra decrypt my-company
# .env ファイルを編集
infra encrypt my-company

# Terraform を生成
infra generate my-company prd

# デプロイ
infra plan my-company prd
infra apply my-company prd

3. DNS を設定

# AGW の Public IP を確認
cd terraform/environments/tenants/my-company/prd
terraform output application_gateway_public_ip

DNS プロバイダー(Cloudflare 等)で A レコードを設定:

  • app.example.com<AGW_PUBLIC_IP>

既存テナントを V2 に移行 (Blue-Green デプロイメント)

既存の V1 環境を V2 に移行する場合、Blue-Green デプロイメントで無停止移行が可能です。

概要

  • V1 環境 (prd): 既存の Container App + DB/Redis/Storage
  • V2 環境 (prd-v2): 新しい Container App (V2 CAE) + 既存の DB/Redis/Storage を共有

1. config.toml に prd-v2 環境を追加

# 既存の prd 環境はそのまま維持
["environments.prd"]
enabled = true
location = "japaneast"
site_url = "https://app.example.com"
# ... 既存の設定

# 新しい prd-v2 環境を追加
["environments.prd-v2"]
enabled = true
location = "japaneast"
site_url = "https://app.example.com"
use_shared_v2 = true
shared_resources_from = "prd" # ← DB/Redis/Storage を prd から共有

["environments.prd-v2.frontend"]
# prd と同じ設定をコピー
image_name = "my-app"
image_tag = "latest"
# ...

["environments.prd-v2.application_gateway"]
enabled = true
min_capacity = 1
max_capacity = 3
waf_mode = "Prevention"

2. V2 環境をデプロイ

# Terraform を生成
infra generate my-company prd-v2

# デプロイ(V1 には影響なし)
cd terraform/environments/tenants/my-company/prd-v2
terraform init
terraform plan
terraform apply

3. V2 環境をテスト

# AGW IP を取得
AGW_IP=$(terraform output -raw application_gateway_public_ip)

# 直接テスト
curl -H "Host: app.example.com" http://$AGW_IP

4. DNS を V2 に切り替え

Cloudflare/DNS プロバイダーで:

  • app.example.com の A レコードを V2 AGW IP に変更

5. V1 環境を削除(オプション)

V2 が安定したら、V1 の Container App を削除:

# V1 の Container App のみ削除(DB/Redis/Storage は残す)
# 注意: 手動で Azure Portal から削除するか、Terraform を調整

Application Gateway WAF 設定

WAF モード

モード動作推奨用途
Detectionログのみ、ブロックなしテスト、移行初期
Prevention悪意のあるリクエストをブロック本番環境

よくある誤検知と対策

Next.js/NextAuth アプリケーションでは、以下の誤検知が発生することがあります:

症状原因対策
403 ForbiddenCookie が WAF ルールに該当Cookie 除外設定
403 ForbiddenJSON ボディが SQL インジェクションと誤判定ルール 942430, 942440 を無効化

これらの除外設定は monolith-ca-only モジュールにデフォルトで含まれています。

WAF ログの確認

# Azure Portal で確認
# Application Gateway → Diagnostic settings → WAF logs を有効化

# Log Analytics でクエリ
az monitor log-analytics query \
--workspace <workspace-id> \
--analytics-query "AzureDiagnostics | where Category == 'ApplicationGatewayFirewallLog' | where action_s == 'Blocked'"

ネットワーク構成

VNet CIDR

VNetCIDR用途
V1 shared (JP)10.0.0.0/16既存環境
V2 shared10.1.0.0/16プライベート CAE

サブネット

V2 shared (10.1.0.0/16):

サブネットCIDR用途
App Gateway10.1.0.0/24Application Gateway
Container App10.1.64.0/18Container Apps
Database10.1.128.0/19(未使用、V1 と共有)

NSG ルール

V1/V2 間の通信を許可するため、以下の NSG ルールが自動設定されます:

  • V1 db-nsg: V2 CA サブネット → V1 DB サブネット (MySQL 3306)
  • V2 container-app-nsg: V2 CA → V1 DB サブネット (Outbound)

SSL/TLS 設定

Cloudflare を使用する場合(推奨)

Cloudflare Proxy を有効にすると、SSL は Cloudflare が処理します:

  1. Cloudflare で DNS レコードを設定(Proxy: ON)
  2. SSL/TLS モード: Flexible または Full
  3. AGW は HTTP のままで OK
User → HTTPS → Cloudflare → HTTP → AGW → Container App

AGW で SSL 終端する場合

Key Vault に証明書をアップロードし、config.toml で指定:

["environments.prd.application_gateway"]
enabled = true
custom_domain = "app.example.com"
ssl_certificate_key_vault_secret_id = "https://my-keyvault.vault.azure.net/secrets/my-cert"

トラブルシューティング

Container App が DB に接続できない

原因: NSG ルールが不足

解決策:

# shared 環境の v2 統合を有効化
cd terraform/environments/shared
# main.tf で enable_v2_integration = true を確認
terraform apply

# shared-v2 環境の v1 DB アクセスを有効化
cd terraform/environments/shared-v2
# main.tf で enable_v1_db_access = true を確認
terraform apply

WAF が正当なリクエストをブロック

原因: OWASP ルールの誤検知

解決策:

  1. WAF ログで blocked ルール ID を確認
  2. config.toml または Terraform で除外設定を追加

DNS 解決ができない

原因: ローカル DNS キャッシュ

解決策:

# Mac
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

# テスト
dig app.example.com @8.8.8.8

関連ドキュメント