はじめに
「S3はファイルをアップロードしてURLで取得できるストレージ」——これが長い間の私のS3理解でした。
バックアップをS3に保存する、ログをS3に流す、手順書通りに設定する。それはできていた。でも「このS3バケットのバケットポリシーを説明してください」「ライフサイクルルールを設定してください」と言われたとき、詰まりました。
S3は「ただのストレージ」ではなく、AWSの中でも機能が多く、設定を間違えると重大なセキュリティ問題を引き起こすサービスです。
この記事では、S3の「知っているようで知らなかった」部分を整理します。
この記事を読むと、以下のことができるようになります。
- バケットポリシーとACLの違いと使い分けが理解できる
- パブリックアクセスブロックの意味と正しい設定が分かる
- ライフサイクルルールでコストを自動最適化する方法が分かる
S3の基本構造
S3のデータ構造はシンプルです。
- バケット:ファイルを入れる「箱」。名前はAWS全体でユニーク
- オブジェクト:バケットに入れるファイル。キー(パス)+データ+メタデータで構成
-
キー:オブジェクトの識別子。
logs/2026/06/access.logのようにスラッシュ区切りで階層っぽく見せられる(実際にはフラットな構造)
# CLIでバケット一覧を確認
aws s3 ls
# バケット内のオブジェクト一覧
aws s3 ls s3://my-bucket/
# ファイルのアップロード
aws s3 cp ./local-file.txt s3://my-bucket/logs/file.txt
# ファイルのダウンロード
aws s3 cp s3://my-bucket/logs/file.txt ./local-file.txt
# バケット内の全オブジェクトをローカルに同期
aws s3 sync s3://my-bucket/logs/ ./local-logs/
「パブリックになっている」は大事故の元
S3に関するセキュリティインシデントの多くは「バケットが意図せずパブリックに公開されていた」ことが原因です。
パブリックアクセスブロックを必ず確認する
AWSはS3バケットに「パブリックアクセスブロック」という機能を提供しています。4つの設定があります。
| 設定 | 意味 |
|---|---|
| 新しいACLを使ったパブリックアクセスのブロック | ACLで新たにパブリックを許可するのを防ぐ |
| 既存のACLを使ったパブリックアクセスのブロック | 既存のパブリックACLも無効にする |
| 新しいバケットポリシーを使ったパブリックアクセスのブロック | ポリシーで新たにパブリックを許可するのを防ぐ |
| 既存のバケットポリシーを使ったパブリックアクセスのブロック | 既存のパブリックポリシーも無効にする |
基本的にすべてONが推奨です。 公開Webサイトのホスティングなど、意図的にパブリックにする場合のみOFFにします。
# パブリックアクセスブロックの設定を確認
aws s3api get-public-access-block --bucket my-bucket
# すべてONに設定する
aws s3api put-public-access-block \
--bucket my-bucket \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
バケットポリシーとは
バケットポリシーは「誰が、このバケットに対して、何をできるか」を定義するJSONドキュメントです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEC2ToReadLogs",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/EC2LogReader"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-log-bucket",
"arn:aws:s3:::my-log-bucket/*"
]
}
]
}
このポリシーは「EC2LogReader というIAMロールを持つリソースが、my-log-bucket バケットのオブジェクトを読み取れる」という設定です。
よくある使いどころ
- 特定のIAMロール(EC2・Lambda)からだけアクセスを許可する
- CloudFrontからだけオブジェクトを取得できるようにする(OAI/OAC)
- ALBのアクセスログをS3に書き込む(ALBサービスからの書き込みを許可)
- 別AWSアカウントからアクセスを許可するクロスアカウント設定
ライフサイクルルールでコストを自動最適化する
S3のストレージクラスは複数あり、アクセス頻度に応じて使い分けることでコストを削減できます。
| ストレージクラス | 用途 | 料金(目安) |
|---|---|---|
| S3 Standard | 頻繁にアクセスするデータ | 高め |
| S3 Standard-IA | 頻度は低いが素早く取得したいデータ | 中 |
| S3 Glacier Instant Retrieval | アーカイブ・数ミリ秒で取得可能 | 安め |
| S3 Glacier Flexible Retrieval | アーカイブ・数時間で取得 | さらに安い |
ライフサイクルルールを設定すると、「作成から30日後にStandard-IAへ移行、90日後にGlacierへ移行、365日後に削除」というようなストレージクラスの自動遷移ができます。
{
"Rules": [
{
"ID": "log-lifecycle",
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
}
],
"Expiration": {
"Days": 365
}
}
]
}
「ログファイルは最初の30日は頻繁に見るが、それ以降はほぼ参照しない」という場合、ライフサイクルルールを設定するだけでストレージコストを大幅に削減できます。
バージョニングとは
S3のバージョニングを有効にすると、オブジェクトを上書き・削除しても過去のバージョンが残ります。
# バージョニングを有効化
aws s3api put-bucket-versioning \
--bucket my-bucket \
--versioning-configuration Status=Enabled
# バージョン一覧を確認
aws s3api list-object-versions \
--bucket my-bucket \
--prefix important-file.txt
「誤って重要なファイルを削除してしまった」「上書きして元のファイルが必要になった」というケースに対応できます。ただし過去のバージョンもストレージ料金がかかるため、ライフサイクルルールと組み合わせて古いバージョンを自動削除する設定が推奨です。
サーバーサイド暗号化
S3に保存するデータを暗号化するオプションです。AWSでは新規バケットにデフォルトで暗号化が適用されるようになっています。
| 暗号化方式 | 鍵の管理 |
|---|---|
| SSE-S3 | AWSが管理(デフォルト) |
| SSE-KMS | AWS KMSで管理(監査ログが残る) |
| SSE-C | 利用者が鍵を管理 |
個人情報・機密情報を扱うバケットはSSE-KMSを使い、KMSキーのポリシーで誰がデータを復号できるかをコントロールすることが推奨されます。
まとめ
この記事では以下のことを解説しました。
- パブリックアクセスブロックは原則すべてON。意図せずパブリックになるのを防ぐ最初の砦
- バケットポリシーで「誰が何をできるか」をJSON形式で細かく制御できる
- ライフサイクルルールでアクセス頻度に応じたストレージクラス自動移行とコスト削減ができる
- バージョニングで誤削除・上書きからデータを保護できる(ライフサイクルルールとセットで使う)
- 機密データにはSSE-KMSで暗号化し、復号権限をIAMポリシーで管理する
S3は「アップロードとダウンロードができる」だけでは実務では足りません。セキュリティ設定とコスト管理を正しく理解することが、AWSエンジニアとして重要なスキルです。
ハンズオンラボでは、未経験からでも「作って覚える」をモットーにしたITハンズオンイベントを定期開催しています。
面白かったら
「👇いいね」で応援