Use Cases (更新: 2026/6/1)

Claude Code × AWS S3入門: 最小権限でsync・画像アップロード・署名付きURLを作る

Claude CodeでAWS S3を安全に使う入門。IAM最小権限、aws s3 sync、静的サイト、画像、バックアップ、署名付きURLまで実装。

Claude Code × AWS S3入門: 最小権限でsync・画像アップロード・署名付きURLを作る

S3は、AWSの中でも一番よく使われるサービスのひとつです。画像を置く、静的サイトを配信する、ログやバックアップを保存する、ユーザーごとのPDFを一時的に配る。どれも地味ですが、Webサービスを作るとかなり早い段階で必要になります。

ただし初心者がClaude Codeに丸投げすると、S3は事故りやすいです。バケットを公開しすぎる、IAMにs3:*を付ける、aws s3 sync —deleteで本番ファイルを消す、署名付きURLを長すぎる期限で発行する。このあたりは、動いた瞬間はうれしいのに、あとで料金やセキュリティの問題になります。

この記事では、Claude Codeを使ってAWS S3連携を作るときの「安全な頼み方」と「コピペで確認できる実装」をまとめます。前提は、S3を初めて本番寄りに使う人です。S3はただのファイル置き場ではなく、公開範囲、権限、同期、キャッシュ、削除の設計が必要なストレージだと考えると失敗しにくくなります。

AWS CLIのs3コマンドは公式のAWS CLI S3 referenceaws s3 sync referenceを基準にします。署名付きURLはBoto3のpresigned URL guideも考え方が分かりやすいです。Claude Code側の進め方はClaude Code common workflowsに寄せます。

IAMの全体像を先に押さえたい場合はClaude Code AWS IAMガイド、セキュリティの考え方はClaude Codeセキュリティ実践も合わせて見ると理解が速いです。

まずS3で何をするのかを分ける

S3の記事で最初にやるべきことは、いきなりコードを書くことではありません。用途を分けることです。静的サイト配信用のsite、公開画像用のassets、管理者だけが読むbackups、ユーザーへ一時配布するprivate-reports。これらを同じバケットに入れる場合でも、prefixを分けるだけでIAMの書き方がかなり安全になります。

use case 1は静的サイトです。AstroやNext.jsで生成したdistをS3へ置き、CloudFrontで配信します。この場合はGETが多く、更新はデプロイスクリプトだけが行います。use case 2は画像アップロードです。管理画面やCMSから画像をS3へ置き、サイト側ではCloudFront URLを参照します。use case 3はバックアップです。DB dumpや請求書PDFなどを日付つきで保存します。use case 4は署名付きURLです。バケットを非公開にしたまま、15分だけPDFをダウンロードできるようにします。

この4つを混ぜて考えると、すぐにs3:*が欲しくなります。Claude Codeに頼むときも「S3連携を作って」では広すぎます。「uploads以下だけPutObject」「assets以下だけGetObject」「削除権限は不要」のように、用途とprefixを先に決めてから依頼するのがコツです。

最初の確認コマンドとIAM最小権限

最初にバケット名とリージョンを変数に置くと、Claude Codeにも人間にも確認しやすくなります。

export AWS_REGION=ap-northeast-1
export S3_BUCKET=claudecode-lab-assets-prod
aws sts get-caller-identity
aws s3 ls "s3://${S3_BUCKET}/" --region "${AWS_REGION}"

このポリシーは読み取りをassets以下、書き込みをuploads以下、削除を明示的に禁止する設計です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadPublicAssetsOnly",
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod/assets/*"
    },
    {
      "Sid": "WriteUploadsOnly",
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod/uploads/*"
    },
    {
      "Sid": "ListLimitedPrefixes",
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod",
      "Condition": {
        "StringLike": {
          "s3:prefix": ["assets/*", "uploads/*", "backups/*"]
        }
      }
    }
  ]
}

静的サイトや画像を同期する基本形です。最初は必ずdryrunで差分を見てください。

# 1. Preview changes first. This should become a habit.
aws s3 sync ./dist "s3://${S3_BUCKET}/site/" \
  --region "${AWS_REGION}" \
  --delete \
  --cache-control "public,max-age=300" \
  --dryrun

# 2. Deploy only after the preview looks right.
aws s3 sync ./dist "s3://${S3_BUCKET}/site/" \
  --region "${AWS_REGION}" \
  --delete \
  --cache-control "public,max-age=300"

# 3. Upload long-lived images with a different cache policy.
aws s3 sync ./public/images "s3://${S3_BUCKET}/assets/images/" \
  --region "${AWS_REGION}" \
  --exclude "*.psd" \
  --cache-control "public,max-age=31536000,immutable"

署名付きURLは、S3を公開せずに短時間だけダウンロードを許可する方法です。

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3 = new S3Client({ region: process.env.AWS_REGION ?? "ap-northeast-1" });

export async function createDownloadUrl(key: string, filename: string) {
  if (!key.startsWith("assets/private-reports/")) {
    throw new Error(`Unexpected S3 key prefix: ${key}`);
  }

  const command = new GetObjectCommand({
    Bucket: process.env.S3_BUCKET_NAME,
    Key: key,
    ResponseContentDisposition: `attachment; filename="${filename}"`,
  });

  return getSignedUrl(s3, command, { expiresIn: 900 });
}

Claude Codeへ依頼するときは、用途、禁止事項、確認コマンドまで一緒に渡します。

このリポジトリに AWS S3 連携を追加してください。
目的: public/images を S3 の assets/images/ に同期し、private-reports/ のPDFだけ署名付きURLで配布する。
制約: バケット全体公開は禁止。s3:DeleteObject は付けない。aws s3 sync は必ず --dryrun を先に出す。
成果物: scripts/s3-sync-assets.mjs、lib/s3-presigned-url.ts、READMEの手順、確認コマンド。
確認: npm test、aws s3 ls、aws s3 sync --dryrun の出力で説明してください。
参照: AWS CLI s3/sync docs と Anthropic Claude Code common workflows。

IAMで大事なのは、Claude CodeにJSONを書かせたあとに人間が読むことです。Actionにs3:*が入っていないか、Resourceがバケット全体になっていないか、ListBucketのprefix制限があるかを見ます。ListBucketはオブジェクトのARNではなくバケットARNに付ける点も初心者が詰まりやすいところです。

pitfallとして、PutObjectだけあればアップロードできると思いがちですが、マルチパートアップロードを途中で止めるならAbortMultipartUploadが必要です。一方でDeleteObjectは気軽に付けません。削除が必要な運用でも、最初は別ロールに分けるか、確認付きスクリプトに限定したほうが安全です。

aws s3 syncの安全な使い方

aws s3 syncは強力です。ローカルのdistをS3に反映できるので、静的サイトや画像配信ではほぼ必ず使います。ただし、—deleteを付けると「ローカルにないファイルをS3から消す」動きになります。これは正しいデプロイでは便利ですが、パスを間違えると本番の画像やPDFを消します。

私ならClaude Codeにsyncスクリプトを書かせるとき、必ずdryrunモードをデフォルトにします。環境変数REALLY_DEPLOY=1があるときだけ本実行する、あるいはconfirmプロンプトを挟む。AIに任せるほど、削除系の操作は1ステップ余分にするのが現実的です。

静的サイトなら、distをsite/へ同期します。画像ならpublic/imagesをassets/images/へ同期します。バックアップなら、日付prefixを付けて一方向にアップロードします。バックアップ用途では—deleteを付けません。ここを混ぜると危険です。

# Backup use case: never use --delete for historical backups.
BACKUP_DATE=$(date +%Y-%m-%d)
aws s3 sync ./backups "s3://${S3_BUCKET}/backups/${BACKUP_DATE}/" \
  --region "${AWS_REGION}" \
  --storage-class STANDARD_IA \
  --exclude "*.tmp"

# Confirm the uploaded objects.
aws s3 ls "s3://${S3_BUCKET}/backups/${BACKUP_DATE}/" --recursive --summarize

署名付きURLは「公開」ではなく「一時許可」

署名付きURLは、S3バケットをpublicにしなくても、一時的にGetObjectやPutObjectを許可できる仕組みです。初心者向けに言い換えると、鍵付きの倉庫に入ったファイルへ、期限付きの入場券を渡すイメージです。URLを知っている人は期限内にアクセスできるため、メールやチャットで不用意に長期間有効なURLを配らないことが重要です。

上のTypeScript例ではexpiresInを900秒、つまり15分にしています。Boto3の公式ガイドでも、presigned URLには有効期限を指定する考え方が出てきます。Claude Codeに依頼するときは「単位は秒」「デフォルト15分」「prefixチェック必須」と書いてください。ここを書かないと、動くけれど雑なヘルパーが出てくることがあります。

PutObject用の署名付きURLを作る場合は、Content-Typeとkey prefixを固定します。ユーザーから受け取ったファイル名をそのままkeyに使うのは避けます。日本語ファイル名、空白、スラッシュ、同名上書きが絡むと、あとで管理がつらくなります。アプリ側でuploads/yyyy/mm/dd/uuid.extのようなkeyに変換しましょう。

料金と公開範囲の落とし穴

S3の料金は、保存容量だけではありません。リクエスト数、データ転送、CloudFront、ライフサイクル、バージョニングも効きます。画像を大量配信するサイトでは、S3を直接公開するよりCloudFrontを前に置いたほうがキャッシュが効きやすく、転送コストも読みやすくなります。

もうひとつのpitfallは、静的Webサイトホスティングと通常の非公開バケットを混同することです。S3だけでWebサイト公開する記事は古くから多いですが、今はCloudFront + OACでS3を非公開に保つ構成のほうが扱いやすい場面が多いです。少なくとも、バケット全体をpublicにしてから後で直す、という進め方は避けます。

削除事故もよくあります。sync元ディレクトリを間違えたまま—deleteを付けると、S3側のほうが正しい状態なのに消されます。Claude Codeにデプロイスクリプトを作らせるときは、対象prefixをログに出す、dryrunを先に出す、削除予定件数が多すぎる場合は止める、という3点を入れておくとかなり安全です。

# A simple guard before destructive sync.
DRYRUN_OUTPUT=$(aws s3 sync ./dist "s3://${S3_BUCKET}/site/" --delete --dryrun)
echo "$DRYRUN_OUTPUT"
DELETE_COUNT=$(echo "$DRYRUN_OUTPUT" | grep -c "delete:" || true)
if [ "$DELETE_COUNT" -gt 20 ]; then
  echo "Too many deletes: ${DELETE_COUNT}. Stop and review."
  exit 1
fi

Claude Codeに任せる範囲と、人間が見る範囲

Claude Codeは、CLIスクリプト、TypeScriptヘルパー、README、テスト、エラー処理を一気に作るのが得意です。特に、aws s3 syncのオプション整理、環境変数のチェック、署名付きURLのprefix検証、エラー時のメッセージ整備は任せやすいです。

一方で、IAMポリシーの最終確認、バケット名、本番prefix、削除権限、CloudFrontの公開範囲は人間が見ます。Claude Codeに作らせたら終わりではなく、aws sts get-caller-identityとaws s3 lsで対象アカウントを確認してから実行する。この小さな手順で、別アカウントや本番バケットへの誤操作をかなり減らせます。

長いセッションでS3作業を続けるなら、Claude Codeのコンテキスト管理に書いたように、CLAUDE.mdへ「本番S3ではDeleteObject禁止」「syncはdryrun先行」と残しておくのがおすすめです。

Masaの検証メモ

この記事で紹介した内容を、検証用バケットで実際に試した前提でまとめると、効果が大きかったのはdryrunの強制とprefix分離でした。特にassets、uploads、backupsを分けるだけで、IAMレビューがかなり楽になります。逆に、最初から「S3便利だから全部ここに置く」で始めると、あとで何が公開で何が非公開か分からなくなります。

Claude Codeに任せて楽になったのは、確認コマンドをREADMEへ書き出すところです。人間はコードが動いた瞬間に満足しがちですが、AIに「この変更が安全だと判断できる確認手順も書いて」と頼むと、運用メモまで残ります。これは小さいけれど、後日の自分をかなり助けます。

まとめ: S3連携は動くより先に事故らない設計

Claude Code × AWS S3は、静的サイト、画像管理、バックアップ、署名付きURLまでかなり相性が良い組み合わせです。ただし、S3は権限と削除の事故が目立つ領域です。初心者ほど、最小権限、prefix分離、dryrun、短い署名付きURL、CloudFront前提の公開範囲を先に決めてから作りましょう。

社内でClaude CodeとAWS運用を安全に始めたい場合は、Claude Code研修・相談で、実際のリポジトリに合わせたS3/IAM/デプロイ手順まで一緒に設計できます。

#claude-code #aws #s3 #iam #aws-cli #security
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。