GuardDuty 組織統合設計書
1. 目的・スコープ
目的
GuardDutyの組織統合を行い、Organization全体の脅威検知を一元管理する。 これにより以下を実現する。
- ctop-production(本番)を含む未導入アカウントに脅威検知を適用
- 全アカウントのfindingsをDelegated Adminに集約
- ルートユーザー利用の検知(MFA設定ができない場合の代替策)
- 新規アカウント追加時の自動有効化
スコープ
- GuardDuty組織統合の設計・構築
- Delegated Admin登録
- 保護プランの選択
- Findingsエクスポート設定(S3 + KMS)
- SCP②のNotActionに
guardduty:*を追加(全リージョン有効化のため) - 通知設計は別途実施
前提
- OU・アカウント構成はOU・アカウント設計書に従う
- SCP設計はSCP設計書に従う
- Terraform運用はTerraform運用設計書に従う
2. 現状と課題
現状(2026-06-26時点)
GuardDuty導入済み(7アカウント — 個別導入):
・production (967691968827)
・fd-sys (913831226605)
・staging (301608970378)
・infra-dev (853790572692)
・develop (900176301532) ← SNSサブスクリプション空(通知されていない)
・踏み台 (770217130318)
・外部連携 (866741171210)
設定:
・Detector有効、finding頻度: 1時間
・Runtime Monitoring有効(ECS Fargate Agent Management有効)
・EKS Audit Logs無効
・Findings: S3にエクスポート + KMS暗号化
・通知: EventBridge(severity >= 7)→ SNS → AWS Chatbot → Slack
・Terraform管理: platform/guarddutyモジュール
GuardDuty未導入(6アカウント):
・ctop-staging (323155024650)
・ctop-production (324454774785) ← ⚠️ 本番環境
・cc-poc (499591337329)
・マネジメント (703480710002)
・fd-security-tooling (860801568046)
・fd-log-archive (385800115893)
招待ベースの管理関係: なし(確認済み)課題
| # | 課題 | リスク |
|---|---|---|
| 1 | ctop-production(本番)に脅威検知がない | 不正アクセスを検知できない |
| 2 | developのSNSサブスクリプションが空 | findingsが通知されていない |
| 3 | 個別導入で管理が分散 | 一元的なfindings管理・対応ができない |
| 4 | 新規アカウント追加時に個別導入が必要 | 導入漏れのリスク(実際にctop系・cc-pocで発生) |
| 5 | 許可リージョン(4リージョン)のみ有効化 | 未使用リージョンでの不正行為を検知できない |
3. アーキテクチャ
全体構成
組織統合の動作
組織統合を有効化すると:
・既存Detector(7アカウント): 自動的にDelegated Adminの配下に入る
・未導入アカウント(6アカウント): 自動的にGuardDutyが有効化される
・既存findingsは引き継がれる
・新規アカウントがOrganizationに追加された場合も自動有効化
・Delegated Adminから全アカウントのfindingsを一元管理4. 組織統合の設定内容
自動有効化設定
| 項目 | 設定値 | 理由 |
|---|---|---|
| GuardDuty自動有効化 | ALL(全メンバー) | 既存・新規アカウント全てに適用 |
| Finding頻度 | ONE_HOUR | 既存設定と同じ |
保護プラン
| 保護プラン | 設定値 | 理由 |
|---|---|---|
| S3 Protection | 有効 | S3のデータ窃取・破壊検知。Extended Threat Detection連携 |
| EKS Protection(Audit Logs) | 無効 | EKSを使用していない |
| Runtime Monitoring | 有効 | メインでECS Fargateを使ってサービスを構築しており、コンテナのランタイム監視が必要 |
| - ECS Fargate Agent Management | 有効 | ECS Fargateタスクのプロセス・ネットワーク・ファイル操作をリアルタイム監視 |
| - EC2 Agent Management | 有効(既存は無効→有効化) | 踏み台・プロキシ等のEC2を利用しているため有効化する |
| - EKS Addon Management | 無効 | EKSを使用していない |
| Malware Protection for EC2 | 有効 | EBSボリュームのマルウェアスキャン |
| Malware Protection for S3 | 有効(4バケット個別設定) | 対象バケット選定完了(調査結果参照)。Delegated Adminから設定不可のため各アカウントで個別設定。詳細は「Malware Protection for S3 設計」セクション参照 |
| RDS Protection | 有効 | RDSログイン異常検知。本番DBの保護 |
| Lambda Protection | 有効 | Lambda通信の脅威検知 |
| Malware Protection for Backup | 無効 | 一部AWS Backupを使用しているが、現時点では不要。必要になったら検討 |
| Extended Threat Detection | 有効(デフォルト) | マルチステージ攻撃の検知。追加コストなし。自動有効化 |
マルチリージョン有効化
AWS公式推奨: 全サポートリージョンでGuardDutyを有効化する
理由:
・未使用リージョンでの不正アクティビティ(マイニング用EC2起動等)を検知
・IAMなどグローバルサービスの検知にも必要
・SCPでリソース作成は制限されているが、SCPが適用されないマネジメントアカウントの侵害や
SCP設定ミスによるリージョン制限の漏れがあった場合の検知層として機能
対応:
・SCP②(リージョン制限)のNotActionにguardduty:*を追加
・全サポートリージョンでGuardDutyを有効化
・Delegated Adminから各リージョンの設定を管理
有効化対象リージョン:
・全サポートリージョン(Delegated Adminの自動有効化で対応)
・各リージョンでDelegated Admin登録が必要(リージョンごとの操作)5. Findingsエクスポート
エクスポート設定
GuardDutyのfindings保持期間は90日。長期保存のためS3にエクスポートする。
エクスポート先: fd-log-archive (385800115893)
・S3バケット: fd-guardduty-findings(新規作成)
・KMS暗号化: 専用キーで暗号化
・ライフサイクル: CloudTrailと同じ方針
Standard(365日) → Glacier(2555日/7年) → 削除
保存期間の根拠:
・監査要件ガイドラインではセキュリティログは1年間保存
参考: docs/sre/incident-response/audit-requirements-guidelines.md
・ただしCloudTrail、Config、Security Hub等の監査系サービスのログとの
相関分析が必要になるケースがあるため、同じ7年保存とする
・Findingsのデータ量は少ないためコスト差はほぼなし
S3のFindings分析:
・AthenaでFindingsを分析する想定
・Athenaのデータベース・テーブル設計、運用設計については今後の検討タスクとする
既存の各アカウントのS3エクスポート:
・組織統合後もそのまま動作する(影響なし)
・Delegated Adminからの集約エクスポートに移行後、段階的に廃止6. SCP修正
SCP②のNotActionに guardduty:* を追加
目的: 全リージョンでGuardDutyを有効化するため、リージョン制限から除外する
修正対象: scp_policies/deny_non_approved_regions.json
追加: "guardduty:*"
理由:
・AWS公式推奨で全サポートリージョンでの有効化が推奨されている
・SCPでリージョン制限されていても、GuardDutyは全リージョンで脅威を検知する必要がある
・AWS Control Towerのリージョン制限SCPでもguardduty:*は除外されている
・GuardDutyの設定変更はDelegated Adminからのみ可能(SCP①でDeleteDetectorをDeny済み)7. Terraform管理
リソース配置
fd-security-tooling(Terraform):
・aws_guardduty_detector — Delegated Admin用Detector
・aws_guardduty_organization_configuration — 組織統合設定
・aws_guardduty_publishing_destination — Findingsエクスポート設定(fd-log-archiveのS3を指定)
コードの配置:
fastdoctor-template/common/security-tooling/guardduty.tf
fd-log-archive(Terraform):
・aws_s3_bucket — Findingsエクスポート用バケット
・aws_s3_bucket_policy — GuardDutyサービスからの書き込み許可
・aws_kms_key — Findings暗号化キー
コードの配置:
fastdoctor-template/common/log-archive/guardduty.tf
マネジメントアカウント(手動操作):
・GuardDuty有効化
・Delegated Admin登録(各リージョンで実施)
→ Terraform管理しない(マネジメントアカウントにTerraform環境を置かない方針)既存のTerraformモジュールとの関係
既存: template_modules/common/platform/guardduty/
・各アカウントで個別にDetector、S3エクスポート、SNS通知を管理
・組織統合後もDetector自体は引き継がれる
・通知設定(EventBridge → SNS)は既存のまま動作
組織統合で追加:
・fd-security-toolingに組織統合設定を追加
・fd-log-archiveに集約エクスポート先を追加
・既存モジュールの即時削除は不要(段階的に整理)8. 適用手順
Step 1: SCP修正(最初に実施)
SCP②のNotActionにguardduty:*を追加
→ fd-security-toolingでterraform apply
※ 全リージョンでGuardDutyを有効化するため、先にSCPを修正しておくStep 2: マネジメントアカウントでGuardDuty有効化 + Delegated Admin登録
コンソール:
1. GuardDuty コンソールを開く
2. 「Get Started」→「Enable GuardDuty」
3. Settings → Delegated Administrator → fd-security-tooling (860801568046) を登録
CLI:
aws guardduty enable-organization-admin-account \
--admin-account-id 860801568046 \
--region ap-northeast-1
※ 各リージョンで実施が必要(リージョンごとにDelegated Admin登録)
※ マネジメントアカウントでGuardDuty未有効化の場合、
Delegated Admin登録時に自動有効化されるStep 3〜5: 構築
Step 3: fd-log-archiveにFindingsエクスポート用S3バケット・KMSキーを作成
→ fastdoctor-template/common/log-archive/ でterraform apply
Step 4: fd-security-toolingで組織統合設定を作成
→ fastdoctor-template/common/security-tooling/ でterraform apply
・Detector作成
・自動有効化設定(ALL)
・保護プラン設定
・Findingsエクスポート設定(fd-log-archiveのS3を指定)
Step 5: 動作確認
・全アカウントでGuardDutyが有効になっていることを確認
・未導入だったアカウント(ctop系、cc-poc等)でDetectorが作成されていることを確認
・サンプルfindingsを生成して通知が来ることを確認9. 既存環境への影響
既存Detectorのあるアカウント(7アカウント):
・既存Detectorは引き継がれる(再作成されない)
・既存のfindingsも引き継がれる
・既存の通知設定(EventBridge → SNS → Chatbot → Slack)はそのまま動作
・保護プランの設定はDelegated Adminの自動有効化設定に合わせて更新される場合がある
→ 事前に既存設定と組織設定の差異を確認すること
未導入アカウント(6アカウント):
・GuardDutyが自動有効化される
・有効化直後はfindingsが生成される可能性がある(初回スキャン)
developアカウント:
・SNSサブスクリプションが空のため、組織統合とは別に通知設定の修正が必要10. SCP保護
SCP①(セキュリティサービス保護)で以下を禁止:
・guardduty:DeleteDetector — Detector削除
・guardduty:DisassociateFromAdministratorAccount — 管理者アカウントからの離脱
→ メンバーアカウントからGuardDutyを無効化・離脱することはできない
→ マネジメントアカウントはSCP適用外のため操作可能11. コスト
GuardDutyの料金体系:
・基本(CloudTrail管理イベント、VPCフローログ、DNSログ): 分析量に応じた従量課金
・保護プラン: 各プランごとの従量課金
・固定費なし(完全従量課金)
既存コスト実績(2026年5月):
・production: $465/月
・fd-sys: $257/月
・staging: $186/月
・infra-dev: $46/月(4月実績)
・develop, 踏み台, 外部連携: 各$20〜50/月(推定)
・合計(推定): 約$1,000〜1,100/月
productionのコスト内訳:
・Fargate Runtime Monitoring: $220/月(47%)← ECS Fargateタスク数に依存
・RDS Login Events: $67/月(14%)← RDSのvCPU数に依存
・CloudTrail管理イベント: $49/月(10%)
・S3 Data Events: $3/月
・Flow Logs / DNS / Lambda: $1/月
→ Fargate Runtime MonitoringとRDS Login Eventsで6割を占める
コスト方針:
・全環境で同じ設定(全保護プラン有効)とする
・非本番環境の保護プランを無効にしても節約効果は微小
(例: infra-devのFargate Runtime Monitoring=$0.01/月、RDS=$4/月)
・保護プランのコストはリソース量に比例するため、
リソースが少ない環境では自然とコストが低くなる
・Fargate Runtime Monitoring、RDS Login Eventsはサービス基盤・本番DBの
脅威検知として必須のため、コスト削減対象としない
既存アカウントへのコスト影響:
・組織統合しても既存Detectorはそのまま引き継がれるため、
既存7アカウントのコストは現状維持(増加しない)
・保護プランの設定を変更しない限り、追加コストは発生しない
組織統合による追加コスト:
・未導入6アカウント: $20〜100/月(操作量が少ないため)
・マルチリージョン有効化: $5〜20/月(未使用リージョンはイベント量がほぼゼロ)
・S3エクスポート(fd-log-archive): $1〜2/月(KMSキー$1 + ストレージ微小)
・合計追加コスト: 約$30〜120/月(既存コストの3〜10%程度の増加)12. Malware Protection for S3 設計
詳細な調査経緯・全367バケットの分類結果は S3 バケット棚卸し調査 を参照。
対象バケット
本番環境の全367バケットを棚卸しし、外部ユーザー(患者)が直接 S3 にファイルをアップロードする4バケットを特定した。 Terraform リポジトリ全体で CORS PUT を許可しているバケットが2件のみであること、およびアプリケーションソースコードの presigned URL 生成パターンの調査により、漏れがないことを確認済み。
| バケット | アカウント | 内容 | Terraform管理 | リージョン | 日次アップロード | 月額コスト |
|---|---|---|---|---|---|---|
| fastdoctor-images-production | fd-sys | 保険証・カルテ画像(Shrine presigned POST) | × | ap-northeast-1 | ~2,490件 | ~$27.2 |
| mental-reserve-patient-medical-image-production | production | メンタルヘルス患者の保険証画像(presigned URL PUT) | ○ | us-east-1 | ~1,203件 | ~$15.4 |
| ai-triage-prd-file-upload | production | 事前問診の症状写真(presigned URL PUT + STS AssumeRole) | ○ | us-east-1 | ~1,877件 | ~$15.7 |
| online-karte-static-front-production | production | 検査結果・お薬手帳・処方箋PDF(BFF PutObject + presigned PUT) | ○ | ap-northeast-1 | ~1,123件 | ~$11.2 |
| 合計 | ~6,693件/日 | ~$69.5/月 |
課金形態
- データスキャン: us-east-1: $0.09/GB、ap-northeast-1: $0.1185/GB。新規アップロードされたオブジェクトのみスキャン
- リクエスト: us-east-1: $0.000215/件、ap-northeast-1: $0.000282/件
- 既存オブジェクトはスキャンされない: EventBridge の S3 Object Created イベントがトリガーのため
- コスト高騰リスク: なし。アップロード頻度は30日間実測済みで安定(日次 ~6,693件)
Terraform 配置
各アカウントで個別設定(Delegated Admin からは設定不可):
production アカウント:
fastdoctor-template/common/production/globals/s3/guardduty.tf(新規作成)
→ mental-reserve-patient-medical-image-production
→ ai-triage-prd-file-upload
→ online-karte-static-front-production
fd-sys アカウント:
fastdoctor-template/common/amazon-connect/globals/s3/guardduty.tf(新規作成)
→ fastdoctor-images-production(TF管理外のため import or ARN 直接指定)新規バケット追加時の漏れ防止策
- PR レビューで防ぐ: Claude auto review プロンプト(
.github/prompts/claude-auto-review.md)に「S3 バケット新規作成時、外部ユーザーアップロードを受ける場合は GuardDuty + Access Logs 必須」のチェック項目を追加済み - 共通モジュールで強制する: ファイルアップロード用バケットの共通モジュールを作成し、GuardDuty + Access Logs + 暗号化 + パブリックアクセスブロックをバケット作成と同時に自動適用
TBAC(Tag-Based Access Control)設計
目的
マルウェアスキャンで脅威が検出されたオブジェクトへのアクセスを即時ブロックする。
方式の選定
| 方式 | 安全性 | アプリ影響 |
|---|---|---|
| ホワイトリスト(公式推奨) | 高(未スキャンもブロック) | スキャン完了まで読み取り不可 |
| ブラックリスト(採用) | 中(検知済みマルウェアをブロック) | 影響なし |
ブラックリスト方式を採用する。 公式推奨はホワイトリスト方式(NO_THREATS_FOUND 以外を全て Deny)だが、アップロード直後〜スキャン完了までの間にアプリからファイルが参照できなくなる影響がある。本システムでは患者がアップロードした保険証・医療画像を医師が即時参照するフローがあるため、アプリ影響を回避するブラックリスト方式を採用する。
ブラックリスト方式のリスクと許容判断:
- 未スキャン・スキャン失敗のオブジェクトが読み取れる
- スキャン所要時間の SLA が非公開のため、未スキャン状態の時間幅が読めない
- ただし GuardDuty が正常稼働している限り、アップロード後短時間でスキャンされるため実質的なリスクは限定的
- マルウェアが検出された時点で即座にブロックされるため、既知マルウェアの拡散防止としては十分機能する
仕組み
GuardDuty がスキャン完了後に S3 オブジェクトに付与する GuardDutyMalwareScanStatus タグをもとに、バケットポリシーでアクセスを制御する。
| タグ値 | アクセス |
|---|---|
NO_THREATS_FOUND | 許可 |
THREATS_FOUND | 拒否 |
| タグなし(未スキャン / スキャン中) | 許可(ブラックリスト方式) |
UNSUPPORTED / ACCESS_DENIED / FAILED | 許可(ブラックリスト方式) |
既存バケットポリシーの現状
| バケット | 既存ポリシー | TBAC 適用方法 |
|---|---|---|
| fastdoctor-images-production | なし | 新規追加 |
| mental-reserve-patient-medical-image-production | なし | 新規追加 |
| ai-triage-prd-file-upload | なし | 新規追加 |
| online-karte-static-front-production | あり(CloudFront OAC 用 Allow) | 既存ポリシーに TBAC Statement を追加 |
IAM ロール・アカウント情報
| アカウント | アカウントID | GuardDuty IAM ロール | 管理者ロール | 対象バケット |
|---|---|---|---|---|
| production | 967691968827 | guardduty-malware-protection-s3-role-virginia | fd-platform-admin-role | mental-reserve-patient-medical-image-production, ai-triage-prd-file-upload |
| production | 967691968827 | guardduty-malware-protection-s3-role-tokyo | fd-platform-admin-role | online-karte-static-front-production |
| fd-sys | 913831226605 | guardduty-malware-protection-s3-role-tokyo | fd-backend-admin | fastdoctor-images-production |
※ production はリージョンが異なる(us-east-1 / ap-northeast-1)ため GuardDuty ロールが2つに分かれている
バケットポリシー設計
production / us-east-1 バケット(mental-reserve-patient-medical-image-production, ai-triage-prd-file-upload):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyReadIfMalware",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::967691968827:assumed-role/fd-platform-admin-role/*",
"arn:aws:iam::967691968827:role/fd-platform-admin-role"
]
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::<BUCKET_NAME>/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/GuardDutyMalwareScanStatus": "THREATS_FOUND"
}
}
},
{
"Sid": "OnlyGuardDutyCanTagScanStatus",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::967691968827:assumed-role/guardduty-malware-protection-s3-role-virginia/GuardDutyMalwareProtection",
"arn:aws:iam::967691968827:role/guardduty-malware-protection-s3-role-virginia",
"arn:aws:sts::967691968827:assumed-role/fd-platform-admin-role/*",
"arn:aws:iam::967691968827:role/fd-platform-admin-role"
]
},
"Action": "s3:PutObjectTagging",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/*",
"Condition": {
"ForAnyValue:StringEquals": {
"s3:RequestObjectTagKeys": "GuardDutyMalwareScanStatus"
}
}
}
]
}production / ap-northeast-1 バケット(online-karte-static-front-production):
既存の CloudFront OAC Allow Statement に TBAC の Deny Statement 2つを追加する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::online-karte-static-front-production/*",
"Condition": {
"StringEquals": {
"aws:SourceArn": "<CLOUDFRONT_DISTRIBUTION_ARN>"
}
}
},
{
"Sid": "DenyReadIfMalware",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::967691968827:assumed-role/fd-platform-admin-role/*",
"arn:aws:iam::967691968827:role/fd-platform-admin-role"
]
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::online-karte-static-front-production/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/GuardDutyMalwareScanStatus": "THREATS_FOUND"
}
}
},
{
"Sid": "OnlyGuardDutyCanTagScanStatus",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::967691968827:assumed-role/guardduty-malware-protection-s3-role-tokyo/GuardDutyMalwareProtection",
"arn:aws:iam::967691968827:role/guardduty-malware-protection-s3-role-tokyo",
"arn:aws:sts::967691968827:assumed-role/fd-platform-admin-role/*",
"arn:aws:iam::967691968827:role/fd-platform-admin-role"
]
},
"Action": "s3:PutObjectTagging",
"Resource": "arn:aws:s3:::online-karte-static-front-production/*",
"Condition": {
"ForAnyValue:StringEquals": {
"s3:RequestObjectTagKeys": "GuardDutyMalwareScanStatus"
}
}
}
]
}注: S3 ポリシー評価順序として Deny が Allow より優先されるため、CloudFront 経由のアクセスであっても THREATS_FOUND タグのオブジェクトはブロックされる。
fd-sys / ap-northeast-1 バケット(fastdoctor-images-production):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyReadIfMalware",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::913831226605:assumed-role/fd-backend-admin/*",
"arn:aws:iam::913831226605:role/fd-backend-admin"
]
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::fastdoctor-images-production/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/GuardDutyMalwareScanStatus": "THREATS_FOUND"
}
}
},
{
"Sid": "OnlyGuardDutyCanTagScanStatus",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::913831226605:assumed-role/guardduty-malware-protection-s3-role-tokyo/GuardDutyMalwareProtection",
"arn:aws:iam::913831226605:role/guardduty-malware-protection-s3-role-tokyo",
"arn:aws:sts::913831226605:assumed-role/fd-backend-admin/*",
"arn:aws:iam::913831226605:role/fd-backend-admin"
]
},
"Action": "s3:PutObjectTagging",
"Resource": "arn:aws:s3:::fastdoctor-images-production/*",
"Condition": {
"ForAnyValue:StringEquals": {
"s3:RequestObjectTagKeys": "GuardDutyMalwareScanStatus"
}
}
}
]
}既存オブジェクトへの影響
ブラックリスト方式のため、既存オブジェクト(タグなし)への影響はなし。 THREATS_FOUND タグが付いたオブジェクトのみ Deny されるため、タグなしオブジェクトは通常通りアクセス可能。
アプリ側の影響
ブラックリスト方式のため、アプリ側への影響はなし。
| 状態 | アクセス | 備考 |
|---|---|---|
| アップロード直後(タグなし) | 許可 | スキャン完了を待たずに参照可能 |
スキャン完了(NO_THREATS_FOUND) | 許可 | — |
マルウェア検知(THREATS_FOUND) | 拒否 | 即時ブロック |
スキャン失敗(FAILED 等) | 許可 | リスク許容(GuardDuty 正常稼働前提) |
検出範囲の制約
サポート・SA 確認済みの内容:
- GuardDuty のスキャンエンジンはファイルベースの静的検出(ライブ挙動解析なし)
- AWS 内製エンジン + Bitdefender のシグネチャベース + ヒューリスティック + ML 検出
- 特定 CVE をトリガーする構造かどうかを判定する仕組みではない
- libpng/libjpeg 脆弱性を突く細工画像の検出は保証されない
- 既知の悪性コード・シグネチャに合致するペイロードが含まれていれば検出される可能性はある
- ライブラリ自体の脆弱性管理は Inspector の領域
隔離バケット
マルウェア検知されたオブジェクトの調査・証跡保持のため、隔離用バケットを用意する。
| アカウント | 隔離バケット名 | リージョン | 備考 |
|---|---|---|---|
| production | fd-malware-quarantine-production | ap-northeast-1 | us-east-1 バケットからのコピーはクロスリージョン転送(データ転送料発生) |
| fd-sys | fd-malware-quarantine-fd-sys | ap-northeast-1 | — |
設定:
- パブリックアクセスブロック: 全て有効
- 暗号化: SSE-S3(デフォルト)
- バージョニング: 有効
- ライフサイクルポリシー: 90日後に Glacier 移行、365日後に削除(監査要件ガイドラインに準拠)
- アクセス: 管理者ロール(
fd-platform-admin-role/fd-backend-admin)のみ
手動隔離手順:
# 1. 管理者ロールで感染オブジェクトを隔離バケットにコピー
aws s3 cp \
s3://<SOURCE_BUCKET>/<OBJECT_KEY> \
s3://fd-malware-quarantine-production/<SOURCE_BUCKET>/<OBJECT_KEY> \
--profile <ADMIN_PROFILE>
# 2. 元バケットから削除
aws s3 rm s3://<SOURCE_BUCKET>/<OBJECT_KEY> --profile <ADMIN_PROFILE>Terraform 配置:
production アカウント:
fastdoctor-template/common/production/globals/s3/malware-quarantine.tf(新規作成)
fd-sys アカウント:
fastdoctor-template/common/amazon-connect/globals/s3/malware-quarantine.tf(新規作成)Lambda 自動隔離(将来オプション)
初期リリースでは TBAC + 手動対応で運用する。運用後に手動対応の頻度が高い場合、EventBridge → Lambda による自動隔離を検討する。
| 項目 | 内容 |
|---|---|
| トリガー | EventBridge: GuardDuty Malware Protection Object Scan Result(THREATS_FOUND) |
| 処理 | 感染オブジェクトを隔離バケットにコピー → 元バケットから削除 |
| 隔離バケット | ライフサイクルポリシー(90日→Glacier、365日→削除)を設定 |
| 考慮事項 | 医療記録は「原則削除しない」設計方針との整合性を確認する必要がある |
Terraform 配置
production アカウント:
fastdoctor-template/common/production/globals/s3/guardduty-tbac.tf(新規作成)
→ mental-reserve-patient-medical-image-production: aws_s3_bucket_policy(新規)
→ ai-triage-prd-file-upload: aws_s3_bucket_policy(新規)
→ online-karte-static-front-production: 既存 aws_s3_bucket_policy に Statement 追加
fd-sys アカウント:
fastdoctor-template/common/amazon-connect/globals/s3/guardduty-tbac.tf(新規作成)
→ fastdoctor-images-production: aws_s3_bucket_policy(新規)適用手順
Step 1: infra-dev でポリシー検証
・テスト用バケット(connect-test-xxx)に TBAC ポリシーを適用
・EICAR ファイルアップロード → THREATS_FOUND タグ付与 → GetObject が Deny されることを確認
・正常ファイルアップロード → NO_THREATS_FOUND タグ付与 → GetObject が許可されることを確認
・タグなしオブジェクト → GetObject が許可されることを確認(ブラックリスト方式)
・GuardDuty 以外からのタグ変更が Deny されることを確認
Step 2: staging でアプリ動作確認
・対象: mental-reserve-patient-medical-image-staging
(staging 環境で確認可能な唯一の対象バケット)
・TBAC ポリシーを適用し、既存のアプリワークフローが正常に動作することを確認
- 患者の保険証アップロード → 医師の画像参照が正常に動作するか
- presigned URL 経由のアクセスが正常か
・問題があれば即時ポリシーを削除してロールバック
Step 3: 本番適用
・4バケットに TBAC ポリシーを適用
・適用後、正常なファイルのアップロード・参照が動作していることを監視
・Slack 通知で THREATS_FOUND の検知を監視SCP によるタグ改ざん防止
バケットポリシーの OnlyGuardDutyCanTagScanStatus で IAM ロール以外のタグ変更を防止しているが、Organizations SCP で追加の防御層を設ける。
SCP ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyGuardDutyTagModification",
"Effect": "Deny",
"Action": [
"s3:PutObjectTagging",
"s3:DeleteObjectTagging"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:TagKeys": "GuardDutyMalwareScanStatus"
},
"ArnNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::967691968827:role/guardduty-malware-protection-s3-role-virginia",
"arn:aws:iam::967691968827:role/guardduty-malware-protection-s3-role-tokyo",
"arn:aws:iam::967691968827:role/fd-platform-admin-role",
"arn:aws:iam::913831226605:role/guardduty-malware-protection-s3-role-tokyo",
"arn:aws:iam::913831226605:role/fd-backend-admin"
]
}
}
}
]
}適用対象
| OU | 適用 | 理由 |
|---|---|---|
| Workloads OU | 適用 | production, fd-sys が所属 |
| Security OU | 適用不要 | 対象バケットなし |
| Sandbox OU | 適用 | infra-dev での TBAC 検証用 |
Terraform 配置
fastdoctor-template/common/security-tooling/scp.tf に追加
または scp_policies/ ディレクトリに新規ポリシー JSON を追加13. 検知時の対応フロー
マルウェア検知時のフロー
1. GuardDuty がスキャン完了
→ THREATS_FOUND タグを付与
→ TBAC により即時アクセスブロック
2. 通知
→ GuardDuty Finding: Object:S3/MaliciousFile(Severity: HIGH)
→ 既存パイプライン: EventBridge → SNS → AWS Chatbot → Slack (#squad-sre-noti-security)
3. SRE が確認
→ Finding の S3ObjectDetails から対象オブジェクトを特定
→ 脅威の種類・深刻度を確認
→ CloudTrail(データイベント有効化済みの場合)でアップロード元を特定
→ アプリ側チームに連絡(対象バケットのオーナーチーム)
4. 対応判断
→ 管理者ロールで感染オブジェクトを隔離バケットにコピー
(DenyReadIfMalware から管理者ロールは除外済みのためアクセス可能)
→ 元バケットから削除
→ 誤検知の場合: タグを NO_THREATS_FOUND に手動更新(管理者ロールで実施)
5. ユーザー対応
→ アップロード元のユーザー(患者)に連絡
→ 端末のセキュリティスキャンを依頼
→ 必要に応じてファイルの再アップロードを案内誤検知時の対応
GuardDuty の誤検知が確認された場合:
1. SCP 除外ロール(管理者)でタグを手動更新
aws s3api put-object-tagging \
--bucket <BUCKET_NAME> \
--key <OBJECT_KEY> \
--tagging '{"TagSet":[{"Key":"GuardDutyMalwareScanStatus","Value":"NO_THREATS_FOUND"}]}'
2. GuardDuty でサプレッションルールを追加(同一パターンの誤検知防止)14. Macie の方針
Macie は現時点では見送り、ガバナンス整備後に Phase 4 として導入予定。 詳細は OU・アカウント設計書の Macie 方針セクション を参照。
15. 今後のタスク
| # | タスク | 概要 |
|---|---|---|
| 1 | 通知設計 | Delegated Adminへの通知集約、Datadog統合、Slack通知先の整理 |
| 2 | developのSNSサブスクリプション修正 | 現在通知されていない問題の修正 |
| 3 | 既存S3エクスポートの整理 | fd-log-archive集約後に各アカウントの個別エクスポートを段階的に廃止 |
| 4 | サプレッションルール | 運用しながら誤検知を抑制するルールを追加 |
| 5 | Security Hub統合 | Security Hub導入時にGuardDutyのfindingsを自動集約 |
| 6 | ✅ 完了(2026-08-14)。調査結果 / 対象4バケット確定 / コスト試算済み → 実装へ | |
| 7 | Athena分析基盤の設計 | Findingsエクスポート先S3のAthenaテーブル設計・運用設計(CloudTrailのAthena設計と合わせて実施) |
| 8 | Malware Protection for S3の実装 | 4バケットへの aws_guardduty_malware_protection_plan 適用。各アカウントで個別設定 |
| 9 | S3 Server Access Logs の有効化 | 医療・個人情報バケットに監査ログ設定。TF管理バケットはコードで、管理外は手動 or import |
| 10 | ファイルアップロード用バケット共通モジュール | GuardDuty + Access Logs + 暗号化を自動適用する共通モジュール。新規バケット追加時の漏れ防止 |
| 11 | TBAC バケットポリシーの実装 | infra-dev 検証 → staging 動作確認(mental-reserve-patient-medical-image-staging)→ 本番4バケットに適用 |
| 12 | SCP タグ改ざん防止の実装 | Workloads OU に GuardDutyMalwareScanStatus タグ変更制限 SCP を適用 |
| 13 | EICAR 画像埋め込み検出テスト | GuardDuty の画像ファイル内ペイロード検出力を検証。テスト計画(doc 未作成: tasks/guardduty-s3-malware-eicar-image-test.md) |
| 14 | 検知時対応フローの文書化・周知 | マルウェア検知時の Slack 通知 → 担当者判断 → ユーザー連絡の運用フローをチームに周知 |
| 15 | 隔離バケットの作成 | production / fd-sys に fd-malware-quarantine-* バケットを作成。Terraform で管理 |