目次を開く
S3 Object Lockの設定画面には,保持日数を入力する欄があります.30日,90日,1年.長くすれば復旧の選択肢は増えますが,同時に,削除できないDataと保存費用を抱える期間も延びます.Compliance Modeでは,root userを含む通常の操作で,保護中のVersionを削除したり保持期限を短縮したりできません.[1]
そこで最初に決めるのは日数ではありません.いつの正常な状態まで戻る必要があり,その復旧に使う全Dataを,いつまで保護する必要があるかです.復旧の時間軸から下限を求め,費用と削除要件に照らして採用できるかを判断します.
S3 Object Lockで守れるものに続く設計編です.前稿が保護・権限・復元の実装を扱ったのに対し,本稿はdays = Nの根拠を扱います.数値は説明用の仮定です.
1.四つの時計を分ける
Retentionという一語で,Lock期間,Backupの保存期間,業務記録の保存義務をまとめないようにします.Archiveを使う場合は,Storage Classの最低課金期間も別に加わります.
| 時計 | 起点と意味 | 期限で起きること |
|---|---|---|
| 固定Object Lock | Version作成日時+Default日数,または明示したRetain Until Date | 他のHold等がなければ,Retentionによる削除防止が終了 |
| 保存・Lifecycle | Currentの作成日時,Noncurrentになった日時など | 対象Actionの適格性が生まれる.即時削除ではない |
| 業務・契約上の期限 | 契約終了,記録作成,削除要求受付など | 満たすべき保存・削除義務を定める |
| Storage Classの最低期間 | 当該Classでの保存・課金の起点 | 早期削除等の残存期間課金に影響 |
Governanceでは,必要な権限と明示的なBypass要求が揃うと例外操作が可能です.したがって「Retention中は誰にも消せない」と一括りにしません.ComplianceについてもAWSはAccount削除の例外を記載しており,Accountの存続や管理境界までObject Lockが守るわけではありません.[1][2]
本稿の設定例は固定Retentionを扱います.期限のあるRetentionと,明示的に解除するまで続くLegal Holdを分け,設定・解除する主体の権限を設計します.[1]
2.正常な復旧点の年齢から下限を求める
侵害がDay 0,検知がDay 21だったとしても,Day 20のBackupが安全とは限りません.必要なのは最新のBackupではなく,調査と検証によって選べる正常な復旧点です.初期侵害とData汚染の時刻は一致するとは限らず,Credential,Application,設定のどこまで戻すかも変わります.
検知までの仮定を,業界の平均Dwell Timeや自社のP95だけで「最大値」と呼ぶことはできません.過去実績,未検知の可能性,Logの不足を分け,設計上採用する上限仮定と残余リスクを記録します.
独立したFull Backupを例に,保守的な直列モデルを置きます.
R >= G + D + I + X + M
G = gap to the completed healthy backup before compromise
D = assumed maximum delay from compromise to detection
I = investigation and recovery-point selection
X = retrieval, clean recovery and business validation
M = margin for uncertainty
Illustrative lower bound: 1 + 21 + 7 + 3 + 14 = 46 days
Configured candidate: 50 days (4 additional days of rounding)
Gは,侵害直前までに完了していた正常なBackupまでの間隔です.定期実行の間隔だけでなく,失敗,遅延,整合性のあるSnapshotが得られる時点も考慮します.Retentionの時計はVersionの作成・Uploadに結び付くため,実際にはCapture時刻と各Versionの作成時刻も照合します.
横にスクロールして図全体をご覧いただけます.
図を文章で読む
正常なBackupから侵害までの間隔G,検知までD,調査I,復旧検証X,不確実性Mを足す.例は1+21+7+3+14=46日を50日に丸める.仮定であり実測ではない.
例えばG=1,D=21,I=7,X=3,M=14日なら下限候補は46日です.説明用の設定値を50日とし,丸めた4日分も記録します.21+7+3+14=45日だけでは,侵害前のBackupまでの間隔が抜けています.一方,調査と復旧準備が並行するなら,実工程のCritical Pathで見直します.足し算の結果を精密な予測とは扱いません.
XにはClean Environment,Identity再発行,Archive取り出し,転送,Database復元,業務検証までを含めます.調査完了時点で保護が切れる設計では,復旧途中で必要なVersionを失う可能性が残ります.
3.RPO,復旧点密度,依存Dataを区別する
毎時Backupは直近の復旧点を細かくできますが,成功と整合性を確認しなければ1時間RPOを保証しません.また,侵害前へ戻すCyber Recoveryでは,通常障害のRPOより大きなData差分を業務側で扱う必要があります.
毎時×45日なら予定上1,080点,毎日×45日なら45点です.ただし,予定件数は正常で復元可能な件数ではありません.Manifestと検証結果を含めて復旧点を数えます.
増分方式では,Retentionを新しい増分だけに付けても不十分です.Day 0のFullにDay 1〜6の増分が依存し,それぞれ作成から50日Lockすると,FullがDay 50で先に削除可能になり,増分が残っていても復元できなくなります.共有Chunkを再利用するDeduplicationでも,同じ問題が起きます.
横にスクロールして図全体をご覧いただけます.
図を文章で読む
Full,増分,WAL,Catalog,Manifestのすべてを必要な利用期限まで保護する.同じ50日を各Uploadから数えるだけではFullが先に期限切れになる.鍵と権限も別途必要である.
必要な制約は「全Objectを同じ日数Lockする」より強くなります.
For every recovery point p and every dependency v in deps(p):
protect_until(v) >= required_use_until(p)
Check: full + increments + WAL + catalog + manifest + shared chunks
Also preserve: decryption capability + reader access + restore tools
Full,増分,WAL,Index,Catalog,Manifestの依存集合を列挙し,共通の必要期限まで保護します.Backup製品のRetention連携やGarbage Collectionがこの依存関係を扱えるか確認します.最古のFullは,新しい復旧点より長く保護する必要があります.復号鍵,Reader権限,復旧用Softwareも同じ期間利用できなければなりません.Object LockはKMS Keyの削除を防ぎません.[8]
Hourly 7日,Daily 50日,Weekly 180日というClass分けも可能ですが,Object TagだけでRetentionは変わりません.Bucket DefaultやVersionへの明示的な設定をBackup Processが実行し,実際のMetadataで確認します.個別設定はDefaultより優先されます.[1]
4.削除要件との衝突を,設定前に見つける
あるVersionに「90日間Complianceで削除不能」と「30日以内に物理削除」を同時に要求すると,通常の操作では両立しません.これは設定方法の不足ではなく,要件の衝突です.
削除期限の起点も明示します.契約終了から30日なのか,Data取得から30日なのかで評価が変わります.Backupに残る期間,利用制限,復旧後に削除を再適用する手順について,Privacy・契約・記録管理の担当者と合意します.一律にBackupの削除義務が免除されるとは考えません.
| Dataの役割 | 保持設計で確認すること | 分離する理由 |
|---|---|---|
| 復旧用Backup | 正常点の探索範囲,依存Data,業務復旧 | 復元することが目的 |
| 正式な記録Archive | 保存義務,完全性,検索・提出方法 | System of Recordとしての要件 |
| Incident Evidence | 対象Version,保全責任,解除条件 | 調査上の必要性が継続期間を決める |
| 一時Export・削除要件の厳しいData | 保存の必要性と削除期限 | 長期Lockへ混在させない判断が必要 |
同じObjectに複数人のDataをまとめると,特定の人だけを消すことが難しくなります.Packagingは費用だけでなく削除粒度にも影響します.復旧時に削除済みDataを再投入しないため,別途保護した削除記録と照合して再削除する工程も検討します.
鍵を破棄して読めなくすることも,Objectの削除と同じとは限りません.法的な十分性は別に確認が必要であり,共有Keyを破棄すれば他の復旧点も失います.削除要件を回避する定型手段にはしません.
5.Governance,Compliance,HoldのOwnerを決める
Governanceは,運用や保持日数を検証しながら限定的な例外権限を残す場合の候補です.Bypassにはs3:BypassGovernanceRetentionと明示的な要求が必要で,削除操作自体の権限も必要です.ConsoleはBypass Headerを自動で含むため,UIで削除を試すOperatorの権限も確認します.[1][2]
Complianceへ進むなら,対象Data,復元,費用,削除義務,Lifecycle,権限分離のReviewを終え,短縮できないことを受け入れます.長いComplianceを設定してから削除例外を考える順序にはしません.Governanceの例外権限を広げる場合も,攻撃者がその権限を奪うThreat Modelへ戻します.
Legal Holdは,固定Retentionとは独立した期限なしの保護です.Incident時の対象Versionを保全する用途に使えますが,解除権限,Owner,Review予定日を持たせます.Hold解除は,まだ有効なRetentionを無効化しません.[1]
Incidentを検知したら,候補の正常点だけでなく依存するFullやManifestも,消える前に保全できるか確認します.保全の開始が間に合わなければ,Legal Holdで既に消えたVersionを取り戻すことはできません.この手順を根拠に,通常Retentionを無条件に短くしないようにします.
6.費用はLock日数ではなく保存量で計算する
最初の近似は,日々新しく保存する物理Bytesと,実際に残す期間の積です.論理的な変更量ではなく,Full,増分,圧縮後のObject,Version,Metadataを含めて観測します.
V = newly stored physical GiB per day
L = actual storage lifetime in days
P = price per GiB-month, normalized from the selected price source
Steady-state payload GiB ~= V * L
Single-class monthly payload cost ~= V * L * P
(approximation when stored payload is billable throughout L)
Add: requests + transitions + retrieval + minimum-duration charges
+ object metadata + temporary restored copies + replication
+ transfer + KMS + inventory / analysis
RをLock日数,Lを保存期間とすると,Lが90日ならLockを45日から30日へ短くしても,保存・削除の運用を変えなければStorage Costは直ちには減りません.既存のCompliance Versionの期限も,Default変更で短くなりません.
例として200 GiB/日が一定で,同一Classに保存される定常状態を比較します.以下の期間は保存期間Lであり,必ずしもLock期間ではありません.
| 保存期間L | 保存量の一次近似 | TiB換算 |
|---|---|---|
| 30日 | 6,000 GiB | 5.86 TiB |
| 45日 | 9,000 GiB | 8.79 TiB |
| 50日 | 10,000 GiB | 9.77 TiB |
| 90日 | 18,000 GiB | 17.58 TiB |
| 180日 | 36,000 GiB | 35.16 TiB |
1 TiBは1,024 GiBです.例えば150 GiB×45日=6,750 GiBは約6.59 TiBであり,6.75 TiBではありません.単価を入れるときも,見積書のGB単位とこのモデルのGiBを確認して揃えます.[9]
1 TiBのFullを毎日45世代なら45 TiBです.最初のFull 1 TiBと44日分の50 GiBなら3,224 GiBですが,これは一つの有限なChainのPayload計算です.定常運用ではFullの再作成,Chainの重複期間,共有Chunkの延命,IndexやReplicaも加わります.
Inventory上に残るBytesと課金対象Bytesも区別します.Lifecycleの削除適格日と実際の処理日には差があり,AWSは期限到達後の処理待ちに関する課金停止の扱いを説明しています.ただしCurrentにDelete Markerが付いただけで,残るData Versionの課金まで終わるとは限りません.見積もりではVersionとClassごとの課金条件を確認します.[6]
実測では日次新規Bytes,Version数,Object Size分布,Class別Bytes,Full切替時のPeakを取ります.月額は平均保存量で,容量と予算の余裕はPeakと増加傾向も含めて評価します.単価はRegion,時点,料金帯を記録し,本稿では固定のAWS価格を掲載しません.
7.Storage ClassをRTOと最低課金期間で選ぶ
Object Lockの保護はStorage Classを跨いで維持され,Lifecycle Transitionも使えます.しかし,安いClassへ置くことと,期限内に復旧できることは別です.[2]
| Class | 最低Storage期間 | 取り出しの性質 | Reviewする費用・制約 |
|---|---|---|---|
| Standard | なし | 即時Access | 通常の保存・Request費用 |
| Standard-IA | 30日 | 即時Access | 最低128 KB課金,取り出し費用,Lifecycle移行の時期 |
| Glacier Instant Retrieval | 90日 | 即時Access | 最低128 KB課金,取り出し費用 |
| Glacier Flexible Retrieval | 90日 | 事前のRestoreが必要 | Retrieval方式,Request,Metadata,復元用一時Copy |
| Glacier Deep Archive | 180日 | 事前のRestoreが必要 | 長い取り出し時間と同様の追加費用 |
AWSの目安では,通常のStandard RetrievalはFlexibleで3〜5時間,Deep Archiveで通常12時間以内,Deep ArchiveのBulkは通常48時間以内です.これは業務復旧の保証ではありません.Object Size,取り出し量,方式や制限により変わり,その後の転送・展開・Database復元・検証が加わります.RTO 2時間の唯一の復旧点をDeep Archiveに置く設計は,この時間軸と整合しません.[3][4]
最低課金期間は,各Classに保存する期間で考えます.50日Lockだから90日Classを使えないわけではなく,その後も長く保存するなら候補になります.逆に移行後43日で削除する設計なら,90日分との差額を含めて比較します.早期削除課金があっても,総額で有利かどうかは単価とAccess量によります.[5][9]
小さいObjectにも注意が必要です.現行のLifecycleは既定で128 KB未満をTransitionしません.2024年9月以前の設定は,変更するまで旧挙動を維持する場合があります.Flexible / Deep ArchiveではObjectごとに8 KBをStandard料金,32 KBをArchive料金で追加課金するMetadataもあります.Object数,Request単価,最低課金Sizeを含めます.[5]
圧縮,増分,Objectの集約は費用削減の候補ですが,復元粒度,並列性,破損時の影響,削除粒度とのTrade-offがあります.Security Windowを縮める前に,Backup Formatと保存設計を確認します.
8.LifecycleをVersionごとの時間軸で読む
Retentionが切れても自動的に消えるわけではありません.またVersioning有効Bucketでexpiration { days = 60 }を指定しても,60日後にData Versionを物理削除する設定にはなりません.通常はDelete Markerを作り,従来のCurrent VersionをNoncurrentにします.[6]
Noncurrent Versionの削除はNoncurrentVersionExpirationで別に定義し,起点はVersionの作成日ではなくNoncurrentになった時点です.S3は後続Versionの作成日時を使います.日数の計算は次のUTC午前0時への丸めを含み,Actionも非同期です.[6][7]
横にスクロールして図全体をご覧いただけます.
図を文章で読む
一意Keyの例ではLock50日,Current expiration60日,Noncurrent expiration7日.削除は概ね67日以降だが丸めと非同期処理がある.上書きしたKeyはNoncurrentの起点が早くなる.
説明用に,一度だけ書いた一意のKeyを作成から50日Lockし,Current expirationを60日,Noncurrent expirationを7日とします.Dataの削除適格時点は概ね60+7日より後です.丸めと処理待ちがあるため,「67日目に必ず物理削除」とは言えません.200 GiB/日なら,Payloadだけでも名目67日で13,400 GiB程度となり,Lock50日の10,000 GiBとは違います.
一方,同じKeyをDay 1に上書きした古いVersionは,Day 1からNoncurrentの時計が進みます.7日条件を先に満たしても,Lock中は削除できず,Hold等がなければLock期限後に削除対象となり得ます.「60日Current+7日Noncurrentだから全Versionが最低67日残る」という読み方も誤りです.
Legal Hold,Replication状態,RuleのFilter,残す新しいVersion数の条件によっても削除可否は変わります.Lifecycleは厳密な削除完了Deadlineを保証しないため,法的・契約上の期限がある場合は,余裕,監視,期限前の対応手順を別に設計します.[6]
9.Decision RecordからOpenTofuへつなぐ
先にReview用のRecordを作り,その値を構成へ反映します.reviewed: trueのような未実施の承認は書きません.
# Illustrative decision, not an approval record.
id: RET-RECOVERY-001
status: PROPOSED
execution_status: NOT_RUN
data_scope: independent-full-backups-under-unique-keys
mode: GOVERNANCE
model_days: { gap: 1, detection: 21, investigation: 7, recovery: 3, margin: 14 }
calculated_minimum_days: 46
candidate_lock_days: 50
storage_class: STANDARD
lifecycle:
current_expiration_days: 60
noncurrent_expiration_days: 7
physical_deletion_deadline_guaranteed: false
reviews:
recovery: null
cost: null
deletion_obligations: null
approval: null
次は既存のRecovery Bucketに対する設定断片です.AWS Provider 6.45.0の公開Schemaに照合しています.VersioningとObject Lockを持つBucket,権限分離,暗号化,監査等は前稿を参照します.この断片だけで安全なBackup環境ができるわけではありません.[10]
# RET-RECOVERY-001. Existing bucket must already have Versioning
# and Object Lock enabled. NOT_RUN; merge the complete Lifecycle rule set.
locals {
gap_days = 1
detection_days = 21
investigation_days = 7
recovery_days = 3
margin_days = 14
minimum_required_days = (
local.gap_days + local.detection_days + local.investigation_days
+ local.recovery_days + local.margin_days
)
retention_days = ceil(local.minimum_required_days / 5) * 5
}
resource "aws_s3_bucket_object_lock_configuration" "recovery" {
bucket = var.bucket_name
rule {
default_retention {
mode = "GOVERNANCE"
days = local.retention_days
}
}
}
resource "aws_s3_bucket_lifecycle_configuration" "recovery" {
bucket = var.bucket_name
rule {
id = "recovery-versions"
status = "Enabled"
filter { prefix = "backups/" }
# Current expiration normally creates a delete marker.
expiration { days = 60 }
# Count from becoming noncurrent, not from upload.
noncurrent_version_expiration { noncurrent_days = 7 }
}
rule {
id = "remove-empty-delete-markers"
status = "Enabled"
filter { prefix = "backups/" }
expiration { expired_object_delete_marker = true }
}
}
例はGovernance・Standard・一意Keyの独立Backupを想定します.Retentionの計算変数をDefaultの値へ接続し,LifecycleはCurrentとNoncurrentを両方示します.Bucket Defaultはbackups/だけでなくBucketへ入る新規Versionに作用しますが,このLifecycle例はbackups/だけを対象にします.他のPrefixに残るDataの保存方針も別途定義します.既存BucketへLifecycle Resourceを追加する場合は,既存の全Ruleを一つの構成として管理する必要があります.別Resourceで同じBucketのLifecycleを上書きしないようにします.
Decision Record,算定表,設定断片,確認資料をダウンロードできます.OpenTofuのinit,validate,plan,applyは未実行です.依存Lockfileは.terraform.lock.hclですが,未初期化のため同梱しません.実際のRuntime,Provider解決結果,Stateと権限を別途Reviewします.[11]
Bucket Defaultの変更は,既存Versionの期限を一括変更するものではありません.50日から30日への変更で,既存のCompliance Versionが短くなることもありません.延長が必要なら対象Versionと依存関係を確認して個別の変更計画を立てます.[1]
10.Guardrailは対象APIと例外まで設計する
s3:object-lock-remaining-retention-daysで,PutObjectRetentionに対する最小・最大の残存日数を制約できます.AWSは最大100年の保持を説明していますが,これは推奨期間ではありません.[2]
例えば最小46日,最大90日の範囲外をDenyするなら,下限と上限は別Statementにします.一つのConditionへ両方を入れるとANDになり,同時に「46未満かつ90超」を要求する誤ったPolicyになり得ます.日数はVersionの年齢ではなく,要求時点の残存日数です.
このGuardだけで全経路の設定ミスを防いだとは判断しません.Bucket Default変更,PUT時の明示Retention,Copy,Replication,条件KeyがないRequest,Legal Hold,Governance Bypass,Policy自体の変更権限を別々にReviewします.厳しい上限はIncident時に必要な延長も拒否し得ます.
保持期限を延長するRequestも,残日数の上限に抵触する可能性があります.緊急時の延長が必要なら,許可する主体と承認条件をあわせて検討します.[2]
11.残ることと,消せることの両方を確認する
復旧訓練では,正常点の探索,依存Dataの取り出し,転送,復元,業務検証までを測ります.保持中の削除拒否だけでは,復旧能力を確認したことにはなりません.
| 確認ケース | 期待するEvidence | 今回の状態 |
|---|---|---|
| 保持中のVersion指定DELETE | 削除権限を持つ非Bypass主体でObject Lockによる拒否 | NOT_RUN |
| Version IDなしのDELETE | Delete Markerと元Versionの残存を区別 | NOT_RUN |
| Full+増分の復元 | 全依存Versionの期限,Hash,業務整合性 | NOT_RUN |
| 期限後,Holdなし | 適切な権限で削除可能.Lifecycle処理も別途追跡 | NOT_RUN |
| Legal Holdあり/解除後 | Holdと残存Retentionそれぞれの効果 | NOT_RUN |
| Archiveからの復旧 | Retrieval開始から業務再開までの時間・費用 | NOT_RUN |
| Default変更 | 既存と新規Versionの保持Metadataの違い | NOT_RUN |
| 削除済みDataを含む復旧 | 削除記録の再適用と再公開の防止 | NOT_RUN |
短い期間の専用検証環境で,Control Objectと呼出主体,停止条件,費用,後片付けを決めて確認します.単に403が返っただけならIAM拒否の可能性があり,Object Lockが効いた証拠とは限りません.前稿の検証設計と合わせて,理由を分離します.
S3 Inventoryは全Versionを対象とし,Version ID,Size,Storage Class,Retain Until Date,Retention Mode,Legal Holdを含めます.最初のReportには最大48時間かかる場合があり,日次・週次のReportは即時状態ではありません.緊急判断ではVersion指定のMetadata取得と照合します.[12]
「期限まで7日未満」「期限切れだが残存」「Hold中でOwner不明」「依存Fullの期限が増分より短い」を集計します.ただしLock期限切れだけで削除すべきとは判定せず,保存方針とLifecycle適格性を突き合わせます.鍵とReaderの利用可能性も別に監視します.
12.数値の変更をRecovery Architectureの変更として扱う
横にスクロールして図全体をご覧いただけます.
図を文章で読む
時間軸と依存関係から必要期限を求め,保存量とStorage Class,削除義務を照合する.矛盾はData分類や構成へ戻して解決し,承認後の訓練結果を次のReviewへ反映する.
Securityは検知遅延の仮定,Operationsは復旧実測,Financeは保存と取り出し費用,Privacy・Legalは削除と記録管理,Businessは許容する損失と停止を確認します.実際の担当者と承認はDecision Recordへ記録し,例示したTeam名を承認実績と混同しません.
例えば復旧工程Xが3日から6日へ変われば,下限は46日から49日へ増えます.現在の50日候補には収まりますが,丸め余裕が4日から1日に減るため,再評価が必要です.検知改善で短縮を検討するときも,平均値の改善だけで上限仮定を下げないようにします.
保持を長くするだけでは,既に汚染されたDataの正常性や復旧の成功率は保証できません.評価するOutcomeは,「定義したThreat Modelと時間軸の下で,正常な復旧点とその依存Dataを利用し,期限内に業務を戻せるか」です.
Retentionは,復旧に必要な保護期間を求め,費用と削除要件が両立することを確認した結果です. days = 50の横には,計算の仮定,依存関係,削除の契約,実測に基づく次のReviewを残します.
参考資料
以下の公式資料を参照しています.数値は仮定に基づく計算例であり,料金見積もりや法的判断,実環境での採用・検証実績ではありません.
- S3 Object Lock: retention, modes and holds
- Object Lock considerations, Lifecycle and retention limits
- S3 storage classes
- Archive retrieval options and timing
- Lifecycle transitions and minimum-duration costs
- Lifecycle expiration and versioning
- Lifecycle actions and UTC date calculation
- AWS KMS key deletion
- Amazon S3 pricing
- AWS Provider 6.45.0: Object Lock configuration · Lifecycle schema
- OpenTofu dependency lock file
- S3 Inventory and optional Object Lock fields