Skip to content

課題21: 金融系SaaSのセキュア基盤構築

難易度: 🟡 中級


1. 分類情報

項目内容
難易度中級
カテゴリセキュリティ
処理タイプリアルタイム
使用IaCCloudFormation
想定所要時間5-6時間

2. シナリオ

企業プロファイル

項目内容
企業名〇〇株式会社
業種投資管理SaaS
従業員数60名(エンジニア20名)
顧客数機関投資家・資産運用会社100社
管理資産額10兆円相当のデータ管理
規制要件金融庁ガイドライン、FISC安全対策基準

現状の課題

〇〇株式会社は機関投資家向けの投資管理SaaSを提供しています。
金融庁の監督指針対応において以下の課題を抱えています:

1. ネットワークセキュリティの不備
   - パブリックサブネットにアプリケーションが配置
   - インターネット経由でのAWSサービスアクセス
   - セグメンテーションが不十分

2. 認証情報管理の問題
   - データベースパスワードが環境変数にハードコード
   - APIキーがソースコードに含まれている
   - シークレットのローテーションが手動

3. アクセス制御の課題
   - IPアドレス制限が不完全
   - WAFが未導入
   - 監査ログが不十分

4. コンプライアンス対応
   - 金融庁ガイドラインへの対応が不完全
   - セキュリティ監査で指摘事項あり
   - 顧客からのセキュリティ質問への回答に時間がかかる

ビジネス目標

KPI現状目標
セキュリティ監査スコア60点90点以上
金融庁ガイドライン準拠率70%100%
シークレットローテーション手動(年1回)自動(90日ごと)
インシデント検知時間数時間5分以内
セキュリティ質問対応3日即日

3. 達成目標(ゴール)

主要な学習成果

この課題を完了すると、以下ができるようになります:

1. セキュアなVPC設計
   - マルチAZ構成とサブネット分離
   - VPCエンドポイントによるプライベートアクセス
   - ネットワークACLとセキュリティグループの多層防御

2. AWS PrivateLinkの活用
   - VPCエンドポイントサービスの構築
   - Interface/Gateway Endpoint の使い分け
   - プライベートなサービス連携

3. AWS WAFによるWebアプリケーション保護
   - マネージドルールの適用
   - カスタムルールの作成
   - レート制限とIP制限

4. AWS Secrets Managerによる認証情報管理
   - シークレットの安全な保存
   - 自動ローテーションの設定
   - アプリケーション統合

合格基準

項目基準
VPC設計プライベートサブネットにアプリが配置されていること
PrivateLinkAWSサービスへのアクセスがVPCエンドポイント経由であること
WAF主要な攻撃パターンがブロックされること
SecretsDBパスワードがSecrets Managerで管理されていること
監査CloudTrailで全アクションが記録されていること

4. 使用するAWSサービス

コア技術スタック

yaml
ネットワーク:
  - Amazon VPC: 仮想ネットワーク
  - VPC Endpoints: プライベートサービスアクセス
  - AWS PrivateLink: サービス間プライベート接続
  - AWS Transit Gateway: VPC間接続(オプション)
  - Network Firewall: 高度なトラフィック制御(オプション)

Webアプリケーション保護:
  - AWS WAF: Webアプリケーションファイアウォール
  - AWS Shield: DDoS保護
  - Amazon CloudFront: CDN + WAF統合

認証情報管理:
  - AWS Secrets Manager: シークレット管理・ローテーション
  - AWS Systems Manager Parameter Store: 設定パラメータ
  - AWS KMS: 暗号化キー管理

アクセス制御:
  - AWS IAM: 認証・認可
  - IAM Identity Center: SSO
  - AWS Organizations: マルチアカウント管理

監視・監査:
  - AWS CloudTrail: API監査ログ
  - Amazon GuardDuty: 脅威検知
  - AWS Config: 構成管理
  - AWS Security Hub: セキュリティ統合ダッシュボード

5. 前提条件

技術要件

bash
# 必要なCLIツール
aws --version          # 2.x
terraform --version    # 1.5+

# AWS設定
aws configure
export AWS_REGION=ap-northeast-1
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

事前準備

bash
# プロジェクト構造
secure-infra/
├── terraform/
   ├── main.tf
   ├── vpc.tf
   ├── endpoints.tf
   ├── waf.tf
   ├── secrets.tf
   ├── security_groups.tf
   ├── iam.tf
   └── variables.tf
├── policies/
   ├── waf-rules.json
   └── iam-policies/
└── docs/
    └── security-architecture.md

6. アーキテクチャ図

全体構成

コンポーネント役割
Userユーザー
AWS ShieldDDoS保護
CloudFront WAFCDN + WAF(L7保護)
ALBApplication Load Balancer
NAT Gatewayプライベートサブネットの外部通信
ECS Fargateコンテナ実行環境
API/Portfolio/Report Serviceマイクロサービス群
RDS PostgreSQLデータベース(Multi-AZ)
VPC EndpointsAWSサービスへのプライベート接続
Secrets KMS認証情報の暗号化管理

WAF Rules: SQL Injection, XSS, Rate Limit, IP Block, Geo Block

Security Groups:

  • alb-sg: Inbound 443 from CloudFront IPs only
  • app-sg: Inbound 8080 from alb-sg only, Outbound 443 to VPC Endpoints only
  • db-sg: Inbound 5432 from app-sg only, Encrypted with KMS CMK

Secrets Manager: finance-app/db/credentials, finance-app/api/keys, finance-app/external/tokens (Rotation: 90 days)

セキュリティレイヤー


7. トラブルシューティングチャレンジ

Challenge 1: VPCエンドポイント経由でSecrets Managerにアクセスできない

問題:
ECSタスクからSecrets Managerへのアクセスがタイムアウトする。
VPCエンドポイントを設定したはずだが機能しない。

エラーログ:
botocore.exceptions.ConnectTimeoutError:
Connect timeout on endpoint URL: "https://secretsmanager.ap-northeast-1.amazonaws.com"

調査項目:
1. VPCエンドポイントの設定
2. セキュリティグループ
3. DNS設定
解決のヒント
bash
# 1. VPCエンドポイントの状態確認
aws ec2 describe-vpc-endpoints \
    --filters "Name=service-name,Values=com.amazonaws.ap-northeast-1.secretsmanager" \
    --query "VpcEndpoints[*].{ID:VpcEndpointId,State:State,DNS:DnsEntries}"

# 2. Private DNSが有効か確認
# private_dns_enabled = true である必要がある

# 3. セキュリティグループ確認
aws ec2 describe-security-groups \
    --group-ids sg-vpce-xxx \
    --query "SecurityGroups[0].IpPermissions"

# Inbound: 443 from VPC CIDR が必要

# 4. ECSタスクのセキュリティグループ確認
# Outbound: 443 to VPCE Security Group が必要

# 5. ルートテーブル確認(S3エンドポイントがGateway型の場合)
aws ec2 describe-route-tables \
    --route-table-ids rtb-xxx

# 6. DNS解決テスト(ECSタスク内から)
nslookup secretsmanager.ap-northeast-1.amazonaws.com
# VPCエンドポイントのプライベートIPが返されるべき

# 解決策:
# - private_dns_enabled = true を設定
# - セキュリティグループでHTTPS許可
# - サブネットにVPCエンドポイントを配置

Challenge 2: WAFでブロックされるべきリクエストが通過する

問題:
SQLインジェクション攻撃がWAFをバイパスしてアプリケーションに到達している。

ログ:
WAF: ALLOW
Application: SQL Injection detected in parameter 'search'

攻撃例:
/api/search?q=1%27%20OR%20%271%27%3D%271

調査項目:
1. WAFルールの設定
2. ルールの優先順位
3. エンコーディング
解決のヒント
bash
# 1. WAFルールのテスト
aws wafv2 get-sampled-requests \
    --web-acl-arn arn:aws:wafv2:...:webacl/finance-app-web-acl \
    --rule-metric-name AWSManagedRulesSQLiRuleSetMetric \
    --scope CLOUDFRONT \
    --time-window StartTime=...,EndTime=... \
    --max-items 100

# 2. SQLiルールがCOUNTモードになっていないか確認
# override_action { count {} } ではなく none {} である必要

# 3. Text Transformationの追加
# URL_DECODEを追加してエンコードされた攻撃を検知

# terraform/waf.tf に追加
rule {
  name     = "CustomSQLiRule"
  priority = 2

  action {
    block {}
  }

  statement {
    sqli_match_statement {
      field_to_match {
        query_string {}
      }
      text_transformation {
        priority = 0
        type     = "URL_DECODE"
      }
      text_transformation {
        priority = 1
        type     = "HTML_ENTITY_DECODE"
      }
      text_transformation {
        priority = 2
        type     = "LOWERCASE"
      }
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "CustomSQLiRuleMetric"
    sampled_requests_enabled   = true
  }
}

# 4. CloudFront経由でのみアクセス可能にする
# ALBのセキュリティグループでCloudFront IPsのみ許可

Challenge 3: シークレットローテーション後にアプリケーションが接続エラー

問題:
Secrets Managerの自動ローテーション実行後、
アプリケーションがデータベースに接続できなくなった。

エラー:
psycopg2.OperationalError: FATAL: password authentication failed for user "app_user"

調査項目:
1. ローテーションLambdaの実行ログ
2. シークレットのバージョン
3. アプリケーションのキャッシュ
解決のヒント
bash
# 1. シークレットのバージョン確認
aws secretsmanager list-secret-version-ids \
    --secret-id finance-app/db/credentials

# AWSCURRENT と AWSPREVIOUS を確認

# 2. ローテーションLambdaのログ確認
aws logs get-log-events \
    --log-group-name /aws/lambda/finance-app-secret-rotation \
    --log-stream-name $(aws logs describe-log-streams \
        --log-group-name /aws/lambda/finance-app-secret-rotation \
        --order-by LastEventTime --descending \
        --query "logStreams[0].logStreamName" --output text)

# 3. 実際のシークレット値確認
aws secretsmanager get-secret-value \
    --secret-id finance-app/db/credentials \
    --query SecretString --output text | jq .

# 4. データベースでパスワード確認(手動テスト)
psql -h xxx.rds.amazonaws.com -U app_user -d finance-app

# 5. アプリケーションのキャッシュクリア
# @lru_cache を使用している場合、キャッシュをクリア

# 解決策:
# a) アプリケーションでシークレットのキャッシュTTLを設定
# b) ローテーション時のエラーハンドリング改善
# c) データベース接続のリトライロジック追加

# キャッシュTTL付きの実装例
from cachetools import TTLCache

class SecretsManager:
    def __init__(self):
        self.cache = TTLCache(maxsize=10, ttl=300)  # 5分キャッシュ

    def get_secret(self, secret_name):
        if secret_name in self.cache:
            return self.cache[secret_name]

        secret = self._fetch_secret(secret_name)
        self.cache[secret_name] = secret
        return secret

8. 設計考慮ポイント

金融庁ガイドライン対応マッピング

yaml
金融機関のシステムリスク管理基準:

1. アクセス管理:
   対応: IAM, VPC Security Groups, WAF IP制限
   証跡: CloudTrail, VPC Flow Logs

2. ネットワーク管理:
   対応: VPC分離, PrivateLink, Network ACL
   証跡: VPC Flow Logs, Config

3. 暗号化:
   対応: KMS (AES-256), TLS 1.2+, RDS暗号化
   証跡: KMS監査ログ, Config Rules

4. 監査ログ:
   対応: CloudTrail, CloudWatch Logs
   保持: 7年以上

5. 脆弱性管理:
   対応: WAF, GuardDuty, Security Hub
   対応: ECRスキャン, Inspector

6. インシデント対応:
   対応: GuardDuty, Security Hub, SNS通知
   手順: ランブック自動化

コスト vs セキュリティのトレードオフ

High Security(本課題構成)

項目月額コスト
Multi-AZ NAT Gateway$90
VPC Endpoints (8個)$80
WAF$10 + $0.60/100万リクエスト
GuardDuty$4〜
CloudTrail$2〜
合計約$190

セキュリティレベル: ★★★★★

Medium Security(代替構成)

項目月額コスト
Single NAT Gateway$45
主要VPC Endpoints (3個)$30
WAF$10
合計約$85

セキュリティレベル: ★★★☆☆

結論: 金融系では High Security が必須


9. 発展課題

上級チャレンジ1: ゼロトラストアーキテクチャ

yaml
# AWS Verified Access による実装

ゼロトラスト原則:
  - Never trust, always verify
  - Assume breach
  - Verify explicitly

実装コンポーネント:
  - AWS Verified Access: アプリケーションアクセス制御
  - IAM Identity Center: 統合認証
  - Device Trust: デバイス検証
  - Continuous Verification: 継続的な認証

# Verified Access Trust Provider
resource "aws_verifiedaccess_trust_provider" "oidc" {
  policy_reference_name = "finance-app-idp"
  trust_provider_type   = "user"

  oidc_options {
    authorization_endpoint = "https://idp.finance-app.example/authorize"
    client_id              = var.oidc_client_id
    client_secret          = var.oidc_client_secret
    issuer                 = "https://idp.finance-app.example"
    token_endpoint         = "https://idp.finance-app.example/token"
    user_info_endpoint     = "https://idp.finance-app.example/userinfo"
    scope                  = "openid profile email"
  }
}

上級チャレンジ2: SOC2/SOC3レポート対応

yaml
# AWS Artifact + 自社監査証跡

SOC2 Type II 対応項目:

Security:
  - 実装: WAF, Security Groups, KMS
  - 証跡: CloudTrail, Config

Availability:
  - 実装: Multi-AZ, Auto Scaling
  - 証跡: CloudWatch, Health Dashboard

Processing Integrity:
  - 実装: Lambda検証, データ整合性チェック
  - 証跡: アプリケーションログ

Confidentiality:
  - 実装: 暗号化, VPC分離, IAM
  - 証跡: KMS監査ログ, Access Analyzer

Privacy:
  - 実装: データ分類, アクセス制御
  - 証跡: Macie, IAM Access Analyzer

上級チャレンジ3: セキュリティ自動修復

python
# Lambda: GuardDuty検知時の自動対応

import boto3
import json

def lambda_handler(event, context):
    """
    GuardDuty検知イベントに対する自動対応
    """
    finding = event['detail']
    finding_type = finding['type']
    severity = finding['severity']

    # 重大度に応じた対応
    if severity >= 7:
        # 高重大度: 即座にブロック
        handle_high_severity(finding)
    elif severity >= 4:
        # 中重大度: アラート + 調査開始
        handle_medium_severity(finding)
    else:
        # 低重大度: ログ記録のみ
        log_finding(finding)


def handle_high_severity(finding):
    """高重大度の検知への対応"""
    ec2 = boto3.client('ec2')
    wafv2 = boto3.client('wafv2')

    finding_type = finding['type']

    if 'UnauthorizedAccess' in finding_type:
        # 不正アクセス: IPをWAFでブロック
        source_ip = finding['service']['action']['networkConnectionAction']['remoteIpDetails']['ipAddressV4']
        block_ip_in_waf(wafv2, source_ip)

    elif 'CryptoCurrency' in finding_type:
        # マイニング検知: インスタンス隔離
        instance_id = finding['resource']['instanceDetails']['instanceId']
        isolate_instance(ec2, instance_id)

    # SNS通知
    notify_security_team(finding)


def block_ip_in_waf(client, ip_address):
    """WAFのIPブロックリストにIPを追加"""
    client.update_ip_set(
        Name='finance-app-ip-block-list',
        Scope='CLOUDFRONT',
        Id='xxx',
        Addresses=[f"{ip_address}/32"],
        LockToken='xxx'
    )


def isolate_instance(client, instance_id):
    """インスタンスを隔離用セキュリティグループに変更"""
    # 全トラフィックを拒否するSGに変更
    client.modify_instance_attribute(
        InstanceId=instance_id,
        Groups=['sg-isolation']
    )

10. コスト見積もり

月額コスト概算

サービススペック月額コスト
NAT Gateway2 × Multi-AZ$90
VPC Endpoints8 Interface Endpoints$80
WAFWeb ACL + ルール$15
Secrets Manager5 シークレット$2
KMS3 CMK$3
CloudTrailMulti-region$2
GuardDuty基本$5
Config基本$3
CloudWatch Logs10GB$5
合計約 $205/月

ROI分析

セキュリティ投資対効果:

コスト:
- 月額インフラ追加費用: $205
- 年間: $2,460

リスク軽減効果:
- データ漏洩時の想定被害: 1億円〜
- セキュリティインシデントによる信用失墜: 計り知れない
- 金融庁による行政処分リスク: 事業継続に影響

ROI:
- セキュリティ投資は保険として考える
- 金融業界では必須投資
- 顧客獲得時のセキュリティ質問対応が容易に

11. 学習のポイント

今回学んだこと

1. セキュアなVPC設計
   □ サブネット分離(Public/Private/Data)
   □ セキュリティグループの多層防御
   □ Network ACLによる追加防御

2. VPCエンドポイント
   □ Interface vs Gateway Endpoint
   □ PrivateLink によるプライベート接続
   □ エンドポイントポリシー

3. AWS WAF
   □ マネージドルールの活用
   □ カスタムルールの作成
   □ レート制限とIP制限

4. Secrets Manager
   □ シークレットの安全な保存
   □ 自動ローテーション
   □ アプリケーション統合

5. 監査とコンプライアンス
   □ CloudTrail
   □ AWS Config
   □ Security Hub

次のステップ

1. 発展学習:
   - AWS Network Firewall
   - AWS Verified Access
   - AWS Macie (データ分類)

2. 認定対応:
   - FISC安全対策基準
   - PCI DSS
   - ISO 27001

3. 認定資格:
   - AWS Certified Security - Specialty
   - AWS Certified Solutions Architect - Professional