<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SAM比較 - CayTech Lab</title>
	<atom:link href="https://caymezon.com/tag/sam%E6%AF%94%E8%BC%83/feed/" rel="self" type="application/rss+xml" />
	<link>https://caymezon.com</link>
	<description></description>
	<lastBuildDate>Sun, 08 Mar 2026 02:58:22 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://caymezon.com/wp-content/uploads/2026/01/cropped-CayTechLab-32x32.jpg</url>
	<title>SAM比較 - CayTech Lab</title>
	<link>https://caymezon.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<atom:link rel='hub' href='https://caymezon.com/?pushpress=hub'/>
	<item>
		<title>AWSコンソールだけで画像認識パイプラインを構築する手順【S3 + Lambda + Rekognition / SAM版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-rekognition-image-pipeline/</link>
					<comments>https://caymezon.com/aws-handson-console-rekognition-image-pipeline/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 08 Mar 2026 02:58:22 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[ML]]></category>
		<category><![CDATA[Rekognition]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[サーバーレス]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[画像認識]]></category>
		<category><![CDATA[画像認識パイプライン]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20249</guid>

					<description><![CDATA[<p>目次 はじめにキーワード解説使用するAWSサービス全体の作業順序① S3 バケットを作成する② Lambda 関数を作成するタイムアウトの設定コードの入力③ Lambda の実行ロールに権限を追加する3-1. Rekog [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-rekognition-image-pipeline/">AWSコンソールだけで画像認識パイプラインを構築する手順【S3 + Lambda + Rekognition / SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">キーワード解説</a></li><li><a href="#toc3" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① S3 バケットを作成する</a></li><li><a href="#toc6" tabindex="0">② Lambda 関数を作成する</a><ol><li><a href="#toc7" tabindex="0">タイムアウトの設定</a></li><li><a href="#toc8" tabindex="0">コードの入力</a></li></ol></li><li><a href="#toc9" tabindex="0">③ Lambda の実行ロールに権限を追加する</a><ol><li><a href="#toc10" tabindex="0">3-1. Rekognition 権限を追加する</a></li><li><a href="#toc11" tabindex="0">3-2. S3 GetObject 権限を追加する</a></li></ol></li><li><a href="#toc12" tabindex="0">④ Lambda に S3 トリガーを追加する</a></li><li><a href="#toc13" tabindex="0">⑤ 動作テスト</a><ol><li><a href="#toc14" tabindex="0">テスト用画像の準備</a></li><li><a href="#toc15" tabindex="0">画像をアップロードする</a></li><li><a href="#toc16" tabindex="0">CloudWatch Logs でラベル検出結果を確認する</a></li><li><a href="#toc17" tabindex="0">複数枚でテストする</a></li></ol></li><li><a href="#toc18" tabindex="0">⑥ リソースの削除</a><ol><li><a href="#toc19" tabindex="0">1. S3 バケットのオブジェクトを全て削除する</a></li><li><a href="#toc20" tabindex="0">2. S3 バケットを削除する</a></li><li><a href="#toc21" tabindex="0">3. Lambda のトリガーを削除する</a></li><li><a href="#toc22" tabindex="0">4. Lambda 関数を削除する</a></li><li><a href="#toc23" tabindex="0">5. IAM ロールを削除する（任意）</a></li><li><a href="#toc24" tabindex="0">6. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc25" tabindex="0">SAMとの対比</a></li><li><a href="#toc26" tabindex="0">トラブルシューティング</a></li><li><a href="#toc27" tabindex="0">まとめ</a><ol><li><a href="#toc28" tabindex="0">コンソール版で実感できたポイント</a></li></ol></li><li><a href="#toc29" tabindex="0">コンソール版と SAM 版を比較してみる</a></li><li><a href="#toc30" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「S3に画像をアップロードしたら、自動で中身を分析してほしい」——そんな仕組みを、<strong>AWSコンソールのみ</strong>でゼロから構築するハンズオンです。</p>
<p>Amazon Rekognition の <code>DetectLabels</code> API を使うと、画像に写っている物体・シーン・動物などを自動で検出できます。犬の写真をアップロードすれば「Dog（信頼度98%）」「Animal（97%）」といったラベルが返ってきます。</p>
<pre><code class="language-plaintext">ユーザー
  ↓ JPEG / PNG をアップロード
S3 バケット（UploadBucket）
  ↓ ObjectCreated イベント（自動）
Lambda（DetectFunction）
  ↓ rekognition:DetectLabels（S3Object を指定）
Amazon Rekognition
  ↓ [{"name": "Dog", "confidence": 98.5}, ...] を返す
Lambda
  ↓ print（JSON）
CloudWatch Logs</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li><strong>S3 トリガー</strong> — S3 へのアップロードを契機に Lambda を自動起動する仕組み</li>
<li><strong>Rekognition DetectLabels</strong> — 画像内の物体・シーン・動物を検出してラベルと信頼度を返す API</li>
<li><strong>IAM 権限管理</strong> — Lambda から S3・Rekognition を呼び出すために必要な権限の追加手順</li>
<li><strong>S3Object 参照</strong> — 画像データを Lambda に転送せず S3 の場所を直接 Rekognition に渡す効率的な方法</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="#">SAM版ハンズオン</a> の比較記事です。</strong><br />コンソール操作で S3・Lambda・Rekognition の連携を視覚的に学び、SAM と何が違うのかを比較したい方向けです。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>DetectLabels</strong></td>
<td>Rekognition API。画像内の物体・シーンを検出してラベル名と信頼度を返す</td>
</tr>
<tr>
<td><strong>信頼度（Confidence）</strong></td>
<td>ラベルが正確であるかどうかの確度（0〜100%）。今回は70%以上のみ返す</td>
</tr>
<tr>
<td><strong>S3Object 参照</strong></td>
<td>画像データを Lambda に転送せず、S3 の場所を Rekognition に渡す方式</td>
</tr>
<tr>
<td><strong>S3 イベント通知</strong></td>
<td>S3 バケットへのオブジェクト作成・削除などをトリガーに Lambda を呼び出す仕組み</td>
</tr>
<tr>
<td><strong>実行ロール</strong></td>
<td>Lambda が他の AWS サービスを操作するために使う IAM ロール</td>
</tr>
<tr>
<td><strong>無料枠</strong></td>
<td>最初の12ヶ月 / 月5,000枚まで無料。超過後は $0.001/枚</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc3">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>S3</strong></td>
<td>画像のアップロード先バケット</td>
<td>月5GBまで無料</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>S3 イベントを受けて Rekognition を呼び出す</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>Rekognition</strong></td>
<td>画像ラベル検出（DetectLabels）</td>
<td>最初の12ヶ月 / 月5,000枚まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda の実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambda の実行ログ（ラベル検出結果）</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① S3 バケットを作成する
      ↓
② Lambda 関数を作成する（コード入力・タイムアウト設定）
      ↓
③ Lambda の実行ロールに権限を追加する
  （S3: GetObject / Rekognition: DetectLabels）
      ↓
④ Lambda に S3 トリガーを追加する
      ↓
⑤ 動作テスト（画像をアップロード → ログを確認）
      ↓
⑥ リソースの削除</code></pre>
<hr>
<h2><span id="toc5">① S3 バケットを作成する</span></h2>
<p><strong>AWSコンソール → S3 → 「バケットを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>バケット名</td>
<td><code>my-rekognition-upload</code>（グローバルユニークな名前）</td>
</tr>
<tr>
<td>リージョン</td>
<td><strong>アジアパシフィック（東京）ap-northeast-1</strong></td>
</tr>
<tr>
<td>その他</td>
<td>デフォルトのまま</td>
</tr>
</tbody>
</table>
<p>「バケットを作成」をクリック。</p>
<p><strong>控えておく情報:</strong></p>
<ul>
<li><strong>バケット名</strong>（削除時・IAMポリシー設定時に使用）</li>
</ul>
<blockquote>
<p><strong>バケット名のグローバルユニークについて：</strong><br />S3 のバケット名は全 AWS アカウントで一意である必要があります。<code>my-rekognition-upload-</code> に自分のアカウントIDや日付を追加すると重複を避けられます。</p>
</blockquote>
<hr>
<h2><span id="toc6">② Lambda 関数を作成する</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>DetectFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルト）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリック。</p>
<h3><span id="toc7">タイムアウトの設定</span></h3>
<p><strong>「設定」タブ → 「一般設定」→「編集」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイムアウト</td>
<td><strong>30</strong> 秒</td>
</tr>
</tbody>
</table>
<p>「保存」をクリック。</p>
<blockquote>
<p><strong>タイムアウトを 30 秒にする理由：</strong><br />Rekognition API の呼び出しには数秒かかることがあります。デフォルト（3秒）では Rekognition のレスポンスを待ちきれずタイムアウトするため、余裕を持って 30 秒に設定します。</p>
</blockquote>
<h3><span id="toc8">コードの入力</span></h3>
<p>「コード」タブ → <code>lambda_function.py</code> を開いて既存の内容を全て置き換える。</p>
<pre><code class="language-python">import json
import urllib.parse
import boto3

rekognition = boto3.client("rekognition")


def lambda_handler(event, context):
    for record in event["Records"]:
        bucket = record["s3"]["bucket"]["name"]
        key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])

        print(json.dumps({"status": "start", "bucket": bucket, "key": key}))

        response = rekognition.detect_labels(
            Image={
                "S3Object": {
                    "Bucket": bucket,
                    "Name": key,
                }
            },
            MaxLabels=10,
            MinConfidence=70,
        )

        labels = [
            {
                "name": label["Name"],
                "confidence": round(label["Confidence"], 1),
            }
            for label in response["Labels"]
        ]

        result = {
            "bucket": bucket,
            "key": key,
            "label_count": len(labels),
            "labels": labels,
        }
        print(json.dumps(result, ensure_ascii=False))

    return {"processedCount": len(event["Records"])}</code></pre>
<p>「Deploy」ボタンをクリックしてコードを保存する。</p>
<p><strong>コードのポイント:</strong></p>
<table>
<thead>
<tr>
<th>ポイント</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>rekognition = boto3.client(&quot;rekognition&quot;)</code> をグローバルに置く</td>
<td>Lambda のコールドスタート時に1回だけ初期化。ウォームスタート時は再利用されパフォーマンスが向上する</td>
</tr>
<tr>
<td><code>urllib.parse.unquote_plus(key)</code></td>
<td>日本語や空白を含むファイル名は S3 イベントで URL エンコードされるため、デコードが必要</td>
</tr>
<tr>
<td><code>S3Object</code> 参照</td>
<td>画像データを Lambda のメモリに転送せず S3 の場所を Rekognition に渡す。メモリ効率が良い</td>
</tr>
<tr>
<td><code>MinConfidence=70</code></td>
<td>信頼度 70% 未満のラベルは結果から除外。全件見たい場合は <code>0</code> に変更して Deploy する</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc9">③ Lambda の実行ロールに権限を追加する</span></h2>
<p>デフォルトの実行ロールは CloudWatch Logs への書き込みのみ。<br />S3 からの読み取りと Rekognition の呼び出し権限を追加する。</p>
<p><strong>Lambda → <code>DetectFunction</code> → 「設定」タブ → 「アクセス権限」→ 実行ロール名のリンクをクリック</strong></p>
<p>（例: <code>DetectFunction-role-XXXX</code>）→ IAM コンソールのロール画面が開く。</p>
<h3><span id="toc10">3-1. Rekognition 権限を追加する</span></h3>
<p>「許可を追加」→「ポリシーをアタッチ」</p>
<p>検索ボックスに <code>Rekognition</code> と入力 → <strong><code>AmazonRekognitionReadOnlyAccess</code></strong> にチェック → 「許可を追加」。</p>
<blockquote>
<p><strong>AmazonRekognitionReadOnlyAccess に含まれる主な権限:</strong></p>
<ul>
<li><code>rekognition:DetectLabels</code> — ラベル検出（今回使用）</li>
<li><code>rekognition:DetectFaces</code> — 顔検出</li>
<li><code>rekognition:DetectText</code> — テキスト検出</li>
</ul>
</blockquote>
<h3><span id="toc11">3-2. S3 GetObject 権限を追加する</span></h3>
<p>「許可を追加」→「インラインポリシーを作成」</p>
<p>「JSON」タブを選択して以下を入力する（<code>my-rekognition-upload</code> を ① のバケット名に変更）:</p>
<pre><code class="language-json">{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-rekognition-upload/*"
    }
  ]
}</code></pre>
<p>「次へ」→ ポリシー名: <code>S3ReadForRekognition</code> → 「ポリシーを作成」。</p>
<blockquote>
<p><strong>なぜ S3 の権限が必要か:</strong><br />Rekognition に <code>S3Object</code> を指定した場合、Rekognition が Lambda の IAM ロールを借りて<br />S3 からオブジェクトを取得します。Lambda ロールに <code>s3:GetObject</code> がないと 403 エラーになります。</p>
<p>SAM版では <code>S3ReadPolicy</code>（SAM 組み込みポリシー）が特定バケットのみに <code>s3:GetObject</code> を自動付与します。<br />コンソール版では手動でインラインポリシーを作成する必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc12">④ Lambda に S3 トリガーを追加する</span></h2>
<p><strong>Lambda → <code>DetectFunction</code> → 「設定」タブ → 「トリガー」→「トリガーを追加」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ソース</td>
<td><strong>S3</strong></td>
</tr>
<tr>
<td>バケット</td>
<td><code>my-rekognition-upload</code>（① で作成したバケット）</td>
</tr>
<tr>
<td>イベントタイプ</td>
<td><strong>すべてのオブジェクト作成イベント（s3:ObjectCreated:*）</strong></td>
</tr>
<tr>
<td>プレフィックス</td>
<td>空欄（全ファイルを対象）</td>
</tr>
<tr>
<td>サフィックス</td>
<td>空欄（全形式を対象）</td>
</tr>
</tbody>
</table>
<p>「再帰呼び出し」の確認チェックボックスにチェック → 「追加」をクリック。</p>
<blockquote>
<p><strong>再帰呼び出しについて：</strong><br />Lambda の実行結果を同じバケットに書き込む構成にすると、S3 イベントが再発火して無限ループになります。<br />今回は S3 への書き込みを行わないため問題ありません。</p>
</blockquote>
<p><!-- ![S3トリガー追加画面：バケットとイベントタイプの設定](images/s3-trigger-setting.jpg) --></p>
<hr>
<h2><span id="toc13">⑤ 動作テスト</span></h2>
<h3><span id="toc14">テスト用画像の準備</span></h3>
<p>任意の JPEG または PNG 画像を用意する（例: 犬・猫・風景など）。<br />ファイルサイズは <strong>15MB 以下</strong> であることを確認する。</p>
<h3><span id="toc15">画像をアップロードする</span></h3>
<p><strong>方法 A: S3 コンソール</strong></p>
<p>S3 → <code>my-rekognition-upload</code> → 「アップロード」→ ファイルをドラッグ＆ドロップ → 「アップロード」</p>
<p><strong>方法 B: AWS CLI</strong></p>
<pre><code class="language-cmd">aws s3 cp "C:\Users\yourname\Pictures\dog.jpg" s3://my-rekognition-upload/ --region ap-northeast-1</code></pre>
<h3><span id="toc16">CloudWatch Logs でラベル検出結果を確認する</span></h3>
<p><strong>Lambda → <code>DetectFunction</code> → 「モニタリング」タブ → 「CloudWatch Logs を表示」</strong></p>
<p>最新のロットストリームを開いて以下のような出力を確認する。</p>
<pre><code class="language-json">{"status": "start", "bucket": "my-rekognition-upload", "key": "dog.jpg"}
{
  "bucket": "my-rekognition-upload",
  "key": "dog.jpg",
  "label_count": 8,
  "labels": [
    {"name": "Dog", "confidence": 98.5},
    {"name": "Pet", "confidence": 98.5},
    {"name": "Animal", "confidence": 98.5},
    {"name": "Canine", "confidence": 98.5},
    {"name": "Mammal", "confidence": 97.2},
    {"name": "Golden Retriever", "confidence": 85.3},
    {"name": "Grass", "confidence": 76.1},
    {"name": "Outdoors", "confidence": 71.4}
  ]
}
{"processedCount": 1}</code></pre>
<p><!-- ![CloudWatch Logsのラベル検出結果：犬の写真から8つのラベルが検出された様子](images/cloudwatch-detect-result.jpg) --></p>
<blockquote>
<p><strong><code>MinConfidence: 70</code> の効果：</strong><br />信頼度 70% 未満のラベルは結果に含まれません。<br />全ラベルを確認したい場合は <code>MinConfidence=0</code> に変更して「Deploy」する。</p>
</blockquote>
<h3><span id="toc17">複数枚でテストする</span></h3>
<pre><code class="language-cmd">aws s3 cp "C:\Users\yourname\Pictures\cat.jpg"  s3://my-rekognition-upload/ --region ap-northeast-1
aws s3 cp "C:\Users\yourname\Pictures\city.jpg" s3://my-rekognition-upload/ --region ap-northeast-1</code></pre>
<p>各ファイルのアップロードごとに Lambda が起動し、それぞれのラベル検出結果がログに記録される。</p>
<blockquote>
<p><strong>無料枠の管理：</strong><br />AWS コンソール → Billing → 無料利用枠 → 「Amazon Rekognition」で当月の使用枚数を確認できます。<br />月5,000枚まで無料のため、学習目的のハンズオンでは通常課金されません。</p>
</blockquote>
<hr>
<h2><span id="toc18">⑥ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除してください。</strong></p>
<h3><span id="toc19">1. S3 バケットのオブジェクトを全て削除する</span></h3>
<pre><code class="language-cmd">aws s3 rm s3://my-rekognition-upload --recursive --region ap-northeast-1</code></pre>
<h3><span id="toc20">2. S3 バケットを削除する</span></h3>
<p><strong>S3 → <code>my-rekognition-upload</code> → 「削除」→ バケット名を入力 → 「削除」</strong></p>
<h3><span id="toc21">3. Lambda のトリガーを削除する</span></h3>
<p><strong>Lambda → <code>DetectFunction</code> → 「設定」→「トリガー」→ S3 トリガーを選択 → 「削除」</strong></p>
<h3><span id="toc22">4. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>DetectFunction</code> → 「アクション」→「削除」</strong></p>
<h3><span id="toc23">5. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>DetectFunction-role-XXXX</code> を削除</strong></p>
<h3><span id="toc24">6. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/DetectFunction</code> → 削除</strong></p>
<blockquote>
<p><strong>SAM版との大きな違い（SAMのメリット）：</strong><br />SAM版では <code>sam delete</code> 1コマンドで上記すべてのリソースを一括削除できます。</p>
</blockquote>
<hr>
<h2><span id="toc25">SAMとの対比</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AWS::S3::Bucket</code></td>
<td>S3 → バケットを作成</td>
</tr>
<tr>
<td><code>S3ReadPolicy</code>（SAM組み込み）</td>
<td>IAM → ロールにインラインポリシーで <code>s3:GetObject</code> を追加</td>
</tr>
<tr>
<td><code>RekognitionDetectOnlyPolicy</code>（SAM組み込み）</td>
<td>IAM → ロールに <code>AmazonRekognitionReadOnlyAccess</code> をアタッチ</td>
</tr>
<tr>
<td><code>Events: Type: S3</code>（ObjectCreated）</td>
<td>Lambda → トリガーを追加（S3・全オブジェクト作成イベント）</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>S3を空にしてから削除 + Lambda + IAM + CloudWatch Logs を個別に削除</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>コンソール版のつまずきポイント：</strong><br /><code>AccessDeniedException</code> が出た場合、S3 の GetObject 権限（インラインポリシー）と Rekognition の DetectLabels 権限（AmazonRekognitionReadOnlyAccess）の両方が揃っているか確認しましょう。どちらか一方が欠けていてもエラーになります。</p>
</blockquote>
<hr>
<h2><span id="toc26">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lambda が動作しない（ログが出ない）</td>
<td>S3 トリガーが設定されていない</td>
<td>④ の手順で S3 トリガーを追加する</td>
</tr>
<tr>
<td><code>AccessDeniedException</code> for Rekognition</td>
<td>Lambda ロールに Rekognition 権限がない</td>
<td>③-1 の手順で <code>AmazonRekognitionReadOnlyAccess</code> をアタッチ</td>
</tr>
<tr>
<td><code>AccessDenied</code> for S3</td>
<td>Lambda ロールに S3 GetObject 権限がない</td>
<td>③-2 の手順でインラインポリシーを追加</td>
</tr>
<tr>
<td><code>InvalidImageFormatException</code></td>
<td>JPEG/PNG 以外のファイルをアップロードした</td>
<td>JPEG または PNG ファイルを使用する</td>
</tr>
<tr>
<td><code>ImageTooLargeException</code></td>
<td>15MB を超える画像をアップロードした</td>
<td>15MB 以下の画像を使用する</td>
</tr>
<tr>
<td>ラベルが 0 件</td>
<td><code>MinConfidence</code> が高すぎる</td>
<td>コードの <code>MinConfidence=70</code> を下げて「Deploy」する</td>
</tr>
<tr>
<td>日本語ファイル名でエラー</td>
<td>URL エンコードが解除されていない</td>
<td>コードに <code>urllib.parse.unquote_plus(key)</code> が含まれているか確認</td>
</tr>
<tr>
<td>Lambda がタイムアウトする</td>
<td>タイムアウトが短い（デフォルト3秒）</td>
<td>② の手順でタイムアウトを 30 秒に変更する</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc27">まとめ</span></h2>
<p>今回のハンズオンで体験できたこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>S3 トリガー</strong></td>
<td>画像アップロードと同時に Lambda が自動起動する仕組みを体験</td>
</tr>
<tr>
<td><strong>Rekognition DetectLabels</strong></td>
<td>画像に写った物体・動物・シーンが自動でラベル付けされる様子を確認</td>
</tr>
<tr>
<td><strong>S3Object 参照</strong></td>
<td>画像をLambdaに転送せずS3の場所だけを渡す効率的な連携方法</td>
</tr>
<tr>
<td><strong>IAM 権限の設定</strong></td>
<td>S3・Rekognition それぞれに必要な権限を個別に追加する手順</td>
</tr>
</tbody>
</table>
<h3><span id="toc28">コンソール版で実感できたポイント</span></h3>
<ul>
<li>S3 → Lambda → Rekognition という3つのサービスの<strong>データの流れ</strong>が視覚的に理解できる</li>
<li>実行ロールに必要な権限を1つずつ追加することで、IAM の仕組みが身につく</li>
<li>リソースを個別に作成・削除することで、各サービスの独立性と依存関係が明確になる</li>
</ul>
<hr>
<h2><span id="toc29">コンソール版と SAM 版を比較してみる</span></h2>
<p>コンソールで S3・Lambda・Rekognition の連携を理解したら、SAM で同じ構成をコードで定義することで「SAM が何を自動化しているか」が明確になります。<code>S3ReadPolicy</code> や <code>RekognitionDetectOnlyPolicy</code> による1行での権限付与など、コンソールでの手動操作がコードに対応しています。</p>
<p><!-- TODO: SAM版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc30">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-rekognition-image-pipeline/">AWSコンソールだけで画像認識パイプラインを構築する手順【S3 + Lambda + Rekognition / SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-rekognition-image-pipeline/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでSNS + SQS + Lambda 通知システムを構築する手順【Pub/Sub・ファンアウト・DLQ / SAM版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-sns-sqs-lambda/</link>
					<comments>https://caymezon.com/aws-handson-console-sns-sqs-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 08 Mar 2026 00:44:37 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[DLQ]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[SNS]]></category>
		<category><![CDATA[SQS]]></category>
		<category><![CDATA[サーバーレス]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[ファンアウト]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[通知システム]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20243</guid>

					<description><![CDATA[<p>目次 はじめにキーワード解説使用するAWSサービス全体の作業順序① SNS Topic を作成する② SQS キューを3つ作成する2-1. AlertDLQ（デッドレターキュー）を先に作成する2-2. LogQueue  [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-sns-sqs-lambda/">AWSコンソールだけでSNS + SQS + Lambda 通知システムを構築する手順【Pub/Sub・ファンアウト・DLQ / SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">キーワード解説</a></li><li><a href="#toc3" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① SNS Topic を作成する</a></li><li><a href="#toc6" tabindex="0">② SQS キューを3つ作成する</a><ol><li><a href="#toc7" tabindex="0">2-1. AlertDLQ（デッドレターキュー）を先に作成する</a></li><li><a href="#toc8" tabindex="0">2-2. LogQueue を作成する（フィルターなし・全メッセージ用）</a></li><li><a href="#toc9" tabindex="0">2-3. AlertQueue を作成する（フィルターあり・アラート用）</a></li></ol></li><li><a href="#toc10" tabindex="0">③ SNS → SQS サブスクリプションを2つ作成する</a><ol><li><a href="#toc11" tabindex="0">3-1. LogQueue サブスクリプション（フィルターなし）</a></li><li><a href="#toc12" tabindex="0">3-2. AlertQueue サブスクリプション（フィルターあり）</a></li></ol></li><li><a href="#toc13" tabindex="0">④ Lambda 関数を2つ作成する</a><ol><li><a href="#toc14" tabindex="0">4-1. LogFunction（全ログ処理）</a></li><li><a href="#toc15" tabindex="0">4-2. AlertFunction（アラート処理・DLQ テスト機能付き）</a></li></ol></li><li><a href="#toc16" tabindex="0">⑤ SQS トリガーを各 Lambda に追加する</a><ol><li><a href="#toc17" tabindex="0">5-1. LogFunction に LogQueue トリガーを追加する</a></li><li><a href="#toc18" tabindex="0">5-2. AlertFunction に AlertQueue トリガーを追加する</a></li></ol></li><li><a href="#toc19" tabindex="0">⑥ 動作テスト</a><ol><li><a href="#toc20" tabindex="0">テスト1: level=info（LogFunction のみ受信）</a></li><li><a href="#toc21" tabindex="0">テスト2: level=warning（両 Lambda が受信 ＝ ファンアウト）</a></li><li><a href="#toc22" tabindex="0">テスト3: level=warning + body=error（AlertFunction 失敗 → DLQ）</a></li></ol></li><li><a href="#toc23" tabindex="0">⑦ リソースの削除</a><ol><li><a href="#toc24" tabindex="0">1. Lambda のトリガーを削除する</a></li><li><a href="#toc25" tabindex="0">2. Lambda 関数を削除する</a></li><li><a href="#toc26" tabindex="0">3. SNS サブスクリプションを削除する</a></li><li><a href="#toc27" tabindex="0">4. SNS Topic を削除する</a></li><li><a href="#toc28" tabindex="0">5. SQS キューを3つ削除する</a></li><li><a href="#toc29" tabindex="0">6. IAM ロールを削除する（任意）</a></li><li><a href="#toc30" tabindex="0">7. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc31" tabindex="0">SAMとの対比</a></li><li><a href="#toc32" tabindex="0">トラブルシューティング</a></li><li><a href="#toc33" tabindex="0">まとめ</a><ol><li><a href="#toc34" tabindex="0">コンソール版で実感できたポイント</a></li></ol></li><li><a href="#toc35" tabindex="0">コンソール版と SAM 版を比較してみる</a></li><li><a href="#toc36" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「1回メッセージを送るだけで、複数のシステムに同時に通知したい」——そんな要件を実現する設計パターンが <strong>Pub/Sub（パブリッシュ・サブスクライブ）</strong> と <strong>ファンアウト</strong> です。</p>
<p>この記事では、<strong>AWSコンソールのみ</strong>を使って、SNS + SQS + Lambda による通知システムをゼロから構築するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">Publisher（aws sns publish）
  ↓ メッセージを1回発行するだけ
SNS Topic（NotificationTopic）
  │
  ├─ サブスクリプション（フィルターなし）
  │    → LogQueue → LogFunction → CloudWatch Logs（全メッセージを記録）
  │
  └─ サブスクリプション（level=warning/critical のみ）
       → AlertQueue → AlertFunction → CloudWatch Logs（アラート処理）
                          ↓ 処理失敗（3回）
                        AlertDLQ</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li><strong>Pub/Sub パターン</strong> — Publisher と Subscriber が疎結合で通信する仕組み</li>
<li><strong>ファンアウト</strong> — 1回の publish で複数の Lambda が並行して動作する体験</li>
<li><strong>SNS フィルターポリシー</strong> — メッセージ属性で配信先を絞り込む設定</li>
<li><strong>DLQ（デッドレターキュー）</strong> — 処理失敗メッセージの退避先を実際に確認</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="#">SAM版ハンズオン</a> の比較記事です。</strong><br />コンソール操作で SNS・SQS・Lambda の連携を視覚的に学び、SAM と何が違うのかを比較したい方向けです。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SNS Topic</strong></td>
<td>メッセージの送信先。複数のサブスクライバーに同時配信できる</td>
</tr>
<tr>
<td><strong>サブスクリプション</strong></td>
<td>Topic からメッセージを受け取るエンドポイントの設定</td>
</tr>
<tr>
<td><strong>Pub/Sub</strong></td>
<td>Publisher（発行者）と Subscriber（購読者）が疎結合で通信するパターン</td>
</tr>
<tr>
<td><strong>ファンアウト</strong></td>
<td>1つのメッセージを複数の宛先に同時配信するパターン</td>
</tr>
<tr>
<td><strong>フィルターポリシー</strong></td>
<td>メッセージ属性に基づき、配信するかどうかを制御するルール</td>
</tr>
<tr>
<td><strong>DLQ（デッドレターキュー）</strong></td>
<td>処理に失敗したメッセージを退避させるキュー</td>
</tr>
<tr>
<td><strong>SNS エンベロープ</strong></td>
<td>SNS が SQS に配信する際にメッセージを包む JSON 構造</td>
</tr>
<tr>
<td><strong>可視性タイムアウト</strong></td>
<td>SQS がメッセージを処理中に他のコンシューマーから見えなくする時間</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc3">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SNS</strong></td>
<td>メッセージの発行・ファンアウト配信</td>
<td>月100万リクエストまで無料</td>
</tr>
<tr>
<td><strong>SQS</strong></td>
<td>メッセージキューイング（LogQueue / AlertQueue / AlertDLQ）</td>
<td>月100万リクエストまで無料</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>キューからメッセージを受信して処理（LogFunction / AlertFunction）</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda の実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambda の実行ログ</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① SNS Topic を作成する
      ↓
② SQS キューを3つ作成する（AlertDLQ / LogQueue / AlertQueue）
      ↓
③ SNS → SQS サブスクリプションを2つ作成する
  （LogQueue: フィルターなし / AlertQueue: フィルターあり）
      ↓
④ Lambda 関数を2つ作成する
      ↓
⑤ SQS トリガーを各 Lambda に追加する
      ↓
⑥ 動作テスト（3パターン）
      ↓
⑦ リソースの削除</code></pre>
<blockquote>
<p><strong>AlertDLQ を先に作成する理由：</strong><br />AlertQueue の作成時に DLQ として AlertDLQ の ARN を指定するため、AlertDLQ を先に作る必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc5">① SNS Topic を作成する</span></h2>
<p><strong>AWSコンソール → SNS → 「トピック」→「トピックを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td><strong>スタンダード</strong></td>
</tr>
<tr>
<td>名前</td>
<td><code>NotificationTopic</code></td>
</tr>
</tbody>
</table>
<p>その他の設定はデフォルトのまま。「トピックを作成」をクリック。</p>
<p><strong>控えておく情報:</strong></p>
<ul>
<li><strong>トピック ARN</strong>（例: <code>arn:aws:sns:ap-northeast-1:123456789012:NotificationTopic</code>）</li>
</ul>
<blockquote>
<p><strong>スタンダードとFIFOの違い：</strong><br />スタンダードは順序保証なし・高スループット。FIFO は順序保証あり・1回限りの配信が必要な場合に使用します。今回のログ/アラート通知にはスタンダードが適しています。</p>
</blockquote>
<hr>
<h2><span id="toc6">② SQS キューを3つ作成する</span></h2>
<p><strong>AWSコンソール → SQS → 「キューを作成」</strong></p>
<h3><span id="toc7">2-1. AlertDLQ（デッドレターキュー）を先に作成する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td>スタンダード</td>
</tr>
<tr>
<td>名前</td>
<td><code>AlertDLQ</code></td>
</tr>
<tr>
<td>メッセージ保持期間</td>
<td>1 日（学習用なので短く設定）</td>
</tr>
</tbody>
</table>
<p>「キューを作成」をクリック。</p>
<p><strong>控えておく情報:</strong></p>
<ul>
<li><strong>AlertDLQ の ARN</strong>（例: <code>arn:aws:sqs:ap-northeast-1:123456789012:AlertDLQ</code>）</li>
</ul>
<hr>
<h3><span id="toc8">2-2. LogQueue を作成する（フィルターなし・全メッセージ用）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td>スタンダード</td>
</tr>
<tr>
<td>名前</td>
<td><code>LogQueue</code></td>
</tr>
<tr>
<td>可視性タイムアウト</td>
<td><strong>180</strong> 秒</td>
</tr>
</tbody>
</table>
<p>「キューを作成」をクリック。</p>
<blockquote>
<p><strong>可視性タイムアウトを 180 秒にする理由：</strong><br />Lambda のデフォルトタイムアウト（3秒）より長く設定することで、処理中に他のコンシューマーがメッセージを二重取得するのを防ぎます。DLQ テストでは 180秒 × 3回 ≒ 9分待つことになります。</p>
</blockquote>
<hr>
<h3><span id="toc9">2-3. AlertQueue を作成する（フィルターあり・アラート用）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td>スタンダード</td>
</tr>
<tr>
<td>名前</td>
<td><code>AlertQueue</code></td>
</tr>
<tr>
<td>可視性タイムアウト</td>
<td><strong>180</strong> 秒</td>
</tr>
</tbody>
</table>
<p>「デッドレターキュー」セクション:</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>デッドレターキューを有効にする</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>デッドレターキューの ARN</td>
<td><code>AlertDLQ</code> の ARN を貼り付ける</td>
</tr>
<tr>
<td>最大受信数</td>
<td><strong>3</strong></td>
</tr>
</tbody>
</table>
<p>「キューを作成」をクリック。</p>
<p><strong>控えておく情報:</strong></p>
<ul>
<li><strong>LogQueue の ARN</strong></li>
<li><strong>AlertQueue の ARN</strong></li>
</ul>
<hr>
<h2><span id="toc10">③ SNS → SQS サブスクリプションを2つ作成する</span></h2>
<blockquote>
<p><strong>SQS キューポリシーの自動追加について：</strong><br />コンソールで SNS → SQS サブスクリプションを作成すると、<br />SNS が SQS キューのアクセスポリシーに <code>sns.amazonaws.com</code> からの <code>sqs:SendMessage</code> 権限を自動追加します。<br />手動でのポリシー設定は不要です（SAM版では <code>AWS::SQS::QueuePolicy</code> を明示的に定義する必要があります）。</p>
</blockquote>
<h3><span id="toc11">3-1. LogQueue サブスクリプション（フィルターなし）</span></h3>
<p><strong>SNS → <code>NotificationTopic</code> → 「サブスクリプション」タブ → 「サブスクリプションを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>プロトコル</td>
<td><strong>Amazon SQS</strong></td>
</tr>
<tr>
<td>エンドポイント</td>
<td><code>LogQueue</code> の ARN</td>
</tr>
<tr>
<td>サブスクリプションフィルターポリシー</td>
<td><strong>設定しない</strong>（空欄のまま）</td>
</tr>
</tbody>
</table>
<p>「サブスクリプションを作成」をクリック。</p>
<hr>
<h3><span id="toc12">3-2. AlertQueue サブスクリプション（フィルターあり）</span></h3>
<p><strong>SNS → <code>NotificationTopic</code> → 「サブスクリプション」タブ → 「サブスクリプションを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>プロトコル</td>
<td><strong>Amazon SQS</strong></td>
</tr>
<tr>
<td>エンドポイント</td>
<td><code>AlertQueue</code> の ARN</td>
</tr>
</tbody>
</table>
<p>「サブスクリプションフィルターポリシー」セクション:</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サブスクリプションフィルターポリシー</td>
<td><strong>有効にする</strong></td>
</tr>
<tr>
<td>フィルターポリシーのスコープ</td>
<td><strong>メッセージ属性</strong>（デフォルト）</td>
</tr>
<tr>
<td>JSON エディタ</td>
<td>以下を入力</td>
</tr>
</tbody>
</table>
<pre><code class="language-json">{
  "level": ["warning", "critical"]
}</code></pre>
<blockquote>
<p><strong>フィルターポリシーの意味：</strong><br /><code>level</code> メッセージ属性の値が <code>&quot;warning&quot;</code> または <code>&quot;critical&quot;</code> のメッセージのみ AlertQueue に配信します。<br /><code>level=info</code> のメッセージは AlertQueue に届かない（LogQueue には届く）。</p>
</blockquote>
<blockquote>
<p><strong>よくある間違い（フィルターが動作しない場合）：</strong></p>
<ul>
<li>スコープが「<strong>メッセージ本文</strong>」になっている → **「メッセージ属性」**に変更する</li>
<li>JSON のスペルミス（<code>&quot;warning&quot;</code> のクォートが抜けている等）</li>
</ul>
</blockquote>
<p>「サブスクリプションを作成」をクリック。</p>
<hr>
<h2><span id="toc13">④ Lambda 関数を2つ作成する</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong>（共通設定）</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>コードを貼り付けたあと、必ず <strong>「Deploy」</strong> ボタンを押してコードを保存します。</p>
<hr>
<h3><span id="toc14">4-1. LogFunction（全ログ処理）</span></h3>
<p><strong>関数名</strong>: <code>LogFunction</code></p>
<p>コードエディタで <code>lambda_function.py</code> を開き、以下を貼り付けて「Deploy」をクリック。</p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    results = []

    for record in event["Records"]:
        sns_envelope = json.loads(record["body"])
        message = sns_envelope["Message"]  # 実際のメッセージ本文
        attributes = sns_envelope.get("MessageAttributes", {})
        level = attributes.get("level", {}).get("Value", "info")

        result = {
            "queue": "log",
            "level": level,
            "message": message,
        }
        print(json.dumps(result, ensure_ascii=False))
        results.append(result)

    print(json.dumps({"processedCount": len(results)}, ensure_ascii=False))
    return {"processedCount": len(results)}</code></pre>
<blockquote>
<p><strong><code>json.loads(record[&quot;body&quot;])</code> が必要な理由：</strong><br />SNS → SQS 配信では、SQS のメッセージボディに <strong>SNS エンベロープ</strong>（JSON文字列）が格納されます。<br />そのため <code>record[&quot;body&quot;]</code> はそのまま使えず、<code>json.loads</code> でパースする必要があります。</p>
<pre><code class="language-json">{
  "Type": "Notification",
  "TopicArn": "arn:aws:sns:...:NotificationTopic",
  "Message": "警告メッセージ",
  "MessageAttributes": {
    "level": {"Type": "String", "Value": "warning"}
  }
}</code></pre>
</blockquote>
<hr>
<h3><span id="toc15">4-2. AlertFunction（アラート処理・DLQ テスト機能付き）</span></h3>
<p><strong>関数名</strong>: <code>AlertFunction</code></p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    results = []

    for record in event["Records"]:
        sns_envelope = json.loads(record["body"])
        message = sns_envelope["Message"]
        attributes = sns_envelope.get("MessageAttributes", {})
        level = attributes.get("level", {}).get("Value", "unknown")

        # DLQテスト用: "error" というメッセージを受信したら意図的に例外発生
        if message.strip().lower() == "error":
            raise ValueError(
                f"アラート処理に失敗: level={level}, message={message}"
            )

        result = {
            "queue": "alert",
            "level": level,
            "message": message,
            "alert_triggered": True,
        }
        print(json.dumps(result, ensure_ascii=False))
        results.append(result)

    print(json.dumps({"processedCount": len(results)}, ensure_ascii=False))
    return {"processedCount": len(results)}</code></pre>
<blockquote>
<p><strong>DLQ テストのしくみ：</strong><br /><code>message == &quot;error&quot;</code> のとき意図的に <code>ValueError</code> を発生させています。<br />SQS は処理失敗を検知してメッセージをキューに戻し、可視性タイムアウト（180秒）後に再試行します。<br />これを3回繰り返すと <code>AlertDLQ</code> に移動します。</p>
</blockquote>
<hr>
<h2><span id="toc16">⑤ SQS トリガーを各 Lambda に追加する</span></h2>
<h3><span id="toc17">5-1. LogFunction に LogQueue トリガーを追加する</span></h3>
<p><strong>Lambda → <code>LogFunction</code> → 「設定」タブ → 「トリガー」→「トリガーを追加」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ソース</td>
<td><strong>SQS</strong></td>
</tr>
<tr>
<td>SQS キュー</td>
<td><code>LogQueue</code></td>
</tr>
<tr>
<td>バッチサイズ</td>
<td><strong>5</strong></td>
</tr>
<tr>
<td>トリガーの有効化</td>
<td>オン</td>
</tr>
</tbody>
</table>
<p>「追加」をクリック。</p>
<p><strong>権限の追加:</strong></p>
<p>Lambda → <code>LogFunction</code> → 「設定」タブ → 「アクセス権限」→ 実行ロール名をクリック（IAM コンソールへ）<br />→「許可を追加」→「ポリシーをアタッチ」→ <code>AWSLambdaSQSQueueExecutionRole</code> をアタッチ。</p>
<blockquote>
<p><strong><code>AWSLambdaSQSQueueExecutionRole</code> が必要な理由：</strong><br />Lambda が SQS からメッセージを受信（<code>sqs:ReceiveMessage</code>）・削除（<code>sqs:DeleteMessage</code>）するために必要な権限がまとまったポリシーです。これがないと Lambda がメッセージを取得できません。</p>
</blockquote>
<hr>
<h3><span id="toc18">5-2. AlertFunction に AlertQueue トリガーを追加する</span></h3>
<p><strong>Lambda → <code>AlertFunction</code> → 「設定」タブ → 「トリガー」→「トリガーを追加」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ソース</td>
<td><strong>SQS</strong></td>
</tr>
<tr>
<td>SQS キュー</td>
<td><code>AlertQueue</code></td>
</tr>
<tr>
<td>バッチサイズ</td>
<td><strong>1</strong></td>
</tr>
<tr>
<td>トリガーの有効化</td>
<td>オン</td>
</tr>
</tbody>
</table>
<p>「追加」をクリック。権限の追加（<code>AWSLambdaSQSQueueExecutionRole</code>）も同様に実施する。</p>
<blockquote>
<p><strong>AlertFunction のバッチサイズを 1 にする理由：</strong><br />1件ずつ処理することで、1件が失敗しても他のメッセージに影響が出ません。<br />DLQ へ移動するメッセージを1件に限定できるため、テストが分かりやすくなります。</p>
</blockquote>
<hr>
<h2><span id="toc19">⑥ 動作テスト</span></h2>
<p>3つのシナリオで SNS フィルター・ファンアウト・DLQ の動作を確認します。</p>
<table>
<thead>
<tr>
<th>テスト</th>
<th>メッセージ属性</th>
<th>LogFunction</th>
<th>AlertFunction</th>
<th>確認ポイント</th>
</tr>
</thead>
<tbody>
<tr>
<td>テスト1</td>
<td><code>level=info</code></td>
<td>処理 ✓</td>
<td>処理しない</td>
<td><strong>フィルター</strong>動作</td>
</tr>
<tr>
<td>テスト2</td>
<td><code>level=warning</code></td>
<td>処理 ✓</td>
<td>処理 ✓</td>
<td><strong>ファンアウト</strong>（1発行→2Lambda）</td>
</tr>
<tr>
<td>テスト3</td>
<td><code>level=warning</code> + body=<code>error</code></td>
<td>処理 ✓</td>
<td>失敗→DLQ</td>
<td><strong>DLQ</strong> 動作</td>
</tr>
</tbody>
</table>
<hr>
<h3><span id="toc20">テスト1: level=info（LogFunction のみ受信）</span></h3>
<pre><code class="language-cmd">aws sns publish ^
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:NotificationTopic ^
  --message "情報メッセージ" ^
  --message-attributes "{\"level\":{\"DataType\":\"String\",\"StringValue\":\"info\"}}" ^
  --region ap-northeast-1</code></pre>
<blockquote>
<p><code>123456789012</code> を自分のアカウントIDに置き換えてください。</p>
</blockquote>
<p><strong>期待する動作:</strong></p>
<ul>
<li><code>LogFunction</code> が処理 → CloudWatch Logs にログが記録される</li>
<li><code>AlertFunction</code> は動作しない（フィルターで除外）</li>
</ul>
<p><strong>CloudWatch Logs で確認:</strong></p>
<p>Lambda → <code>LogFunction</code> → 「モニタリング」タブ → 「CloudWatch Logs を表示」</p>
<pre><code class="language-json">{"queue": "log", "level": "info", "message": "情報メッセージ"}
{"processedCount": 1}</code></pre>
<hr>
<h3><span id="toc21">テスト2: level=warning（両 Lambda が受信 ＝ ファンアウト）</span></h3>
<pre><code class="language-cmd">aws sns publish ^
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:NotificationTopic ^
  --message "警告メッセージ" ^
  --message-attributes "{\"level\":{\"DataType\":\"String\",\"StringValue\":\"warning\"}}" ^
  --region ap-northeast-1</code></pre>
<p><strong>期待する動作:</strong></p>
<ul>
<li><code>LogFunction</code> が処理（<code>level=warning</code> を受信）</li>
<li><code>AlertFunction</code> も処理（フィルターを通過）</li>
<li><strong>1回の publish で 2つの Lambda が並行して動作する</strong> ← ファンアウトのポイント</li>
</ul>
<p><strong>LogFunction のログ:</strong></p>
<pre><code class="language-json">{"queue": "log", "level": "warning", "message": "警告メッセージ"}</code></pre>
<p><strong>AlertFunction のログ:</strong></p>
<pre><code class="language-json">{"queue": "alert", "level": "warning", "message": "警告メッセージ", "alert_triggered": true}</code></pre>
<p><!-- ![ファンアウト動作確認：LogFunction と AlertFunction が同時に実行](images/fanout-both-lambda.jpg) --></p>
<hr>
<h3><span id="toc22">テスト3: level=warning + body=error（AlertFunction 失敗 → DLQ）</span></h3>
<pre><code class="language-cmd">aws sns publish ^
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:NotificationTopic ^
  --message "error" ^
  --message-attributes "{\"level\":{\"DataType\":\"String\",\"StringValue\":\"warning\"}}" ^
  --region ap-northeast-1</code></pre>
<p><strong>期待する動作:</strong></p>
<ul>
<li><code>LogFunction</code> → 正常処理（<code>message=error</code> でも例外なし）</li>
<li><code>AlertFunction</code> → <code>ValueError</code> 発生</li>
<li>AlertQueue の可視性タイムアウト（180秒）後に再試行 × 3回 → <code>AlertDLQ</code> に移動</li>
</ul>
<blockquote>
<p><strong>DLQ に移動するまでの待機時間:</strong> 最大 180秒 × 3回 ≒ 9分かかります。<br />CloudWatch Logs で <code>AlertFunction</code> に <code>[ERROR] ValueError</code> が 3回記録されたことを確認してから DLQ をポーリングするとよいです。</p>
</blockquote>
<p><strong>DLQ にメッセージが届いたか確認:</strong></p>
<p>SQS → <code>AlertDLQ</code> → 「メッセージを送受信」→「メッセージをポーリング」</p>
<p><code>&quot;error&quot;</code> のメッセージ（SNS エンベロープ形式）が表示されれば DLQ 動作確認完了。</p>
<p><!-- ![AlertDLQ にメッセージが届いた様子](images/dlq-message-arrived.jpg) --></p>
<hr>
<h2><span id="toc23">⑦ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除してください。</strong></p>
<h3><span id="toc24">1. Lambda のトリガーを削除する</span></h3>
<ul>
<li><strong>Lambda → <code>LogFunction</code> → 「設定」→「トリガー」→ SQS トリガーを削除</strong></li>
<li><strong>Lambda → <code>AlertFunction</code> → 同様に削除</strong></li>
</ul>
<h3><span id="toc25">2. Lambda 関数を削除する</span></h3>
<ul>
<li><code>LogFunction</code> / <code>AlertFunction</code> を削除</li>
</ul>
<h3><span id="toc26">3. SNS サブスクリプションを削除する</span></h3>
<p><strong>SNS → <code>NotificationTopic</code> → 「サブスクリプション」タブ → 2つのサブスクリプションを削除</strong></p>
<h3><span id="toc27">4. SNS Topic を削除する</span></h3>
<p><strong>SNS → トピック → <code>NotificationTopic</code> → 「削除」</strong></p>
<h3><span id="toc28">5. SQS キューを3つ削除する</span></h3>
<p><strong>SQS → <code>LogQueue</code> / <code>AlertQueue</code> / <code>AlertDLQ</code> を各々削除</strong></p>
<h3><span id="toc29">6. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>LogFunction-role-XXXX</code> / <code>AlertFunction-role-XXXX</code> を削除</strong></p>
<h3><span id="toc30">7. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/LogFunction</code> / <code>/aws/lambda/AlertFunction</code> を削除</strong></p>
<blockquote>
<p><strong>SAM版との大きな違い（SAMのメリット）：</strong><br />SAM版では <code>sam delete</code> 1コマンドで上記すべてのリソースを一括削除できます。</p>
</blockquote>
<hr>
<h2><span id="toc31">SAMとの対比</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AWS::SNS::Topic</code></td>
<td>SNS → トピックを作成</td>
</tr>
<tr>
<td><code>AWS::SQS::QueuePolicy</code></td>
<td>SNS サブスクリプション作成時に<strong>自動追加</strong>される</td>
</tr>
<tr>
<td><code>AWS::SNS::Subscription</code></td>
<td>SNS → サブスクリプションを作成（フィルターポリシー含む）</td>
</tr>
<tr>
<td><code>FilterPolicy: &#39;{&quot;level&quot;: ...}&#39;</code></td>
<td>サブスクリプション作成時の「フィルターポリシー」に JSON を入力</td>
</tr>
<tr>
<td><code>SQSPollerPolicy</code> × 2</td>
<td>Lambda の IAM ロールに <code>AWSLambdaSQSQueueExecutionRole</code> をアタッチ</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>SNS / SQS × 3 / Lambda × 2 / IAM / ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>コンソール版の最大のつまずきポイント：</strong><br />SNS の「サブスクリプション」を作り忘れると、SNS publish しても SQS キューにメッセージが届きません。<br />「キューにメッセージが来ない」と感じたら、まずサブスクリプションが正しく作成されているか確認しましょう。</p>
</blockquote>
<hr>
<h2><span id="toc32">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>SNS publish してもキューにメッセージが来ない</td>
<td><strong>SNS サブスクリプションが未作成</strong></td>
<td>SNS → <code>NotificationTopic</code> → 「サブスクリプション」タブで2つ作成されているか確認</td>
</tr>
<tr>
<td>SNS publish してもキューにメッセージが来ない（その2）</td>
<td>SQS キューポリシーが設定されていない</td>
<td>SQS → キュー → 「アクセスポリシー」タブで <code>sns.amazonaws.com</code> からの <code>sqs:SendMessage</code> があるか確認</td>
</tr>
<tr>
<td><code>level=warning</code> でも AlertQueue に届かない</td>
<td>フィルターポリシーのスコープが「メッセージ本文」になっている</td>
<td>SNS → サブスクリプション → フィルターポリシーのスコープを**「メッセージ属性」**に変更</td>
</tr>
<tr>
<td>Lambda が実行されない</td>
<td>SQS トリガーが設定されていない</td>
<td>⑤ の手順でトリガーを追加する</td>
</tr>
<tr>
<td>Lambda が実行されない（SQS権限エラー）</td>
<td><code>AWSLambdaSQSQueueExecutionRole</code> がアタッチされていない</td>
<td>⑤ の権限追加手順を実施する</td>
</tr>
<tr>
<td>DLQ にメッセージが届かない</td>
<td>可視性タイムアウト（180秒）× 3回 の待機中</td>
<td>最大 9分待つ。CloudWatch Logs で 3回の ERROR ログを確認してからポーリング</td>
</tr>
<tr>
<td>SNS エンベロープの構造が分からない</td>
<td>Lambda のコードで <code>print(record[&quot;body&quot;])</code> して CloudWatch Logs で確認する</td>
<td></td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc33">まとめ</span></h2>
<p>今回のハンズオンで体験できたこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Pub/Sub パターン</strong></td>
<td>Publisher は誰が受け取るか知らずに SNS Topic に発行するだけ。Subscriber（SQS）が購読して処理</td>
</tr>
<tr>
<td><strong>ファンアウト</strong></td>
<td><code>level=warning</code> の1回の publish で LogFunction と AlertFunction の両方が並行して動作</td>
</tr>
<tr>
<td><strong>SNS フィルターポリシー</strong></td>
<td><code>level=info</code> は LogQueue のみ配信、<code>level=warning/critical</code> は両キューに配信</td>
</tr>
<tr>
<td><strong>DLQ</strong></td>
<td>AlertFunction が 3回失敗したメッセージが AlertDLQ に退避</td>
</tr>
</tbody>
</table>
<h3><span id="toc34">コンソール版で実感できたポイント</span></h3>
<ul>
<li>SNS Topic / SQS キュー / Lambda という3つのリソースの<strong>組み合わせ方</strong>が視覚的に理解できる</li>
<li>SNS サブスクリプションのフィルターポリシーJSON を直接入力することで、ルールの書き方が身につく</li>
<li>リソースを1つずつ作成することで、各サービスの役割と依存関係が明確になる</li>
</ul>
<hr>
<h2><span id="toc35">コンソール版と SAM 版を比較してみる</span></h2>
<p>コンソールで SNS + SQS + Lambda の連携を理解したら、SAM で同じ構成をコードで定義することで「SAM が何を自動化しているか」が明確になります。<code>AWS::SQS::QueuePolicy</code> の明示的な記述や <code>SQSPollerPolicy</code> によるワンライン権限付与など、コンソールでの手動操作がコードに対応しています。</p>
<p><!-- TODO: SAM版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc36">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-sns-sqs-lambda/">AWSコンソールだけでSNS + SQS + Lambda 通知システムを構築する手順【Pub/Sub・ファンアウト・DLQ / SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-sns-sqs-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</title>
		<link>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/</link>
					<comments>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 08:50:35 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[APIGateway]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cognito]]></category>
		<category><![CDATA[JWT]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[サーバーレス]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[新UI]]></category>
		<category><![CDATA[認証]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20237</guid>

					<description><![CDATA[<p>目次 はじめにCognito 新UIで戸惑いやすいポイント（先読み）キーワード解説前提条件使用するAWSサービス全体の作業順序① Cognito User Pool を作成する1-1. アプリケーションを定義する1-2. [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/">AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-6" checked><label class="toc-title" for="toc-checkbox-6">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">Cognito 新UIで戸惑いやすいポイント（先読み）</a></li><li><a href="#toc3" tabindex="0">キーワード解説</a></li><li><a href="#toc4" tabindex="0">前提条件</a></li><li><a href="#toc5" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc6" tabindex="0">全体の作業順序</a></li><li><a href="#toc7" tabindex="0">① Cognito User Pool を作成する</a><ol><li><a href="#toc8" tabindex="0">1-1. アプリケーションを定義する</a></li><li><a href="#toc9" tabindex="0">1-2. オプションを設定する</a></li><li><a href="#toc10" tabindex="0">1-3. リターン URL（スキップ）</a></li><li><a href="#toc11" tabindex="0">控えておく情報</a></li></ol></li><li><a href="#toc12" tabindex="0">② テスト用アプリクライアントを作成する</a><ol><li><a href="#toc13" tabindex="0">2-1. アプリケーションを定義する</a></li><li><a href="#toc14" tabindex="0">2-2. リターン URL（スキップ）</a></li><li><a href="#toc15" tabindex="0">2-3. Client secret configuration</a></li><li><a href="#toc16" tabindex="0">2-4. 認証フローを確認する</a></li></ol></li><li><a href="#toc17" tabindex="0">③ Lambda 関数を作成する</a><ol><li><a href="#toc18" tabindex="0">コードの入力</a></li></ol></li><li><a href="#toc19" tabindex="0">④ API Gateway REST API を作成する</a><ol><li><a href="#toc20" tabindex="0">4-1. API タイプの選択</a></li><li><a href="#toc21" tabindex="0">4-2. リソース /hello を作成する</a></li><li><a href="#toc22" tabindex="0">4-3. リソース /profile を作成する</a></li><li><a href="#toc23" tabindex="0">4-4. Cognito Authorizer を作成する</a></li><li><a href="#toc24" tabindex="0">4-5. /profile GET メソッドに Authorizer を設定する</a></li><li><a href="#toc25" tabindex="0">4-6. API をデプロイする</a></li></ol></li><li><a href="#toc26" tabindex="0">⑤ テストユーザーを作成する</a></li><li><a href="#toc27" tabindex="0">⑥ 動作テスト</a><ol><li><a href="#toc28" tabindex="0">テスト1: 公開エンドポイント（/hello）→ 200</a></li><li><a href="#toc29" tabindex="0">テスト2: 未認証でプライベートエンドポイント（/profile）→ 401</a></li><li><a href="#toc30" tabindex="0">テスト3: IDトークンを取得する</a></li><li><a href="#toc31" tabindex="0">テスト4: 認証ありでプライベートエンドポイント（/profile）→ 200</a></li></ol></li><li><a href="#toc32" tabindex="0">⑦ リソースの削除</a><ol><li><a href="#toc33" tabindex="0">1. API Gateway を削除する</a></li><li><a href="#toc34" tabindex="0">2. Lambda 関数を削除する</a></li><li><a href="#toc35" tabindex="0">3. Cognito User Pool を削除する</a></li><li><a href="#toc36" tabindex="0">4. IAM ロールを削除する（任意）</a></li><li><a href="#toc37" tabindex="0">5. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc38" tabindex="0">SAMとの対比</a></li><li><a href="#toc39" tabindex="0">トラブルシューティング</a></li><li><a href="#toc40" tabindex="0">まとめ</a></li><li><a href="#toc41" tabindex="0">コンソール版とSAM版を比較してみる</a></li><li><a href="#toc42" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「ログインしたユーザーだけが使えるAPIを作りたい」——そんな要件を、<strong>Amazon Cognito + API Gateway + Lambda</strong> はサーバー側の認証コードをほぼ書かずに実現します。</p>
<p>この記事では、<strong>AWSコンソールのみ</strong>を使って、以下の構成の認証付き REST API をゼロから構築するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">クライアント（curl）
  │
  ├─ GET /hello  → 認証不要 → Lambda → 200 OK
  │
  └─ GET /profile
        ├─ Authorizationヘッダーなし → API Gateway が 401 を返す（Lambda は呼ばれない）
        └─ Authorization: &lt;IDトークン&gt;
              → Cognito Authorizer が JWT を検証（Lambda 不要）
              → Lambda → email / sub を返す → 200 OK</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li>Amazon Cognito <strong>User Pool</strong> によるユーザー管理と JWT 発行</li>
<li>API Gateway の <strong>Cognito Authorizer</strong> を使ったエンドポイントごとの認証制御</li>
<li>Lambda 側で認証コードを書かずに <code>claims</code>（ユーザー情報）を取得するパターン</li>
<li><strong>新UI対応</strong> — Cognito コンソールの大幅変更点と、操作でハマりやすいポイント</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="#">SAM版ハンズオン</a> の比較記事です。</strong><br />コンソール操作でCognitoとAPI Gatewayの連携を視覚的に学び、SAMと何が違うのかを比較したい方向けです。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">Cognito 新UIで戸惑いやすいポイント（先読み）</span></h2>
<p>操作を始める前に、<strong>2026年時点の新UI</strong>で戸惑いやすい変更点を把握しておきましょう。</p>
<table>
<thead>
<tr>
<th>変更点</th>
<th>旧UI</th>
<th>新UI（現在）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>User Pool 作成の入口</strong></td>
<td>「ユーザープールを作成」ボタンから</td>
<td>**「アプリケーションを作成」**ボタンから（名称が変わった）</td>
</tr>
<tr>
<td><strong>作成の粒度</strong></td>
<td>User Pool → App Client を別々に作成</td>
<td><strong>1ページのウィザード</strong>で User Pool とクライアントを同時作成</td>
</tr>
<tr>
<td><strong>クライアントシークレット</strong></td>
<td>デフォルトなし</td>
<td>「従来のウェブアプリケーション」を選ぶと<strong>シークレット必須</strong>になる</td>
</tr>
<tr>
<td><strong>User Pool 名</strong></td>
<td>指定した名前がそのまま付く</td>
<td>アプリ名の前に <strong><code>User pool - </code></strong> が自動で付く（例: <code>User pool - MyWebApp</code>）</td>
</tr>
<tr>
<td><strong>クライアント ID の場所</strong></td>
<td>概要ページに表示</td>
<td>左サイドバー → 「アプリケーション」から辿る</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>最大のハマりポイント（クライアントシークレット）：</strong><br />新UIの「アプリケーションを作成」で「従来のウェブアプリケーション」を選ぶと、クライアントシークレットが<strong>自動で付与</strong>されます。シークレットありのクライアントで <code>initiate-auth</code> を実行すると <code>SECRET_HASH was not received</code> エラーが出て詰まります。<br />このハンズオンでは②の手順でシークレットなしのクライアントを別途作成します。</p>
</blockquote>
<hr>
<h2><span id="toc3">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>User Pool</strong></td>
<td>Cognitoのユーザーディレクトリ。ユーザー登録・認証・JWT発行を一手に担う</td>
</tr>
<tr>
<td><strong>User Pool Client</strong></td>
<td>アプリが User Pool に接続するための設定。<strong>Client ID</strong> を持つ</td>
</tr>
<tr>
<td><strong>IDトークン</strong></td>
<td>ログイン成功時に Cognito が発行する JWT。email / sub などのユーザー情報を含む</td>
</tr>
<tr>
<td><strong>Cognito Authorizer</strong></td>
<td>API Gateway が IDトークンを検証する認可機能。Lambdaコードが不要で動作する</td>
</tr>
<tr>
<td><strong>claims</strong></td>
<td>JWT ペイロードに含まれる情報（email / sub / token_use など）</td>
</tr>
<tr>
<td><strong>FORCE_CHANGE_PASSWORD</strong></td>
<td>管理者作成ユーザーの初期状態。この状態では <code>initiate-auth</code> がトークンを返さない</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">前提条件</span></h2>
<table>
<thead>
<tr>
<th>ツール</th>
<th>確認コマンド</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWSアカウント</td>
<td>—</td>
<td>IAMユーザーまたはルートユーザー</td>
</tr>
<tr>
<td>AWS CLI v2（テスト用）</td>
<td><code>aws --version</code></td>
<td>IDトークン取得・ユーザー作成に使用</td>
</tr>
</tbody>
</table>
<blockquote>
<p>AWS CLI がない場合は、テスト操作に <strong>AWSコンソールの CloudShell</strong> を代用できます（後述）。</p>
</blockquote>
<hr>
<h2><span id="toc5">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Amazon Cognito</strong></td>
<td>ユーザー管理・認証・JWT発行</td>
<td>月5万MAU（月間アクティブユーザー）まで無料</td>
</tr>
<tr>
<td><strong>API Gateway</strong></td>
<td>REST API のエンドポイント管理・認可</td>
<td>月100万リクエストまで無料（無料期間12ヶ月）</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>APIのビジネスロジック（1関数）</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda の実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambda の実行ログ</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① Cognito User Pool を作成する（新UI対応）
      ↓
② テスト用アプリクライアントを作成する（シークレットなし）
      ↓
③ Lambda 関数を作成する
      ↓
④ API Gateway REST API を作成する
  （/hello・/profile エンドポイント + Cognito Authorizer 設定）
      ↓
⑤ テストユーザーを作成する
      ↓
⑥ 動作テスト（401確認 → JWTトークン取得 → 認証成功）
      ↓
⑦ リソースの削除</code></pre>
<hr>
<h2><span id="toc7">① Cognito User Pool を作成する</span></h2>
<p><strong>AWSコンソール → Cognito → 「アプリケーションを作成」</strong></p>
<p><!-- ![Cognito コンソールのトップ画面](images/cognito-top.jpg) --></p>
<blockquote>
<p><strong>新UIの注意：</strong><br />旧UIにあった「ユーザープールを作成」ボタンは廃止されています。現在は「<strong>アプリケーションを作成</strong>」からウィザードで User Pool とクライアントをまとめて作成します。</p>
</blockquote>
<h3><span id="toc8">1-1. アプリケーションを定義する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>アプリケーションタイプ</td>
<td><strong>従来のウェブアプリケーション</strong></td>
</tr>
<tr>
<td>アプリケーション名</td>
<td><code>MyWebApp</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc9">1-2. オプションを設定する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サインイン識別子のオプション</td>
<td><strong>メールアドレス</strong> にチェック（電話番号・ユーザー名はチェック不要）</td>
</tr>
<tr>
<td>自己登録を有効</td>
<td>チェックする（デフォルトでチェック済み）</td>
</tr>
<tr>
<td>サインアップのための必須属性</td>
<td>空欄のまま（属性を選択しない）</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>サインイン識別子は作成後に変更不可。</strong> 「メールアドレス」のみ選択しておくことを推奨します。</p>
</blockquote>
<h3><span id="toc10">1-3. リターン URL（スキップ）</span></h3>
<p>「リターン URL を追加」は入力不要（今回はマネージドログインページを使わないため）。</p>
<p>画面下部の「<strong>ユーザーディレクトリを作成する</strong>」をクリック。</p>
<h3><span id="toc11">控えておく情報</span></h3>
<p>作成後、User Pool の概要ページが開きます。</p>
<ul>
<li><strong>ユーザープール ID</strong>（例: <code>ap-northeast-1_XXXXXXXX</code>）<br />→ 概要ページの「ユーザープール情報」欄に表示</li>
<li><strong>クライアント ID</strong>（例: <code>XXXXXXXXXXXXXXXXXXXXXXXXXX</code>）<br />→ 左サイドバー「アプリケーション」→「アプリケーションクライアント」→ <code>MyWebApp</code> をクリック → 「クライアント ID」欄</li>
</ul>
<blockquote>
<p><strong>注意：</strong> 概要ページの「レコメンデーション」欄にも <code>MyWebApp</code> のリンクが表示されますが、これは Quick Setup ガイドへの誘導です。クライアント ID は左サイドバーから辿ってください。</p>
</blockquote>
<blockquote>
<p><strong>User Pool 名について：</strong><br />新UIでは、アプリ名の前に <code>User pool - </code> が自動で付きます（例: <code>User pool - MyWebApp</code>）。以降の手順では「作成した User Pool」と表記します。</p>
</blockquote>
<hr>
<h2><span id="toc12">② テスト用アプリクライアントを作成する</span></h2>
<p>新UIの「アプリケーションを作成」で自動作成された <code>MyWebApp</code> クライアントには<strong>クライアントシークレットが自動付与</strong>されています。シークレットありのクライアントで CLI から <code>initiate-auth</code> を実行すると <code>SECRET_HASH was not received</code> エラーが出ます。</p>
<p>そのため、<strong>シークレットなし・<code>ALLOW_USER_PASSWORD_AUTH</code> 有効</strong>の新しいクライアントを別途作成します。</p>
<p><strong>Cognito → 作成した User Pool → 左サイドバー「アプリケーション」→「アプリケーションクライアント」→「アプリケーションクライアントを作成」</strong></p>
<h3><span id="toc13">2-1. アプリケーションを定義する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>アプリケーションタイプ</td>
<td><strong>シングルページアプリケーション (SPA)</strong></td>
</tr>
<tr>
<td>アプリケーション名</td>
<td><code>MyWebAppClient</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>「SPA」を選ぶ理由：</strong><br />新UIでは「従来のウェブアプリケーション」を選ぶとクライアントシークレットが<strong>必須</strong>になります。「SPA」を選ぶとシークレットなしで作成できます。CLI テスト目的ではこちらを使います。</p>
</blockquote>
<h3><span id="toc14">2-2. リターン URL（スキップ）</span></h3>
<p>入力不要。</p>
<h3><span id="toc15">2-3. Client secret configuration</span></h3>
<p>SPA を選択した場合、この欄は表示されません（シークレットなしで自動確定）。</p>
<p>「<strong>アプリケーションクライアントを作成</strong>」をクリック。</p>
<h3><span id="toc16">2-4. 認証フローを確認する</span></h3>
<p>作成後、<code>MyWebAppClient</code> をクリックして詳細画面を開きます。</p>
<p>「認証フロー」セクションに <strong><code>ALLOW_USER_PASSWORD_AUTH</code></strong> が含まれていることを確認します。</p>
<p>含まれていない場合は「編集」→「ALLOW_USER_PASSWORD_AUTH」にチェック → 「変更を保存」。</p>
<blockquote>
<p><strong>ALLOW_USER_PASSWORD_AUTH とは：</strong><br />CLI から username と password を直接指定して認証する「ユーザーパスワード認証」フローです。テスト用に有効化します（本番環境では SRP フローが推奨）。</p>
</blockquote>
<p><strong>控えておく情報（更新）：</strong></p>
<ul>
<li><strong>クライアント ID</strong> → 新しく作成した <code>MyWebAppClient</code> のクライアント ID を使う（① の <code>MyWebApp</code> のクライアント ID は使わない）</li>
</ul>
<hr>
<h2><span id="toc17">③ Lambda 関数を作成する</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>CognitoApiFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリック。</p>
<h3><span id="toc18">コードの入力</span></h3>
<p>関数ページ → 「コード」タブ → <code>lambda_function.py</code> を開いて既存の内容を<strong>全て置き換え</strong>て以下を貼り付けます。</p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    resource = event.get("resource", "/")  # API Gateway プロキシ統合: リクエストパスが "resource" に入る

    if resource == "/hello":
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"message": "Hello! This is a public endpoint."}),
        }

    if resource == "/profile":
        # event["requestContext"]["authorizer"]["claims"] に JWT ペイロードが格納される
        claims = (
            event.get("requestContext", {})
            .get("authorizer", {})
            .get("claims", {})
        )
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(
                {
                    "message": "認証成功",
                    "email": claims.get("email"),
                    "sub": claims.get("sub"),          # Cognito が生成したユーザーの一意 ID
                    "token_use": claims.get("token_use"),  # "id" が返る（IDトークンを使っているため）
                },
                ensure_ascii=False,
            ),
        }

    return {
        "statusCode": 404,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"message": "Not Found"}),
    }</code></pre>
<p>「<strong>Deploy</strong>」ボタンをクリックしてコードを保存します。</p>
<blockquote>
<p><strong>Lambda 側で認証コードが不要な理由：</strong><br />API Gateway の Cognito Authorizer が IDトークン（JWT）の検証をすべて担っています。Lambda が呼ばれた時点では認証済みであることが保証されており、検証済みの <code>claims</code> だけを受け取って使えばよい設計です。</p>
</blockquote>
<hr>
<h2><span id="toc19">④ API Gateway REST API を作成する</span></h2>
<p><strong>AWSコンソール → API Gateway → 「APIを作成」</strong></p>
<h3><span id="toc20">4-1. API タイプの選択</span></h3>
<p>「REST API」の「<strong>構築</strong>」をクリック。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>API タイプ</td>
<td><strong>REST API</strong>（「プライベート」ではない方）</td>
</tr>
<tr>
<td>新しい API の作成</td>
<td>「新しい API」</td>
</tr>
<tr>
<td>API 名</td>
<td><code>CognitoSampleApi</code></td>
</tr>
<tr>
<td>エンドポイントタイプ</td>
<td>リージョン</td>
</tr>
</tbody>
</table>
<p>「<strong>APIを作成</strong>」をクリック。</p>
<hr>
<h3><span id="toc21">4-2. リソース /hello を作成する</span></h3>
<p>左のリソースツリーで <strong><code>/</code>（ルート）を選択</strong> → 「<strong>リソースを作成</strong>」ボタンをクリック</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソースパス（親パス）</td>
<td><code>/</code>（変更不要）</td>
</tr>
<tr>
<td>リソース名</td>
<td><code>hello</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>新UIの注意点：</strong><br />「リソースパス」はリソースを作成する<strong>親パスの選択</strong>（<code>/</code> = ルート配下という意味）です。<code>/hello</code> と入力する欄ではありません。「リソース名」に <code>hello</code> と入力するだけで OK です。</p>
</blockquote>
<p>「<strong>リソースを作成</strong>」をクリック。</p>
<p><strong><code>/hello</code> を選択した状態で → 「メソッドを作成」→ メソッドタイプ <code>GET</code> を選択</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>統合タイプ</td>
<td><strong>Lambda 関数</strong></td>
</tr>
<tr>
<td>Lambda プロキシ統合の使用</td>
<td><strong>チェックする</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>CognitoApiFunction</code></td>
</tr>
</tbody>
</table>
<p>「保存」→「OK」（Lambda 呼び出し権限の追加確認）。</p>
<hr>
<h3><span id="toc22">4-3. リソース /profile を作成する</span></h3>
<p>左のリソースツリーで <strong><code>/</code>（ルート）を選択</strong> → 「<strong>リソースを作成</strong>」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソースパス（親パス）</td>
<td><code>/</code>（変更不要）</td>
</tr>
<tr>
<td>リソース名</td>
<td><code>profile</code></td>
</tr>
</tbody>
</table>
<p>「<strong>リソースを作成</strong>」をクリック。</p>
<p><strong><code>/profile</code> を選択した状態で → 「メソッドを作成」→ メソッドタイプ <code>GET</code> を選択</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>統合タイプ</td>
<td><strong>Lambda 関数</strong></td>
</tr>
<tr>
<td>Lambda プロキシ統合の使用</td>
<td><strong>チェックする</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>CognitoApiFunction</code></td>
</tr>
</tbody>
</table>
<p>「保存」をクリック。</p>
<hr>
<h3><span id="toc23">4-4. Cognito Authorizer を作成する</span></h3>
<p>左側メニューの「<strong>オーソライザー</strong>」→「<strong>オーソライザーを作成</strong>」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>オーソライザー名</td>
<td><code>CognitoAuthorizer</code></td>
</tr>
<tr>
<td>オーソライザーのタイプ</td>
<td><strong>Cognito</strong></td>
</tr>
<tr>
<td>Cognito ユーザープール（リージョン）</td>
<td><code>ap-northeast-1</code>（変更不要）</td>
</tr>
<tr>
<td>Cognito ユーザープール（検索欄）</td>
<td>① で作成した User Pool を選択（例: <code>User pool - MyWebApp</code>）</td>
</tr>
<tr>
<td>トークンのソース</td>
<td><code>Authorization</code>（<strong>必ず入力する</strong>）</td>
</tr>
<tr>
<td>トークンの検証（オプション）</td>
<td>空欄のまま</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>新UIの注意点：</strong><br />「トークンのソース」はデフォルトで<strong>空欄</strong>になっています。<code>Authorization</code> と入力しないと動作しません。入力を忘れると全リクエストが 401 になります。</p>
</blockquote>
<p>「<strong>オーソライザーを作成</strong>」をクリック。</p>
<p><strong>動作確認：</strong></p>
<p>「オーソライザーのテスト」→ テスト用トークン欄に適当な文字を入力 → 「テスト」→ <code>401</code> が返れば正常（正しいトークンがないため 401 が正解）。</p>
<p><!-- ![Cognito Authorizer のテスト画面](images/cognito-authorizer-test.jpg) --></p>
<hr>
<h3><span id="toc24">4-5. /profile GET メソッドに Authorizer を設定する</span></h3>
<p>左のリソースツリーで <strong><code>/profile</code> → <code>GET</code></strong> を選択 → 「メソッドリクエストの設定」セクションの「<strong>編集</strong>」ボタンをクリック</p>
<p>「認可」ドロップダウンを開き、<strong><code>Cognito ユーザープールオーソライザー</code></strong> の配下にある <strong><code>CognitoAuthorizer</code></strong> を選択 → 「<strong>保存</strong>」</p>
<blockquote>
<p><strong>新UIの注意点：</strong><br />選択肢は <code>なし</code> / <code>AWS IAM</code> / <code>Cognito ユーザープールオーソライザー</code>（カテゴリ）→ <code>CognitoAuthorizer</code> の階層構造になっています。<br /><code>CognitoAuthorizer</code> はカテゴリ名ではなく、その下にインデントされた項目を選んでください。</p>
</blockquote>
<blockquote>
<p><strong>ポイント：</strong><br /><code>/hello GET</code> には Authorizer を<strong>設定しない</strong>（認証不要）。<br /><code>/profile GET</code> にのみ CognitoAuthorizer を設定することで、エンドポイントごとに認証要件を分けます。</p>
</blockquote>
<hr>
<h3><span id="toc25">4-6. API をデプロイする</span></h3>
<p><strong>「アクション」→「API のデプロイ」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>デプロイされるステージ</td>
<td><strong>「新しいステージ」</strong></td>
</tr>
<tr>
<td>ステージ名</td>
<td><code>Prod</code></td>
</tr>
</tbody>
</table>
<p>「デプロイ」をクリック。</p>
<p><strong>控えておく情報：</strong></p>
<p>「Prod ステージエディター」に表示される <strong>URL の呼び出し</strong>（例: <code>https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod</code>）をコピーします。</p>
<hr>
<h2><span id="toc26">⑤ テストユーザーを作成する</span></h2>
<p><strong>Cognito → 作成した User Pool → 左サイドバー「ユーザー管理」→「ユーザー」→「ユーザーを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>招待メッセージ</td>
<td><strong>「招待を送信しない」</strong> を選択</td>
</tr>
<tr>
<td>E メールアドレス</td>
<td><code>test@example.com</code></td>
</tr>
<tr>
<td>仮パスワード</td>
<td><strong>「パスワードの設定」</strong> を選択</td>
</tr>
<tr>
<td>パスワード</td>
<td><code>TestPass1!</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>パスワードポリシー（新UIのデフォルト）：</strong><br />最小8文字 / 数字・小文字・大文字・特殊文字をそれぞれ1文字以上含むこと。<br /><code>TestPass1</code> は特殊文字がないため不可。<code>TestPass1!</code> を使ってください。</p>
</blockquote>
<p>「<strong>ユーザーを作成</strong>」をクリック。</p>
<blockquote>
<p>ユーザーの「確認ステータス」列に <strong>「パスワードを強制的に変更」</strong> と表示されます（= FORCE_CHANGE_PASSWORD 状態）。<br />この状態で <code>initiate-auth</code> を実行してもトークンが返らず <code>NEW_PASSWORD_REQUIRED</code> チャレンジが返されます。<br />次の CLI コマンドで永続パスワードを設定して「確認済み」（CONFIRMED）に変更します。</p>
</blockquote>
<p><strong>CLI で永続パスワードを設定する：</strong></p>
<p><strong>方法 A: CloudShell（コンソール版ハンズオンにおすすめ）</strong></p>
<p>AWSコンソール画面下部の「<strong>CloudShell</strong>」をクリックして起動します。コンソールと同じ認証情報が自動で使われるため追加設定は不要。</p>
<pre><code class="language-bash">aws cognito-idp admin-set-user-password \
  --user-pool-id ap-northeast-1_XXXXXXXX \
  --username test@example.com \
  --password 'TestPass1!' \
  --permanent \
  --region ap-northeast-1</code></pre>
<blockquote>
<p>CloudShell は Linux シェルのため <code>\</code> で改行します。<code>!</code> を含むパスワードはシングルクォート <code>&#39;...&#39;</code> で囲んでください（ダブルクォートだと bash がエラーになる場合があります）。</p>
</blockquote>
<p><strong>方法 B: ローカルの AWS CLI（コマンドプロンプト）</strong></p>
<pre><code class="language-cmd">aws cognito-idp admin-set-user-password ^
  --user-pool-id ap-northeast-1_XXXXXXXX ^
  --username test@example.com ^
  --password TestPass1! ^
  --permanent ^
  --region ap-northeast-1</code></pre>
<blockquote>
<p><code>ap-northeast-1_XXXXXXXX</code> を ① で控えた<strong>ユーザープール ID</strong> に置き換えてください。</p>
</blockquote>
<p>コマンドが出力なしで返れば成功です。コンソールでユーザーの「確認ステータス」が**「確認済み」**に変わったことを確認してください。</p>
<hr>
<h2><span id="toc27">⑥ 動作テスト</span></h2>
<h3><span id="toc28">テスト1: 公開エンドポイント（/hello）→ 200</span></h3>
<pre><code class="language-cmd">curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/hello</code></pre>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{"message": "Hello! This is a public endpoint."}</code></pre>
<hr>
<h3><span id="toc29">テスト2: 未認証でプライベートエンドポイント（/profile）→ 401</span></h3>
<pre><code class="language-cmd">curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<p>期待するレスポンス（API Gateway が返す。Lambda は呼ばれていない）:</p>
<pre><code class="language-json">{"message": "Unauthorized"}</code></pre>
<hr>
<h3><span id="toc30">テスト3: IDトークンを取得する</span></h3>
<pre><code class="language-cmd">aws cognito-idp initiate-auth ^
  --auth-flow USER_PASSWORD_AUTH ^
  --auth-parameters "USERNAME=test@example.com,PASSWORD=TestPass1!" ^
  --client-id XXXXXXXXXXXXXXXXXXXXXXXXXX ^
  --region ap-northeast-1</code></pre>
<blockquote>
<p><code>XXXXXXXXXXXXXXXXXXXXXXXXXX</code> を <strong>② で控えた <code>MyWebAppClient</code> のクライアント ID</strong> に置き換えてください（① の <code>MyWebApp</code> のクライアント ID ではありません）。</p>
</blockquote>
<p>レスポンス例（抜粋）:</p>
<pre><code class="language-json">{
    "AuthenticationResult": {
        "AccessToken": "eyJra...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjb...",
        "IdToken": "eyJra..."
    }
}</code></pre>
<p><strong><code>IdToken</code> の値をコピーしておきます</strong>（次のテストで使用）。</p>
<blockquote>
<p><strong>IdToken と AccessToken の違い：</strong></p>
<table>
<thead>
<tr>
<th>トークン</th>
<th>用途</th>
<th>含まれる情報</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IdToken</strong></td>
<td>ユーザー認証（今回使用）</td>
<td>email / sub など</td>
</tr>
<tr>
<td>AccessToken</td>
<td>Cognito API へのアクセス</td>
<td>sub / scope など</td>
</tr>
</tbody>
</table>
<p>API Gateway の Cognito Authorizer に渡すのは <strong>IdToken</strong>。AccessToken を渡しても 403 になります。</p>
</blockquote>
<hr>
<h3><span id="toc31">テスト4: 認証ありでプライベートエンドポイント（/profile）→ 200</span></h3>
<p>IdToken は非常に長いため、変数に格納してから実行します。</p>
<p><strong>方法 A: CloudShell（おすすめ）</strong></p>
<pre><code class="language-bash">TOKEN="eyJra...（IdToken全体を貼り付ける）"
curl -H "Authorization: $TOKEN" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<p><strong>方法 B: Windows CMD（変数使用）</strong></p>
<pre><code class="language-cmd">set TOKEN=eyJra...（IdToken全体を貼り付ける）
curl -H "Authorization: %TOKEN%" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<blockquote>
<p><strong>重要：</strong> CMD では変数展開に <code>%TOKEN%</code> を使います。<code>$TOKEN</code>（bash 構文）を CMD で使うと文字列 <code>$TOKEN</code> がそのまま送られ 401 になります。<br />また <code>Bearer</code> プレフィックスは不要です。raw JWT をそのまま Authorization ヘッダーに指定してください。</p>
</blockquote>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{
  "message": "認証成功",
  "email": "test@example.com",
  "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token_use": "id"
}</code></pre>
<blockquote>
<p><code>sub</code> は Cognito が自動生成したユーザーの一意 ID です。<br /><code>token_use: &quot;id&quot;</code> は IDトークンを使っていることを示します。</p>
</blockquote>
<p><!-- ![認証成功レスポンス](images/cognito-auth-success.jpg) --></p>
<hr>
<h2><span id="toc32">⑦ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<h3><span id="toc33">1. API Gateway を削除する</span></h3>
<p><strong>API Gateway → APIs → <code>CognitoSampleApi</code> を選択 → 「アクション」→「APIの削除」</strong></p>
<hr>
<h3><span id="toc34">2. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>CognitoApiFunction</code> を選択 → 「アクション」→「削除」</strong></p>
<hr>
<h3><span id="toc35">3. Cognito User Pool を削除する</span></h3>
<p><strong>Cognito → 作成した User Pool → 右上の「ユーザープールを削除」ボタン → ユーザープール名を入力 → 「削除」</strong></p>
<blockquote>
<p>ユーザーとアプリクライアントも一緒に削除されます。</p>
</blockquote>
<hr>
<h3><span id="toc36">4. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>CognitoApiFunction-role-XXXX</code> を検索して削除</strong></p>
<hr>
<h3><span id="toc37">5. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/CognitoApiFunction</code> → 削除</strong></p>
<hr>
<h2><span id="toc38">SAMとの対比</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AWS::Cognito::UserPool</code></td>
<td>Cognito → 「アプリケーションを作成」で User Pool を作成</td>
</tr>
<tr>
<td><code>AWS::Cognito::UserPoolClient</code>（シークレットなし）</td>
<td>② の手順で SPA タイプのクライアント <code>MyWebAppClient</code> を別途作成</td>
</tr>
<tr>
<td><code>Auth.DefaultAuthorizer: CognitoAuthorizer</code></td>
<td>API Gateway → オーソライザーを作成して /profile GET に適用</td>
</tr>
<tr>
<td><code>Auth: Authorizer: NONE</code>（/hello 側）</td>
<td>/hello GET には Authorizer を設定しない</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>API Gateway / Lambda / Cognito / IAM ロール / ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc39">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>initiate-auth</code> で <code>Client is configured with secret but SECRET_HASH was not received</code></td>
<td>① で自動作成された <code>MyWebApp</code>（シークレットあり）のクライアント ID を使っている</td>
<td>② の手順で <code>MyWebAppClient</code>（シークレットなし）を作成し、そちらの Client ID を使う</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>NotAuthorizedException</code></td>
<td>ユーザーが FORCE_CHANGE_PASSWORD 状態</td>
<td><code>admin-set-user-password --permanent</code> で CONFIRMED に変更する</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>InvalidParameterException</code></td>
<td><code>ALLOW_USER_PASSWORD_AUTH</code> が無効</td>
<td>User Pool Client の認証フロー設定を確認する</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 401</td>
<td><code>Bearer TOKEN</code> 形式で送っている</td>
<td><code>Bearer</code> を外し raw JWT（<code>eyJra...</code>）をそのまま Authorization ヘッダーに指定する</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>トークンが期限切れ（1時間で失効）</td>
<td><code>initiate-auth</code> で新しいトークンを取得し直す</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>AccessToken を使っている（IdToken ではない）</td>
<td><code>AuthenticationResult.IdToken</code> を使用しているか確認する</td>
</tr>
<tr>
<td>Lambda の <code>claims</code> が空</td>
<td><code>/profile GET</code> に Authorizer が設定されていない</td>
<td>④ 4-5 の手順で CognitoAuthorizer を設定し直す</td>
</tr>
<tr>
<td>Lambda の <code>resource</code> が <code>/</code> になる</td>
<td>Lambda プロキシ統合が有効になっていない</td>
<td>GET メソッドで「Lambda プロキシ統合の使用」をチェックする</td>
</tr>
<tr>
<td>Authorizer テストが 500 になる</td>
<td>User Pool が選択されていない、またはトークンのソースが空</td>
<td>オーソライザーの設定を確認し <code>Authorization</code> を入力し直す</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc40">まとめ</span></h2>
<p>今回のハンズオンで体験できたこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Cognito User Pool</strong></td>
<td>ユーザー作成・JWT 発行・パスワードポリシーを新UIで設定</td>
</tr>
<tr>
<td><strong>Cognito Authorizer</strong></td>
<td>API Gateway がIDトークンを自動検証 → Lambda は認証コード不要</td>
</tr>
<tr>
<td><strong>エンドポイント別認証制御</strong></td>
<td>/hello（認証なし）と /profile（認証必須）を同じ Lambda で分岐</td>
</tr>
<tr>
<td><strong>FORCE_CHANGE_PASSWORD 対処</strong></td>
<td><code>admin-set-user-password --permanent</code> で CONFIRMED 状態に変更</td>
</tr>
<tr>
<td><strong>新UI操作</strong></td>
<td>「アプリケーションを作成」→ SPA クライアントの追加作成 → Authorizer のトークンソース設定</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc41">コンソール版とSAM版を比較してみる</span></h2>
<p>コンソールでCognitoとAPI Gatewayの連携を理解したら、SAMで同じ構成をコードで定義することで「SAMが何を自動化しているか」が明確になります。<code>DefaultAuthorizer</code> によるワンライン認証設定や、<code>ALLOW_USER_PASSWORD_AUTH</code> の自動有効化など、コンソールでの手動操作がコードに対応しています。</p>
<p><!-- TODO: SAM版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc42">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/">AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでStep Functions + Lambdaワークフローを構築する手順【SAM版との比較付き / 新UI対応】</title>
		<link>https://caymezon.com/aws-handson-console-step-functions-lambda/</link>
					<comments>https://caymezon.com/aws-handson-console-step-functions-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 05:25:15 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[StepFunctions]]></category>
		<category><![CDATA[エラー処理]]></category>
		<category><![CDATA[ステートマシン]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[ワークフロー]]></category>
		<category><![CDATA[並列処理]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[新UI]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20229</guid>

					<description><![CDATA[<p>目次 はじめにStep Functions 新UIで戸惑いやすいポイント（先読み）キーワード解説前提条件使用するAWSサービス全体の作業順序① Lambda 関数を5つ作成する共通手順1-1. ValidateFunct [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-step-functions-lambda/">AWSコンソールだけでStep Functions + Lambdaワークフローを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-8" checked><label class="toc-title" for="toc-checkbox-8">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">Step Functions 新UIで戸惑いやすいポイント（先読み）</a></li><li><a href="#toc3" tabindex="0">キーワード解説</a></li><li><a href="#toc4" tabindex="0">前提条件</a></li><li><a href="#toc5" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc6" tabindex="0">全体の作業順序</a></li><li><a href="#toc7" tabindex="0">① Lambda 関数を5つ作成する</a><ol><li><a href="#toc8" tabindex="0">共通手順</a></li><li><a href="#toc9" tabindex="0">1-1. ValidateFunction（注文検証）</a></li><li><a href="#toc10" tabindex="0">1-2. InventoryFunction（在庫確認）</a></li><li><a href="#toc11" tabindex="0">1-3. PaymentFunction（支払い処理）</a></li><li><a href="#toc12" tabindex="0">1-4. ConfirmFunction（注文確定）</a></li><li><a href="#toc13" tabindex="0">1-5. ErrorHandlerFunction（エラー処理）</a></li></ol></li><li><a href="#toc14" tabindex="0">② Step Functions ステートマシンを作成する</a><ol><li><a href="#toc15" tabindex="0">2-1. 作成方法の選択（新UI：3択モーダル）</a></li><li><a href="#toc16" tabindex="0">2-2. 名前とタイプの設定（モーダル）</a></li><li><a href="#toc17" tabindex="0">2-3. ASL の入力（「{ } コード」タブ）</a></li><li><a href="#toc18" tabindex="0">2-4. 実行ロールの確認と作成（「設定」タブ）</a></li></ol></li><li><a href="#toc19" tabindex="0">③ 動作テスト</a><ol><li><a href="#toc20" tabindex="0">テスト1: 正常処理</a></li><li><a href="#toc21" tabindex="0">テスト2: 在庫切れエラー（Parallel Catch の確認）</a></li><li><a href="#toc22" tabindex="0">テスト3: 支払い失敗エラー（Parallel Catch の確認）</a></li><li><a href="#toc23" tabindex="0">テスト4: 検証エラー（ValidateOrder Retry + Catch の確認）</a></li></ol></li><li><a href="#toc24" tabindex="0">④ リソースの削除</a><ol><li><a href="#toc25" tabindex="0">1. ステートマシンを削除する</a></li><li><a href="#toc26" tabindex="0">2. Lambda 関数を5つ削除する</a></li><li><a href="#toc27" tabindex="0">3. IAM ロールを削除する（任意）</a></li><li><a href="#toc28" tabindex="0">4. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc29" tabindex="0">SAMとの対比</a></li><li><a href="#toc30" tabindex="0">トラブルシューティング</a></li><li><a href="#toc31" tabindex="0">まとめ</a></li><li><a href="#toc32" tabindex="0">コンソール版とSAM版を比較してみる</a></li><li><a href="#toc33" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「複数のLambda関数を順番に呼び出したい」「エラーが起きたとき自動でリトライして、それでも失敗したら別の処理に切り替えたい」という要件を、<strong>AWS Step Functions</strong> は視覚的なフロー定義で実現します。</p>
<p>この記事では、<strong>AWSコンソールのみ</strong>を使って、受注処理ワークフロー（注文検証 → 在庫確認・支払い並列処理 → 注文確定）をゼロから構築するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">入力: 注文データ（order_id / item_id / quantity）
  ↓
[ValidateOrder] 注文検証 ... Task + Retry + Catch
  ↓ 成功
[ProcessInParallel] 並列処理 ... Parallel + Catch
  ├─ [CheckInventory] 在庫確認
  └─ [ProcessPayment] 支払い処理
  ↓ 成功
[ConfirmOrder] 注文確定
  ↓
終了（成功）

[HandleError] エラー処理（Catch 先）
  ↓
終了（エラー通知済み）</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li>Step Functions の <strong>Task / Parallel / Retry / Catch</strong> という基本パターン</li>
<li>並列ブランチの結果をリストとして次のステートに渡す仕組み</li>
<li><strong>Workflow Studio（新UI）</strong> の操作方法 — ビジュアルエディタと ASL コードエディタの関係</li>
<li><code>ResultPath: &quot;$.error&quot;</code> でエラー情報を元の入力にマージして後続ステートに渡すテクニック</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="#">SAM版ハンズオン</a> の比較記事です。</strong><br />コンソール操作でStep Functionsの概念を視覚的に学び、SAMと何が違うのかを比較したい方向けです。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">Step Functions 新UIで戸惑いやすいポイント（先読み）</span></h2>
<p>操作を始める前に、<strong>2026年時点の新UI</strong>と旧UIの違いを把握しておきましょう。</p>
<table>
<thead>
<tr>
<th>変更点</th>
<th>旧UI</th>
<th>新UI（現在）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>作成モーダル</strong></td>
<td>「空白のステートマシン」テンプレートを選択</td>
<td><strong>3択モーダル</strong> が表示される</td>
</tr>
<tr>
<td><strong>作成選択肢</strong></td>
<td>テンプレートギャラリーのみ</td>
<td><strong>「自分で作成する」</strong>「Hello World を実行」「テンプレートを選択」の3択</td>
</tr>
<tr>
<td><strong>ASL入力の場所</strong></td>
<td>作成フォームに「コード」タブ</td>
<td><strong>Workflow Studio 内の「{ } コード」タブ</strong></td>
</tr>
<tr>
<td><strong>ロール設定タイミング</strong></td>
<td>ASL入力と同じ画面</td>
<td><strong>「設定」タブ</strong>で別途確認</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>最大のハマりポイント：</strong><br />「テンプレートを選択」を押してしまうと36個のテンプレートギャラリーが開きます。今回の目的には <strong>「自分で作成する」</strong> を選ぶ必要があります。これを知らずに迷う人が多いポイントです。</p>
</blockquote>
<hr>
<h2><span id="toc3">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>ステートマシン</strong></td>
<td>ワークフローの全体定義。状態（State）の集合と遷移ルールをもつ</td>
</tr>
<tr>
<td><strong>Task ステート</strong></td>
<td>Lambda などの外部リソースを呼び出す状態</td>
</tr>
<tr>
<td><strong>Parallel ステート</strong></td>
<td>複数のブランチを<strong>同時に実行</strong>する状態。両ブランチの結果がリストで次のステートに渡る</td>
</tr>
<tr>
<td><strong>Retry</strong></td>
<td>エラー発生時に同じステートを自動で<strong>再実行</strong>するルール</td>
</tr>
<tr>
<td><strong>Catch</strong></td>
<td>リトライ後もエラーが続く場合に<strong>別のステートへ遷移</strong>するルール</td>
</tr>
<tr>
<td><strong>ResultPath</strong></td>
<td>Catch 時にエラー情報をどのフィールドに格納するかの指定（<code>&quot;$.error&quot;</code> → 元の入力の <code>error</code> キーにマージ）</td>
</tr>
<tr>
<td><strong>ASL</strong></td>
<td>Amazon States Language。ステートマシン定義の JSON 形式</td>
</tr>
<tr>
<td><strong>Workflow Studio</strong></td>
<td>Step Functions のビジュアルエディタ。フロー図と ASL コードを双方向に編集できる</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">前提条件</span></h2>
<table>
<thead>
<tr>
<th>ツール</th>
<th>確認コマンド</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWSアカウント</td>
<td>—</td>
<td>IAMユーザーまたはルートユーザー</td>
</tr>
<tr>
<td>AWS CLI v2（任意）</td>
<td><code>aws --version</code></td>
<td>テスト実行を CLI で行う場合のみ必要</td>
</tr>
</tbody>
</table>
<p>今回はほぼコンソール操作のみで完結します。</p>
<hr>
<h2><span id="toc5">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Step Functions</strong></td>
<td>ワークフロー（ステートマシン）の管理・実行</td>
<td>月4,000回の状態遷移まで無料（標準タイプ）</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>各ステートで実行されるビジネスロジック</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda・Step Functionsの実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambdaの実行ログ</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① Lambda 関数を5つ作成する
      ↓（各関数の ARN が必要）
② Step Functions ステートマシンを作成する（新UI対応）
      ↓
③ 動作テスト（正常処理 / エラー処理）
      ↓
④ リソースの削除</code></pre>
<hr>
<h2><span id="toc7">① Lambda 関数を5つ作成する</span></h2>
<h3><span id="toc8">共通手順</span></h3>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>各関数でコードを貼り付けたあと、必ず <strong>「Deploy」</strong> ボタンを押してコードを保存します。</p>
<hr>
<h3><span id="toc9">1-1. ValidateFunction（注文検証）</span></h3>
<p><strong>関数名</strong>: <code>ValidateFunction</code></p>
<p>コードエディタで <code>lambda_function.py</code> を開き、既存の内容を全て置き換えて以下を貼り付ける。</p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    item_id = event.get("item_id")
    quantity = event.get("quantity", 0)

    if not order_id:
        raise ValueError("order_id が指定されていません")
    if not item_id:
        raise ValueError("item_id が指定されていません")
    if not isinstance(quantity, int) or quantity &lt;= 0:
        raise ValueError(f"quantity は正の整数である必要があります: {quantity}")

    result = {
        **event,          # 元の入力フィールドをすべて引き継ぐ（テスト用フラグを後続ステートに渡すため）
        "validated": True,
    }
    print(json.dumps({"step": "validate", **result}, ensure_ascii=False))
    return result</code></pre>
<p><strong>ARN を控えておく</strong>: 関数ページ右上の「関数の ARN」をコピー（例: <code>arn:aws:lambda:ap-northeast-1:123456789012:function:ValidateFunction</code>）</p>
<hr>
<h3><span id="toc10">1-2. InventoryFunction（在庫確認）</span></h3>
<p><strong>関数名</strong>: <code>InventoryFunction</code></p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    item_id = event.get("item_id")
    quantity = event.get("quantity", 1)

    if item_id == "item-999":
        raise ValueError(f"在庫不足: item_id={item_id}")

    result = {
        "order_id": order_id,
        "item_id": item_id,
        "quantity": quantity,
        "stock_available": True,
    }
    print(json.dumps({"step": "inventory", **result}, ensure_ascii=False))
    return result</code></pre>
<p><strong>ARN を控えておく</strong></p>
<hr>
<h3><span id="toc11">1-3. PaymentFunction（支払い処理）</span></h3>
<p><strong>関数名</strong>: <code>PaymentFunction</code></p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    quantity = event.get("quantity", 1)

    # エラーテスト用: fail_payment=True の場合は例外発生
    if event.get("fail_payment"):
        raise RuntimeError(f"支払い処理に失敗: order_id={order_id}")

    amount = quantity * 1000  # 1個 1,000円

    result = {
        "order_id": order_id,
        "amount": amount,
        "payment_status": "completed",
    }
    print(json.dumps({"step": "payment", **result}, ensure_ascii=False))
    return result</code></pre>
<p><strong>ARN を控えておく</strong></p>
<hr>
<h3><span id="toc12">1-4. ConfirmFunction（注文確定）</span></h3>
<p><strong>関数名</strong>: <code>ConfirmFunction</code></p>
<pre><code class="language-python">import json
import datetime


def lambda_handler(event, context):
    # Parallel ステートの後に呼ばれるため、event はリスト形式
    #   event[0]: CheckInventory（在庫確認）の結果
    #   event[1]: ProcessPayment（支払い処理）の結果
    inventory_result = event[0]
    payment_result = event[1]

    order_id = inventory_result.get("order_id")
    now = datetime.datetime.now(datetime.timezone.utc)

    result = {
        "order_id": order_id,
        "item_id": inventory_result.get("item_id"),
        "quantity": inventory_result.get("quantity"),
        "amount": payment_result.get("amount"),
        "confirmed_at": now.isoformat(),
        "status": "confirmed",
    }
    print(json.dumps({"step": "confirm", **result}, ensure_ascii=False))
    return result</code></pre>
<p><strong>ARN を控えておく</strong></p>
<blockquote>
<p><strong>Parallel ステート後の <code>event</code> がリストになる理由：</strong><br /><code>ProcessInParallel</code> の各ブランチの出力が配列でまとめられて次のステートに渡されます。<code>event[0]</code> が在庫確認の結果、<code>event[1]</code> が支払い処理の結果です。この仕様を知らないと <code>list indices must be integers</code> エラーで詰まります。</p>
</blockquote>
<hr>
<h3><span id="toc13">1-5. ErrorHandlerFunction（エラー処理）</span></h3>
<p><strong>関数名</strong>: <code>ErrorHandlerFunction</code></p>
<pre><code class="language-python">import json


def lambda_handler(event, context):
    # ResultPath: "$.error" により、エラー情報が元の入力に付加されて渡される
    error_info = event.get("error", {})
    original_input = {k: v for k, v in event.items() if k != "error"}

    result = {
        "status": "error",
        "error_type": error_info.get("Error", "Unknown"),
        "error_cause": error_info.get("Cause", ""),
        "original_input": original_input,
    }
    print(json.dumps({"step": "error_handler", **result}, ensure_ascii=False))
    return result</code></pre>
<p><strong>ARN を控えておく</strong></p>
<hr>
<h2><span id="toc14">② Step Functions ステートマシンを作成する</span></h2>
<p><strong>AWSコンソール → Step Functions → 「ステートマシンを作成」</strong></p>
<h3><span id="toc15">2-1. 作成方法の選択（新UI：3択モーダル）</span></h3>
<p>「ステートマシンを作成」ボタンを押すと <strong>3択のモーダル</strong> が表示されます。</p>
<p><img decoding="async" src="https://caymezon.com/wp-content/uploads/2026/03/aws-handson-console-step-functions-lambda-stepfunctions-creat-modal-f49940.jpg" alt="Step Functions 作成モーダル（新UI）"></p>
<table>
<thead>
<tr>
<th>選択肢</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hello World を実行</td>
<td>ガイド付きチュートリアル（今回は使わない）</td>
</tr>
<tr>
<td>テンプレートを選択</td>
<td>36個のテンプレートギャラリーが開く（今回は使わない）</td>
</tr>
<tr>
<td><strong>自分で作成する</strong></td>
<td>ゼロからワークフローを作成する ← <strong>これを選ぶ</strong></td>
</tr>
</tbody>
</table>
<p><strong>「自分で作成する」</strong> をクリックします。</p>
<blockquote>
<p><strong>「テンプレートを選択」を押してしまった場合：</strong><br />テンプレートギャラリーが開きます。左上の「✕」で閉じて、改めてモーダルから「自分で作成する」を選んでください。</p>
</blockquote>
<hr>
<h3><span id="toc16">2-2. 名前とタイプの設定（モーダル）</span></h3>
<p>「自分で作成する」をクリックすると Workflow Studio が開き、同時に設定モーダルが表示されます。</p>
<p><!-- ![Step Functions 名前・タイプ設定モーダル](images/stepfunctions-name-type-modal.jpg) --></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ステートマシン名</td>
<td><code>OrderWorkflow</code></td>
</tr>
<tr>
<td>ステートマシンのタイプ</td>
<td><strong>標準</strong></td>
</tr>
</tbody>
</table>
<p>「続行」をクリックするとモーダルが閉じ、Workflow Studio の編集画面に切り替わります。</p>
<blockquote>
<p><strong>標準（Standard）と Express の違い：</strong><br />標準タイプは「正確に1回実行」「最大1年の実行時間」「実行履歴をコンソールで確認可能」が特徴です。受注処理のような確実な実行が必要なユースケースに適しています。</p>
</blockquote>
<hr>
<h3><span id="toc17">2-3. ASL の入力（「{ } コード」タブ）</span></h3>
<p>Workflow Studio の画面上部にある <strong>「{ } コード」</strong> タブをクリックしてコードエディタを表示します。</p>
<p><!-- ![Workflow Studio コードタブ](images/stepfunctions-workflow-studio-code.jpg) --></p>
<p>既存の内容を<strong>全て削除</strong>し、以下の JSON を貼り付けます。</p>
<blockquote>
<p><strong>【重要】</strong> <code>REPLACE_WITH_ARN_ValidateFunction</code> などのプレースホルダーを、① で控えた実際の Lambda ARN に置き換えること。</p>
</blockquote>
<pre><code class="language-json">{
  "Comment": "受注処理ワークフロー（検証 → 並列処理 → 確定）",
  "StartAt": "ValidateOrder",
  "States": {
    "ValidateOrder": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ValidateFunction",
      "Next": "ProcessInParallel",
      "Retry": [
        {
          "ErrorEquals": ["States.ALL"],
          "IntervalSeconds": 2,
          "MaxAttempts": 1,
          "BackoffRate": 2.0
        }
      ],
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "Next": "HandleError",
          "ResultPath": "$.error"
        }
      ]
    },
    "ProcessInParallel": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "CheckInventory",
          "States": {
            "CheckInventory": {
              "Type": "Task",
              "Resource": "REPLACE_WITH_ARN_InventoryFunction",
              "End": true
            }
          }
        },
        {
          "StartAt": "ProcessPayment",
          "States": {
            "ProcessPayment": {
              "Type": "Task",
              "Resource": "REPLACE_WITH_ARN_PaymentFunction",
              "End": true
            }
          }
        }
      ],
      "Next": "ConfirmOrder",
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "Next": "HandleError",
          "ResultPath": "$.error"
        }
      ]
    },
    "ConfirmOrder": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ConfirmFunction",
      "End": true
    },
    "HandleError": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ErrorHandlerFunction",
      "End": true
    }
  }
}</code></pre>
<p>貼り付けると <strong>「フロー」タブ</strong> に切り替えると、フロー図が自動生成されます。ASL を正しく記述できているかを視覚的に確認できます。</p>
<p><!-- ![Workflow Studio フロー図プレビュー](images/stepfunctions-workflow-preview.jpg) --></p>
<hr>
<h3><span id="toc18">2-4. 実行ロールの確認と作成（「設定」タブ）</span></h3>
<p>画面上部の <strong>「設定」</strong> タブをクリックして実行ロールを確認します。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>実行ロール</td>
<td><strong>「新しいロールを作成」</strong>（デフォルトのまま）</td>
</tr>
<tr>
<td>ログ記録</td>
<td>OFF（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「新しいロールを作成」を選ぶと、以下のような青いボックスが表示されます。</p>
<blockquote>
<p>実行ロールは、完全な許可で作成されます。<code>StepFunctions-OrderWorkflow-role-XXXX</code> という名前の新しい実行ロールが作成されます。ステートマシンで指定されたアクションに必要なすべての許可が自動生成されます。</p>
</blockquote>
<p>「自動生成された許可を確認」を展開すると <code>lambda:Invoke</code> が含まれていることを確認できます。</p>
<p>右上の <strong>「作成」</strong> ボタンをクリックします。</p>
<blockquote>
<p><strong>IAMロールの自動作成について：</strong><br />ASL 定義に記述した Lambda ARN に対して <code>lambda:Invoke</code> 権限を持つロールが自動的に作成されます。SAM版では <code>LambdaInvokePolicy</code> ポリシーでこれを明示的に定義しています。</p>
</blockquote>
<hr>
<h2><span id="toc19">③ 動作テスト</span></h2>
<p><strong>Step Functions → <code>OrderWorkflow</code> → 「実行を開始」</strong></p>
<h3><span id="toc20">テスト1: 正常処理</span></h3>
<p><strong>入力データ:</strong></p>
<pre><code class="language-json">{
  "order_id": "ORD-001",
  "item_id": "item-001",
  "quantity": 2
}</code></pre>
<p>「実行を開始」をクリックします。</p>
<p><strong>実行グラフで確認:</strong></p>
<ul>
<li>全ステートが<strong>緑色</strong>になることを確認する</li>
<li><code>ProcessInParallel</code> の2つのブランチが<strong>同時に緑</strong>になることを確認する（並列処理の視覚化）</li>
</ul>
<p><!-- ![正常処理の実行グラフ](images/stepfunctions-success-graph.jpg) --></p>
<p><strong>出力を確認:</strong></p>
<p>実行完了後、「出力」タブで以下のような JSON が表示されます。</p>
<pre><code class="language-json">{
  "order_id": "ORD-001",
  "item_id": "item-001",
  "quantity": 2,
  "amount": 2000,
  "confirmed_at": "2026-03-01T10:00:00.000000+00:00",
  "status": "confirmed"
}</code></pre>
<hr>
<h3><span id="toc21">テスト2: 在庫切れエラー（Parallel Catch の確認）</span></h3>
<p><strong>入力データ:</strong></p>
<pre><code class="language-json">{
  "order_id": "ORD-002",
  "item_id": "item-999",
  "quantity": 1
}</code></pre>
<p><strong>期待する動作:</strong></p>
<ol>
<li><code>ValidateOrder</code> → 成功</li>
<li><code>ProcessInParallel</code> → <code>CheckInventory</code> が <code>ValueError</code> を発生させる</li>
<li><code>ProcessInParallel</code> の Catch が動作 → <code>HandleError</code> へ遷移</li>
<li><code>HandleError</code> → 成功（エラー情報をログに記録して終了）</li>
</ol>
<p><strong>実行グラフで確認:</strong></p>
<ul>
<li><code>CheckInventory</code> が<strong>赤く</strong>なる</li>
<li><code>ProcessInParallel</code> から <code>HandleError</code> へ遷移するパスが強調される</li>
</ul>
<p><!-- ![在庫切れエラーの実行グラフ](images/stepfunctions-inventory-error.jpg) --></p>
<p><strong>出力を確認:</strong></p>
<pre><code class="language-json">{
  "status": "error",
  "error_type": "ValueError",
  "error_cause": "在庫不足: item_id=item-999",
  "original_input": {
    "order_id": "ORD-002",
    "item_id": "item-999",
    "quantity": 1,
    "validated": true
  }
}</code></pre>
<hr>
<h3><span id="toc22">テスト3: 支払い失敗エラー（Parallel Catch の確認）</span></h3>
<p><strong>入力データ:</strong></p>
<pre><code class="language-json">{
  "order_id": "ORD-003",
  "item_id": "item-001",
  "quantity": 2,
  "fail_payment": true
}</code></pre>
<p><strong>期待する動作:</strong></p>
<ol>
<li><code>ValidateOrder</code> → 成功</li>
<li><code>ProcessInParallel</code> → <code>ProcessPayment</code> が <code>RuntimeError</code> を発生させる</li>
<li><code>ProcessInParallel</code> の Catch が動作 → <code>HandleError</code> へ遷移</li>
</ol>
<hr>
<h3><span id="toc23">テスト4: 検証エラー（ValidateOrder Retry + Catch の確認）</span></h3>
<p><strong>入力データ（<code>order_id</code> を省略）:</strong></p>
<pre><code class="language-json">{
  "item_id": "item-001",
  "quantity": 2
}</code></pre>
<p><strong>期待する動作:</strong></p>
<ol>
<li><code>ValidateOrder</code> → <code>ValueError</code> 発生</li>
<li>Retry: <code>IntervalSeconds: 2</code> で2秒後に自動リトライ（合計2回試行）</li>
<li>2回とも失敗 → Catch が動作 → <code>HandleError</code> へ遷移</li>
</ol>
<p><strong>Retry の確認方法:</strong></p>
<p>実行グラフで <code>ValidateOrder</code> を選択 → <strong>「イベント」タブ</strong> で以下の順序を確認します：</p>
<pre><code class="language-plaintext">TaskStateEntered → TaskScheduled → TaskStarted → TaskFailed
  → TaskScheduled（リトライ1回目）→ TaskStarted → TaskFailed
  → TaskStateExited（Catch 発動）→ HandleError へ</code></pre>
<p><code>ValidateFunction</code> が合計2回呼ばれていることが分かります。</p>
<hr>
<h2><span id="toc24">④ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<h3><span id="toc25">1. ステートマシンを削除する</span></h3>
<p><strong>Step Functions → <code>OrderWorkflow</code> → 「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<p>削除後、ステータスが「<strong>削除中</strong>」に変わります。以下のようなメッセージが表示されます：</p>
<blockquote>
<p>ステートマシンに削除のマークが付けられました。すべての実行が停止されると削除されます。</p>
</blockquote>
<p>これは正常な動作です。実行中のワークフローがすべて終了するまで完全削除を待つ仕様のため、実行中のものがなければ数秒〜数十秒でリストから消えます。ページをリロードして確認します。</p>
<hr>
<h3><span id="toc26">2. Lambda 関数を5つ削除する</span></h3>
<p><strong>Lambda → 関数一覧 → 各関数を選択 → 「アクション」→「削除」</strong></p>
<p>削除対象:</p>
<ul>
<li><code>ValidateFunction</code></li>
<li><code>InventoryFunction</code></li>
<li><code>PaymentFunction</code></li>
<li><code>ConfirmFunction</code></li>
<li><code>ErrorHandlerFunction</code></li>
</ul>
<hr>
<h3><span id="toc27">3. IAM ロールを削除する（任意）</span></h3>
<p>Step Functions の実行ロール（<code>StepFunctions-OrderWorkflow-role-XXXX</code>）と、Lambda 関数のロール（<code>ValidateFunction-role-XXXX</code> など5つ）を削除します。</p>
<p><strong>IAM → ロール → 各ロールを検索して削除</strong></p>
<hr>
<h3><span id="toc28">4. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → 各 Lambda の <code>/aws/lambda/関数名</code> を削除</strong></p>
<hr>
<h2><span id="toc29">SAMとの対比</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AWS::Serverless::StateMachine</code></td>
<td>Step Functions → ステートマシンを作成</td>
</tr>
<tr>
<td><code>Type: STANDARD</code></td>
<td>タイプ = 「標準」</td>
</tr>
<tr>
<td><code>Definition: {...}</code></td>
<td>「{ } コード」タブに ASL JSON を貼り付け</td>
</tr>
<tr>
<td><code>DefinitionSubstitutions</code></td>
<td>JSON 内の ARN プレースホルダーを手動で置換</td>
</tr>
<tr>
<td><code>LambdaInvokePolicy</code> × 5</td>
<td>「設定」タブ → 「新しいロールを作成」で自動生成</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>Lambda × 5 / ステートマシン / IAM ロール / ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc30">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>実行が即座に <code>ExecutionFailed</code> になる</td>
<td>ASL 内の Lambda ARN が間違っている</td>
<td>① で控えた ARN と再照合する</td>
</tr>
<tr>
<td>「テンプレートを選択」を押してギャラリーが開いた</td>
<td>新UI操作ミス</td>
<td>✕で閉じ、モーダルから「自分で作成する」を選ぶ</td>
</tr>
<tr>
<td>「{ } コード」タブが見つからない</td>
<td>モーダルが前面に出ている</td>
<td>「続行」でモーダルを閉じてから Workflow Studio を操作する</td>
</tr>
<tr>
<td><code>HandleError</code> に渡る <code>error_cause</code> が空</td>
<td>Python 例外が Lambda レベルでハンドルされている</td>
<td>コードの <code>raise</code> が正しく記述されているか確認</td>
</tr>
<tr>
<td><code>ProcessInParallel</code> が一方しか実行されない</td>
<td>Parallel ブランチの定義ミス</td>
<td>ASL JSON の <code>Branches</code> 配列に2つの要素があるか確認</td>
</tr>
<tr>
<td><code>ConfirmFunction</code> でエラー: <code>list indices must be integers</code></td>
<td><code>event[0]</code> / <code>event[1]</code> で取り出しているが、入力が配列でない</td>
<td><code>ProcessInParallel</code> の直後にのみ呼ばれる関数かを確認する</td>
</tr>
<tr>
<td>ステートマシン削除後「削除中」のまま消えない</td>
<td>実行中のワークフローが残っている</td>
<td>実行一覧から実行中のものを停止してから再確認</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc31">まとめ</span></h2>
<p>今回のハンズオンで体験できたこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Task + Retry + Catch</strong></td>
<td>ValidateOrder で注文検証 → リトライ → それでも失敗したらエラーハンドラへ</td>
</tr>
<tr>
<td><strong>Parallel ステート</strong></td>
<td>在庫確認と支払い処理を同時実行し、両結果をリストで次へ渡す</td>
</tr>
<tr>
<td><strong>ResultPath</strong></td>
<td><code>&quot;$.error&quot;</code> でエラー情報を元の入力にマージ → エラーハンドラで参照</td>
</tr>
<tr>
<td><strong>Workflow Studio</strong></td>
<td>ASL コードと視覚フロー図を双方向で確認できる新UI</td>
</tr>
<tr>
<td><strong>新UI操作</strong></td>
<td>3択モーダル → 「自分で作成する」→「{ } コード」タブ → 「設定」タブ の流れ</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc32">コンソール版とSAM版を比較してみる</span></h2>
<p>コンソールでStep Functionsの概念を理解したら、SAMで同じ構成をコードで定義することで「SAMが何を自動化しているか」が明確になります。<code>DefinitionSubstitutions</code> による ARN の自動差し込みや、<code>LambdaInvokePolicy</code> によるワンライン権限付与など、コンソールでの手動操作がコードに対応しています。</p>
<p><!-- TODO: SAM版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc33">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-step-functions-lambda/">AWSコンソールだけでStep Functions + Lambdaワークフローを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-step-functions-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでS3 + CloudFront静的サイトホスティングを構築する手順【SAM版との比較付き / 新UI対応】</title>
		<link>https://caymezon.com/aws-handson-console-s3-cloudfront-hosting/</link>
					<comments>https://caymezon.com/aws-handson-console-s3-cloudfront-hosting/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 07:34:52 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[CDN]]></category>
		<category><![CDATA[CloudFront]]></category>
		<category><![CDATA[OAC]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[新UI]]></category>
		<category><![CDATA[静的サイトホスティング]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20210</guid>

					<description><![CDATA[<p>目次 はじめにCloudFront 新UI で戸惑いやすいポイント（先読み）SAM vs コンソール：どれだけ違うか構築するもの全体の作業順序① S3 バケット作成② CloudFront ディストリビューション作成（新 [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-s3-cloudfront-hosting/">AWSコンソールだけでS3 + CloudFront静的サイトホスティングを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-10" checked><label class="toc-title" for="toc-checkbox-10">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">CloudFront 新UI で戸惑いやすいポイント（先読み）</a></li><li><a href="#toc3" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc4" tabindex="0">構築するもの</a></li><li><a href="#toc5" tabindex="0">全体の作業順序</a></li><li><a href="#toc6" tabindex="0">① S3 バケット作成</a></li><li><a href="#toc7" tabindex="0">② CloudFront ディストリビューション作成（新UI・6ステップウィザード）</a><ol><li><a href="#toc8" tabindex="0">ステップ1: Choose a plan（プランを選択）</a></li><li><a href="#toc9" tabindex="0">ステップ2: Get started（基本設定）</a></li><li><a href="#toc10" tabindex="0">ステップ3: Specify origin（オリジンの指定）</a></li><li><a href="#toc11" tabindex="0">ステップ4: Enable security（セキュリティ設定）</a></li><li><a href="#toc12" tabindex="0">ステップ5: Review and create（確認と作成）</a></li></ol></li><li><a href="#toc13" tabindex="0">③ S3 バケットポリシーの確認</a></li><li><a href="#toc14" tabindex="0">④ HTML ファイルをアップロード</a><ol><li><a href="#toc15" tabindex="0">index.html（トップページ）</a></li><li><a href="#toc16" tabindex="0">error.html（カスタム404ページ）</a></li><li><a href="#toc17" tabindex="0">方法A: S3 コンソールからアップロード</a></li><li><a href="#toc18" tabindex="0">方法B: AWS CLI でアップロード</a></li></ol></li><li><a href="#toc19" tabindex="0">⑤ CloudFront URL でアクセス確認</a></li><li><a href="#toc20" tabindex="0">⑥ キャッシュの動作確認（任意）</a><ol><li><a href="#toc21" tabindex="0">6-1. index.html を更新してアップロード</a></li><li><a href="#toc22" tabindex="0">6-2. キャッシュを削除する（新UI: 「キャッシュ削除」タブ）</a></li></ol></li><li><a href="#toc23" tabindex="0">⑦ リソースの削除</a><ol><li><a href="#toc24" tabindex="0">1. CloudFront ディストリビューションを無効化する</a></li><li><a href="#toc25" tabindex="0">2. Pricing plan（プライシングプラン）をキャンセルする</a></li><li><a href="#toc26" tabindex="0">3. 月末を待ってから削除する</a></li><li><a href="#toc27" tabindex="0">4. S3 バケット内のファイルをすべて削除する</a></li><li><a href="#toc28" tabindex="0">5. S3 バケットを削除する</a></li><li><a href="#toc29" tabindex="0">6. CloudFront OAC を削除する（任意）</a></li></ol></li><li><a href="#toc30" tabindex="0">SAMとの対比まとめ</a></li><li><a href="#toc31" tabindex="0">トラブルシューティング</a></li><li><a href="#toc32" tabindex="0">まとめ</a><ol><li><a href="#toc33" tabindex="0">コンソール操作で確認できたこと</a></li><li><a href="#toc34" tabindex="0">どちらを使うべきか</a></li></ol></li><li><a href="#toc35" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>この記事は、<a href="https://caymezon.com/aws-handson-s3-cloudfront-hosting/">SAM版ハンズオン記事</a>の比較版です。</p>
<p>SAM版ではコマンド数本でS3・OAC・CloudFront・バケットポリシーが一括デプロイできましたが、<strong>実際にコンソールで操作してみると思わぬハマりポイント</strong>がいくつかあります。</p>
<p>特に <strong>CloudFront コンソールは 2026年に大きくUIが刷新</strong> され、6ステップのウィザード形式に変わりました。ネット上の古い手順書と画面が全く違って戸惑う人が多いはずです。この記事では <strong>2026年の新UI</strong> に対応した手順を詳しく解説します。</p>
<p><strong>この記事を読むとわかること：</strong></p>
<ul>
<li>CloudFront 新UI（6ステップウィザード）の各ステップで何を設定するか</li>
<li>「Allow private S3 bucket access to CloudFront」チェックボックスで何が自動化されるのか</li>
<li><strong>削除時に新登場した「Pricing plan キャンセル」手順</strong>（これを知らないと削除できない）</li>
<li>キャッシュ削除（旧: 「無効化」）の操作と注意点</li>
</ul>
<hr>
<h2><span id="toc2">CloudFront 新UI で戸惑いやすいポイント（先読み）</span></h2>
<p>操作を始める前に、旧UIとの違いを把握しておきましょう。</p>
<table>
<thead>
<tr>
<th>変更点</th>
<th>旧UI</th>
<th>新UI（2026年〜）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>ウィザード形式</strong></td>
<td>長い1画面に全設定を入力</td>
<td><strong>6ステップのウィザード</strong>に分割</td>
</tr>
<tr>
<td><strong>プランの選択</strong></td>
<td>なし</td>
<td><strong>ステップ1でプランを選択</strong>（無料 / 有料）</td>
</tr>
<tr>
<td><strong>OAC の設定</strong></td>
<td>手動でOACを作成 → ARNをコピー → 貼り付け</td>
<td><strong>「Allow private S3 bucket access」チェック1つ</strong>で自動設定</td>
</tr>
<tr>
<td><strong>「無効化」タブ</strong></td>
<td>Invalidation（無効化）</td>
<td>**「キャッシュ削除」**に名称変更</td>
</tr>
<tr>
<td><strong>削除手順</strong></td>
<td>無効化 → 削除</td>
<td>無効化 → <strong>Pricing plan キャンセル</strong> → 月末待機 → 削除</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>「Pricing plan キャンセル」が最大のハマりポイント：</strong><br />新UIで作成したディストリビューションは「Pricing plan（プライシングプラン）」に加入しています。<br />削除する前にプランをキャンセルする操作が必要で、しかもキャンセルは<strong>月末（翌月1日）に有効</strong>になるため、<strong>すぐに削除できません</strong>。<br />知らないと「subscribed to a pricing plan」エラーで詰まります（後述）。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc3">SAM vs コンソール：どれだけ違うか</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動・新UI）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>OACの設定</strong></td>
<td><code>Type: AWS::CloudFront::OriginAccessControl</code> + 自動ポリシー</td>
<td>ステップ3のチェックボックス1つ</td>
</tr>
<tr>
<td><strong>バケットポリシー更新</strong></td>
<td><code>WebsiteBucketPolicy</code> で自動生成</td>
<td>チェックボックスで自動（ただし確認が必要）</td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td><code>sam delete</code> 1コマンド（即時）</td>
<td><strong>無効化 → プランキャンセル → 月末待機 → 削除</strong></td>
</tr>
<tr>
<td><strong>コスト管理</strong></td>
<td>Pricing planなし</td>
<td><strong>Pricing planのキャンセルが必要</strong></td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">構築するもの</span></h2>
<p>SAM版と全く同じ構成・機能の静的サイトホスティング環境を構築します。</p>
<pre><code class="language-plaintext">ブラウザ
  ↓ HTTPS（HTTPは自動リダイレクト）
CloudFront（CDN・エッジキャッシュ）
  ↓ OAC（署名付きリクエスト）
S3 バケット（非公開・パブリックアクセスブロック）
  └── index.html / error.html</code></pre>
<hr>
<h2><span id="toc5">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① S3 バケット作成（非公開）
      ↓
② CloudFront ディストリビューション作成（6ステップウィザード）
      ↓（自動でOAC設定・バケットポリシー更新）
③ S3 バケットポリシーの確認（自動設定を確認）
      ↓
④ HTML ファイルをアップロード
      ↓
⑤ CloudFront URL でアクセス確認
      ↓
⑥ キャッシュの動作確認（任意）
⑦ リソースの削除（要注意: 月末まで待機が必要）</code></pre>
<blockquote>
<p><strong>順序の理由：</strong><br />② でCloudFrontディストリビューションを作成する際に「どのS3バケットをオリジンにするか」を指定するため、① でバケットを先に作成しておく必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc6">① S3 バケット作成</span></h2>
<p><strong>AWSコンソール → S3 → 「バケットを作成」</strong></p>
<p><!-- ![S3 バケット作成画面](images/s3-create-bucket.jpg) --></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>バケット名</td>
<td><code>my-cloudfront-website</code>（任意・グローバルで一意な名前）</td>
</tr>
<tr>
<td>AWSリージョン</td>
<td><strong>アジアパシフィック（東京）ap-northeast-1</strong></td>
</tr>
<tr>
<td>オブジェクト所有者</td>
<td>ACL 無効（デフォルトのまま）</td>
</tr>
<tr>
<td>パブリックアクセスのブロック</td>
<td><strong>すべてブロック</strong>（変更しない）</td>
</tr>
<tr>
<td>バージョニング</td>
<td>無効（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「バケットを作成」をクリックします。</p>
<blockquote>
<p><strong>パブリックアクセスをブロックしたまま使う理由：</strong><br />従来の静的サイトホスティングではS3バケットを公開する方法もありましたが、現在の推奨は <strong>S3を非公開にしてCloudFront OAC経由でのみアクセスさせる</strong>構成です。直接S3 URLからのアクセスを防ぎ、CloudFrontのHTTPS・キャッシュ・WAFの恩恵を受けられます。</p>
</blockquote>
<blockquote>
<p><strong>バケット名のルール：</strong></p>
<ul>
<li>グローバルで一意（AWS全体で重複不可・削除後しばらく再利用不可）</li>
<li><code>my-cloudfront-website-自分のAWSアカウントID</code> のように末尾にアカウントIDを付けると一意にしやすい</li>
<li>SAMでは <code>!Sub &quot;${AWS::StackName}-website-${AWS::AccountId}&quot;</code> で自動的に一意化しています</li>
</ul>
</blockquote>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>バケット名（例: <code>my-cloudfront-website</code>）</li>
</ul>
<hr>
<h2><span id="toc7">② CloudFront ディストリビューション作成（新UI・6ステップウィザード）</span></h2>
<p><strong>AWSコンソール → CloudFront → 「ディストリビューションを作成」</strong></p>
<blockquote>
<p><strong>CloudFrontはグローバルサービスのため、コンソール右上のリージョン表示は「グローバル」になります。</strong><br />S3バケットのリージョンは東京（ap-northeast-1）のままで問題ありません。</p>
</blockquote>
<hr>
<h3><span id="toc8">ステップ1: Choose a plan（プランを選択）</span></h3>
<p><!-- ![CloudFront プラン選択画面（新UI）](images/cloudfront-plan-select.jpg) --></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>プラン</td>
<td><strong>無料（$0/month）</strong></td>
</tr>
</tbody>
</table>
<p>「Next」をクリックします。</p>
<blockquote>
<p><strong>無料プランの内容（1ヶ月あたり）：</strong></p>
<ul>
<li>リクエスト数: 100万（1M）</li>
<li>データ転送: 100GB</li>
<li>DDoS保護・グローバルCDN・デフォルトキャッシュルールが含まれる</li>
</ul>
<p>ハンズオン目的では無料枠で十分です。有料プランは本番サービスで大量トラフィックが想定される場合に選択します。</p>
<p><strong>SAMとの差分：</strong> SAM（CloudFormation）で作成したディストリビューションにはPricing planの概念がありません。「月額$0」のプランでも加入状態になるため、削除時にキャンセル手続きが必要になります（後述）。</p>
</blockquote>
<hr>
<h3><span id="toc9">ステップ2: Get started（基本設定）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Distribution name</td>
<td><code>my-cloudfront-site</code>（任意）</td>
</tr>
<tr>
<td>Distribution type</td>
<td><strong>Single website or app</strong></td>
</tr>
<tr>
<td>Route 53 managed domain</td>
<td>空欄（カスタムドメインなし）</td>
</tr>
</tbody>
</table>
<p>「Next」をクリックします。</p>
<hr>
<h3><span id="toc10">ステップ3: Specify origin（オリジンの指定）</span></h3>
<p>このステップが最も重要です。S3バケットをオリジンとして設定し、OACを自動構成します。</p>
<p><!-- ![CloudFront オリジン設定画面（新UI）](images/cloudfront-origin-setting.jpg) --></p>
<p><strong>Origin type セクション：</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Origin type</td>
<td><strong>Amazon S3</strong> を選択</td>
</tr>
</tbody>
</table>
<p><strong>Origin セクション：</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>S3 origin</td>
<td>① で作成したバケット名を入力または「Browse S3」で選択</td>
</tr>
<tr>
<td>Origin path</td>
<td>空欄（変更不要）</td>
</tr>
</tbody>
</table>
<p><strong>Settings セクション：</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Allow private S3 bucket access to CloudFront</td>
<td><strong>チェックを入れる（Recommended）</strong></td>
</tr>
<tr>
<td>オリジン設定</td>
<td>Use recommended origin settings（デフォルトのまま）</td>
</tr>
<tr>
<td>Cache settings</td>
<td>Use recommended cache settings tailored to serving S3 content（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「Next」をクリックします。</p>
<blockquote>
<p><strong>「Allow private S3 bucket access to CloudFront」チェックボックスの重要性：</strong></p>
<p>これが新UIの最大の改善点です。チェックを入れると：</p>
<ol>
<li>CloudFrontが S3 に安全にアクセスするための <strong>OAC（Origin Access Control）を自動作成</strong></li>
<li>ディストリビューション作成後に <strong>S3バケットポリシーを自動で更新</strong></li>
</ol>
<p><strong>旧UIでの手順（参考）：</strong></p>
<ol>
<li>CloudFront → OAC を手動で作成</li>
<li>ディストリビューション作成時にOACを選択・ARNをコピー</li>
<li>S3 → バケットポリシーを手動で編集・貼り付け</li>
</ol>
<p>新UIではこのすべてがチェック1つで完結します。</p>
<p><strong>SAMとの差分：</strong> SAMでは <code>Type: AWS::CloudFront::OriginAccessControl</code> リソースと <code>WebsiteBucketPolicy</code> リソースで同じことを明示的に定義しています。</p>
</blockquote>
<hr>
<h3><span id="toc11">ステップ4: Enable security（セキュリティ設定）</span></h3>
<p>「Security protections from WAF are included in your plan at no additional charge.」と表示されます。無料プランにWAF保護が含まれており、追加料金は発生しません。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Use monitor mode</td>
<td><strong>チェックしない</strong>（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「Next」をクリックします。</p>
<blockquote>
<p><strong>「Use monitor mode」について：</strong><br />チェックを入れると「何がブロックされるかを記録するだけ」のモードになります（実際にはブロックしない）。ハンズオンでは不要なのでチェックせずに進みます。</p>
</blockquote>
<hr>
<h3><span id="toc12">ステップ5: Review and create（確認と作成）</span></h3>
<p>設定内容を確認して「ディストリビューションを作成」をクリックします。</p>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>CloudFront ドメイン名（例: <code>xxxxxxxxxxxx.cloudfront.net</code>）</li>
<li>ディストリビューション ID（例: <code>EXXXXXXXXXXXXXXXXX</code>）</li>
</ul>
<blockquote>
<p><strong>CloudFrontのデプロイには 5〜15分かかります。</strong><br />ステータスが「有効」になるまで待ってから次のステップに進んでください。</p>
</blockquote>
<hr>
<h2><span id="toc13">③ S3 バケットポリシーの確認</span></h2>
<p>新UIでは、ステップ3で「Allow private S3 bucket access to CloudFront」にチェックを入れると、ディストリビューション作成時に <strong>S3バケットポリシーが自動で更新されます</strong>。</p>
<p>自動設定されたポリシーを確認します。</p>
<p><strong>S3 → <code>my-cloudfront-website</code> → 「アクセス許可」タブ → 「バケットポリシー」</strong></p>
<p><!-- ![S3 バケットポリシー確認画面](images/s3-bucket-policy.jpg) --></p>
<p>以下のようなポリシーが自動で設定されていることを確認します。</p>
<pre><code class="language-json">{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-cloudfront-website/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EXXXXXXXXXXXXXXXXX"
                }
            }
        }
    ]
}</code></pre>
<p><strong>このポリシーのポイント：</strong></p>
<ul>
<li><code>Principal.Service: cloudfront.amazonaws.com</code> — CloudFrontサービスからのアクセスのみ許可</li>
<li><code>Condition.AWS:SourceArn</code> — <strong>特定のディストリビューション</strong>からのアクセスのみ許可（他のCloudFrontからはアクセスできない）</li>
<li><code>Action: s3:GetObject</code> のみ — 読み取り専用。書き込み・削除は不可</li>
</ul>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMでは <code>WebsiteBucketPolicy</code> リソースに上記と同じポリシーを明示的に記述しています。コンソールでは自動設定されますが、SAMを読むとその中身が可視化されます。</p>
</blockquote>
<hr>
<h2><span id="toc14">④ HTML ファイルをアップロード</span></h2>
<p>アップロードするHTMLファイルの内容を確認しておきます。自分で用意したHTMLがあればそちらを使っても構いません。</p>
<h3><span id="toc15">index.html（トップページ）</span></h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="ja"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;S3 + CloudFront ハンズオン&lt;/title&gt;
  &lt;style&gt;
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      max-width: 640px;
      margin: 60px auto;
      padding: 20px;
      color: #333;
    }
    h1 { color: #232f3e; }
    .badge {
      background: #ff9900;
      color: white;
      padding: 3px 10px;
      border-radius: 4px;
      font-size: 0.85em;
      font-weight: bold;
    }
    .info {
      background: #f4f6f8;
      border-left: 4px solid #ff9900;
      padding: 12px 16px;
      margin: 20px 0;
      border-radius: 0 4px 4px 0;
    }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;デプロイ成功！&lt;/h1&gt;
  &lt;p&gt;
    &lt;span class="badge"&gt;CloudFront CDN&lt;/span&gt; 経由でこのページが配信されています。
  &lt;/p&gt;
  &lt;div class="info"&gt;
    &lt;strong&gt;このページの配信構成:&lt;/strong&gt;&lt;br&gt;
    S3 バケット（オリジン） → CloudFront（CDN）→ あなたのブラウザ
  &lt;/div&gt;
  &lt;p&gt;S3 + CloudFront による静的サイトホスティングのハンズオンです。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3><span id="toc16">error.html（カスタム404ページ）</span></h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="ja"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;title&gt;404 - ページが見つかりません&lt;/title&gt;
  &lt;style&gt;
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      max-width: 640px;
      margin: 60px auto;
      padding: 20px;
      color: #333;
      text-align: center;
    }
    h1 { color: #cc0000; }
    a { color: #ff9900; }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;404 - ページが見つかりません&lt;/h1&gt;
  &lt;p&gt;お探しのページは存在しないか、移動・削除された可能性があります。&lt;/p&gt;
  &lt;p&gt;&lt;a href="/"&gt;トップページへ戻る&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>上記2ファイルをS3にアップロードします。</p>
<h3><span id="toc17">方法A: S3 コンソールからアップロード</span></h3>
<p><strong>S3 → <code>my-cloudfront-website</code> → 「アップロード」</strong></p>
<p><code>index.html</code> と <code>error.html</code> を選択してアップロードします。</p>
<h3><span id="toc18">方法B: AWS CLI でアップロード</span></h3>
<pre><code class="language-cmd">aws s3 sync C:\my-aws\aws-learning-projects\s3-cloudfront-hosting\website\ ^
  s3://my-cloudfront-website/ ^
  --region ap-northeast-1</code></pre>
<hr>
<h2><span id="toc19">⑤ CloudFront URL でアクセス確認</span></h2>
<p>CloudFrontのステータスが「有効」になったらブラウザでアクセスします。</p>
<pre><code class="language-plaintext">https://xxxxxxxxxxxx.cloudfront.net</code></pre>
<p><strong>期待する表示:</strong> <code>index.html</code> の内容が表示される。</p>
<p><strong>HTTP → HTTPS リダイレクトの確認：</strong></p>
<pre><code class="language-plaintext">http://xxxxxxxxxxxx.cloudfront.net</code></pre>
<p>HTTPでアクセスすると自動的にHTTPSにリダイレクトされることを確認します。</p>
<p><strong>カスタム404ページの確認：</strong></p>
<pre><code class="language-plaintext">https://xxxxxxxxxxxx.cloudfront.net/notfound</code></pre>
<p>存在しないページにアクセスすると <code>error.html</code> の内容が表示されることを確認します。</p>
<p><!-- ![CloudFront経由でindex.htmlが表示](images/cloudfront-index.jpg) --></p>
<hr>
<h2><span id="toc20">⑥ キャッシュの動作確認（任意）</span></h2>
<p>CloudFront CDNの重要な概念「キャッシュ」と「キャッシュ削除（旧: 無効化）」を体験します。</p>
<h3><span id="toc21">6-1. index.html を更新してアップロード</span></h3>
<p><code>index.html</code> のテキストを変更して再度アップロードします。</p>
<pre><code class="language-cmd">aws s3 cp C:\my-aws\aws-learning-projects\s3-cloudfront-hosting\website\index.html ^
  s3://my-cloudfront-website/index.html ^
  --region ap-northeast-1</code></pre>
<p>ブラウザでCloudFront URLにアクセスしても<strong>古いキャッシュが表示される場合があります</strong>（TTLが切れるまで）。</p>
<h3><span id="toc22">6-2. キャッシュを削除する（新UI: 「キャッシュ削除」タブ）</span></h3>
<p><strong>CloudFront → ディストリビューション → 「キャッシュ削除」タブ → 「キャッシュ削除を作成」</strong></p>
<p><!-- ![CloudFront キャッシュ削除画面（新UI）](images/cloudfront-cache-invalidation.jpg) --></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>オブジェクトパス</td>
<td><code>/*</code>（全キャッシュを削除）または <code>/index.html</code>（特定ファイルのみ）</td>
</tr>
</tbody>
</table>
<p>「キャッシュ削除を作成」をクリックします。ステータスが「完了」になったら（1〜3分）ブラウザを強制リロード（<code>Ctrl+Shift+R</code>）して確認します。</p>
<blockquote>
<p><strong>旧UIとの名称変更：</strong><br />旧UIでは「無効化（Invalidation）」タブでしたが、新UIでは「キャッシュ削除」に名称変更されました。機能は同じです。</p>
</blockquote>
<blockquote>
<p><strong>無効化の料金：</strong><br />毎月最初の1,000パスは無料。それ以降は $0.005/パス。<br /><code>/*</code> は1パスとしてカウントされるため、ハンズオン程度なら無料枠内です。</p>
</blockquote>
<hr>
<h2><span id="toc23">⑦ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<blockquote>
<p><strong>重要: 新UIで作成したディストリビューションの削除手順（旧UIとは異なります）</strong></p>
<p>旧UIでは「無効化 → 削除」の2ステップでしたが、新UIでは以下の手順が必要です：<br /><strong>無効化 → Pricing plan キャンセル → 月末（翌月1日）まで待機 → 削除</strong></p>
<p>月末まで削除できないのは想定外でハマる人が多いポイントです。</p>
</blockquote>
<hr>
<h3><span id="toc24">1. CloudFront ディストリビューションを無効化する</span></h3>
<p><strong>CloudFront → ディストリビューション → 対象を選択 → 「無効化」ボタン → 確認 → 「無効化」</strong></p>
<p>ステータスが「有効」→「無効」に変わるまで待ちます（5〜15分）。</p>
<blockquote>
<p><strong>無効化が完了しないとディストリビューションを削除できません。</strong>（削除ボタンがグレーアウトしたまま）</p>
</blockquote>
<hr>
<h3><span id="toc25">2. Pricing plan（プライシングプラン）をキャンセルする</span></h3>
<p>ステータスが「無効」になったら、プランをキャンセルします。</p>
<p><strong>無効化したディストリビューションをクリック → 「Billing」セクション → 「Manage plan」→「Cancel plan」（プランをキャンセル）→「Cancel plan」ボタン</strong></p>
<p><!-- ![CloudFront Pricing plan キャンセル画面](images/cloudfront-cancel-plan.jpg) --></p>
<p>キャンセルが受け付けられると「無料プランのキャンセルがスケジュールされています。このプランは [月末日] に終了します。」と表示されます。</p>
<blockquote>
<p><strong>「この日を過ぎると、すべての使用は従量制料金で課金されます」という警告について：</strong><br />これは「もし使い続けた場合」の説明です。ディストリビューションは「無効」状態のためリクエストを受け付けず、使用量ゼロ = 課金ゼロです。無効化済みであれば課金されません。</p>
</blockquote>
<hr>
<h3><span id="toc26">3. 月末を待ってから削除する</span></h3>
<p>プランキャンセルは<strong>月末（翌月1日）に有効</strong>になります。それまでディストリビューションは削除できません。</p>
<p>月末以降：</p>
<p><strong>ディストリビューションを選択 → 「削除」→ 確認 → 「削除」</strong></p>
<blockquote>
<p><strong>キャンセル前に削除しようとすると：</strong><br /><code>You can&#39;t delete this distribution while it&#39;s subscribed to a pricing plan.</code><br />というエラーが表示されます。その場合は手順2のプランキャンセルを行ってください。</p>
</blockquote>
<hr>
<h3><span id="toc27">4. S3 バケット内のファイルをすべて削除する</span></h3>
<p><strong>方法A: AWS CLI で一括削除（推奨）</strong></p>
<pre><code class="language-cmd">aws s3 rm s3://my-cloudfront-website --recursive --region ap-northeast-1</code></pre>
<p><strong>方法B: S3 コンソールから</strong></p>
<p>S3 → <code>my-cloudfront-website</code> → ファイルをすべて選択 → 「削除」→ 確認テキストを入力 → 「オブジェクトを削除」</p>
<hr>
<h3><span id="toc28">5. S3 バケットを削除する</span></h3>
<p><strong>S3 → <code>my-cloudfront-website</code> を選択 → 「削除」→ バケット名を入力 → 「バケットを削除」</strong></p>
<hr>
<h3><span id="toc29">6. CloudFront OAC を削除する（任意）</span></h3>
<p>ステップ3で自動作成された OAC は、ディストリビューション削除後も残ります。不要なら手動で削除します。</p>
<p><strong>CloudFront → 左サイドバー「オリジンアクセスコントロール」→ 作成した OAC を選択 → 「削除」</strong></p>
<blockquote>
<p><strong>注意：</strong> ディストリビューションの「オリジン」タブではなく、左サイドバーの「オリジンアクセスコントロール」から削除します。ディストリビューションが削除済みでないと削除できません。</p>
</blockquote>
<hr>
<h2><span id="toc30">SAMとの対比まとめ</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Type: AWS::S3::Bucket</code>（パブリックアクセスブロック自動）</td>
<td>① S3バケット作成（すべてブロックのまま）</td>
</tr>
<tr>
<td><code>Type: AWS::CloudFront::OriginAccessControl</code></td>
<td>ステップ3 「Allow private S3 bucket access」チェックで自動作成</td>
</tr>
<tr>
<td><code>Type: AWS::CloudFront::Distribution</code></td>
<td>② CloudFront 新UIウィザード（6ステップ）</td>
</tr>
<tr>
<td><code>WebsiteBucketPolicy</code>（ポリシー自動生成）</td>
<td>ステップ3のチェックでディストリビューション作成時に自動更新</td>
</tr>
<tr>
<td><code>sam delete</code>（即時削除可能）</td>
<td><strong>無効化 → Pricing planキャンセル → 月末待機 → 削除</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>削除の大きな違い：</strong><br />コンソール新UIで作成したディストリビューションはPricing planに加入するため、プランキャンセル後に月末まで削除できない制約があります。<br /><strong>SAMで作成したディストリビューションにはPricing planの概念がないため、<code>sam delete</code> で即座に削除手続きが完了します。</strong><br />これがSAM版の大きなメリットのひとつです。</p>
</blockquote>
<hr>
<h2><span id="toc31">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>CloudFront URL で 403 が返る</td>
<td>バケットポリシーが未設定</td>
<td>③ の手順でバケットポリシーを確認する</td>
</tr>
<tr>
<td>CloudFront URL で 403 が返る</td>
<td>CloudFrontのデプロイがまだ完了していない</td>
<td>ステータスが「有効」になるまで5〜15分待つ</td>
</tr>
<tr>
<td>S3の直接URLにアクセスすると 403</td>
<td>正常（パブリックアクセスをブロックしているため）</td>
<td>CloudFront URL でアクセスする</td>
</tr>
<tr>
<td>index.htmlを更新したのに古い内容が表示される</td>
<td>CloudFrontキャッシュが残っている</td>
<td>⑥ の手順でキャッシュを削除する</td>
</tr>
<tr>
<td>ディストリビューションを削除できない（削除ボタンがグレー）</td>
<td>ステータスが「有効」のまま</td>
<td>「無効化」してステータスが「無効」になるまで待つ</td>
</tr>
<tr>
<td>「subscribed to a pricing plan」エラーが出て削除できない</td>
<td>Pricing planのキャンセル操作が必要</td>
<td>手順2でプランをキャンセルし、月末以降に削除する</td>
</tr>
<tr>
<td>プランキャンセル後も削除できない</td>
<td>キャンセルは月末（翌月1日）まで有効にならない</td>
<td>月末以降に削除する。無効化済みなら課金されない</td>
</tr>
<tr>
<td>OAC 削除時エラー</td>
<td>ディストリビューションの「オリジン」タブを操作しようとしている</td>
<td>左サイドバー「オリジンアクセスコントロール」から削除する</td>
</tr>
<tr>
<td>バケット削除がエラーになる</td>
<td>バケット内にオブジェクトが残っている</td>
<td><code>aws s3 rm s3://バケット名 --recursive</code> で先に空にする</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc32">まとめ</span></h2>
<h3><span id="toc33">コンソール操作で確認できたこと</span></h3>
<p>今回のコンソール操作で、SAMが自動化していることと、新UI特有のハマりポイントが明確になりました：</p>
<table>
<thead>
<tr>
<th>項目</th>
<th>コンソール操作で学べたこと</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>OAC の正体</strong></td>
<td>「CloudFrontからS3へのAWS署名付きリクエストを有効にする」という設定。新UIでチェック1つで完結</td>
</tr>
<tr>
<td><strong>バケットポリシーの役割</strong></td>
<td>OAC設定後に自動生成されるポリシーで「このCloudFrontだけが読める」を実現している</td>
</tr>
<tr>
<td><strong>Pricing plan の存在</strong></td>
<td>新UIならではの概念。月末まで削除できないのは意図的な仕様</td>
</tr>
<tr>
<td><strong>キャッシュ削除（Invalidation）</strong></td>
<td>ファイル更新後にエッジキャッシュを手動でリフレッシュする必要がある</td>
</tr>
</tbody>
</table>
<h3><span id="toc34">どちらを使うべきか</span></h3>
<table>
<thead>
<tr>
<th>シーン</th>
<th>推奨</th>
</tr>
</thead>
<tbody>
<tr>
<td>本番環境・チーム開発</td>
<td><strong>SAM</strong>（再現性・Git管理・削除の容易さ）</td>
</tr>
<tr>
<td>AWSを初めて学ぶ</td>
<td><strong>コンソール</strong>（OAC・バケットポリシーの意味を視覚的に理解する）</td>
</tr>
<tr>
<td>構築済みリソースの確認・デバッグ</td>
<td><strong>コンソール</strong>（キャッシュ削除・バケットポリシー確認）</td>
</tr>
<tr>
<td>すぐにリソースを削除したい</td>
<td><strong>SAM</strong>（Pricing planなし・<code>sam delete</code> 即時）</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc35">関連記事</span></h2>
<ul>
<li>SAM版ハンズオン — コマンド数本でS3 + CloudFront環境を構築</li>
</ul>

<a rel="noopener" href="https://caymezon.com/aws-handson-s3-cloudfront-hosting/" title="AWSハンズオン - S3 + CloudFrontで静的サイトをCDN配信しよう【SAM版 / Windows対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-cloudfront-hosting-featured-5ba466-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-cloudfront-hosting-featured-5ba466-160x90.jpg 160w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-cloudfront-hosting-featured-5ba466-120x68.jpg 120w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-cloudfront-hosting-featured-5ba466-320x180.jpg 320w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-cloudfront-hosting-featured-5ba466-376x212.jpg 376w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AWSハンズオン - S3 + CloudFrontで静的サイトをCDN配信しよう【SAM版 / Windows対応】</div><div class="blogcard-snippet internal-blogcard-snippet">はじめに「ウェブサイトを公開したいけど、サーバーは持ちたくない」「静的なHTMLサイトを世界中から速く見せたい」という要件に、S3 + CloudFront の組み合わせはベストな選択肢のひとつです。この記事では、AWS SAM（Serve...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://caymezon.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">caymezon.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.02.23</div></div></div></div></a>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-s3-cloudfront-hosting/">AWSコンソールだけでS3 + CloudFront静的サイトホスティングを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-s3-cloudfront-hosting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでS3 + Lambdaファイルアップロードトリガーを構築する手順【SAM版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-s3-event-lambda/</link>
					<comments>https://caymezon.com/aws-handson-console-s3-event-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 04:16:15 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[S3イベント]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[ファイルアップロード]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[非同期処理]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20204</guid>

					<description><![CDATA[<p>目次 はじめにSAM vs コンソール：どれだけ違うか構築するもの全体の作業順序① S3 バケット作成1-1. バケットの設定② Lambda 関数作成2-1. 基本設定2-2. コードの入力③ S3 トリガーを Lam [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-s3-event-lambda/">AWSコンソールだけでS3 + Lambdaファイルアップロードトリガーを構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-12" checked><label class="toc-title" for="toc-checkbox-12">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">構築するもの</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① S3 バケット作成</a><ol><li><a href="#toc6" tabindex="0">1-1. バケットの設定</a></li></ol></li><li><a href="#toc7" tabindex="0">② Lambda 関数作成</a><ol><li><a href="#toc8" tabindex="0">2-1. 基本設定</a></li><li><a href="#toc9" tabindex="0">2-2. コードの入力</a></li></ol></li><li><a href="#toc10" tabindex="0">③ S3 トリガーを Lambda に追加</a></li><li><a href="#toc11" tabindex="0">④ 動作テスト</a><ol><li><a href="#toc12" tabindex="0">4-1. テスト用ファイルの準備</a></li><li><a href="#toc13" tabindex="0">4-2. ファイルのアップロード</a></li><li><a href="#toc14" tabindex="0">4-3. CloudWatch Logs でログを確認</a></li><li><a href="#toc15" tabindex="0">4-4. 日本語ファイル名のテスト（任意）</a></li></ol></li><li><a href="#toc16" tabindex="0">⑤ リソースの削除</a><ol><li><a href="#toc17" tabindex="0">1. S3 バケット内のオブジェクトをすべて削除する</a></li><li><a href="#toc18" tabindex="0">2. S3 バケットを削除する</a></li><li><a href="#toc19" tabindex="0">3. Lambda 関数を削除する</a></li><li><a href="#toc20" tabindex="0">4. IAM ロールを削除する（任意）</a></li><li><a href="#toc21" tabindex="0">5. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc22" tabindex="0">SAMとの対比まとめ</a></li><li><a href="#toc23" tabindex="0">トラブルシューティング</a></li><li><a href="#toc24" tabindex="0">まとめ</a><ol><li><a href="#toc25" tabindex="0">コンソール操作で確認できたこと</a></li><li><a href="#toc26" tabindex="0">どちらを使うべきか</a></li></ol></li><li><a href="#toc27" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>この記事は、<a href="https://caymezon.com/aws-handson-s3-event-lambda/">SAM版ハンズオン記事</a>の比較版です。</p>
<p>SAM版ではコマンド数本でS3バケット・Lambda・イベント通知設定が完了しましたが、<strong>「SAMが裏で何をやっているのか？」「バケット名のグローバルユニーク問題はどう解決する？」「再帰呼び出しの警告って何？」</strong> といった疑問を実際のコンソール操作を通じて体験できるのがこの記事です。</p>
<p><strong>この記事を読むとわかること：</strong></p>
<ul>
<li>S3・Lambda を個別に設定する順序と依存関係</li>
<li>SAMの <code>!Sub &quot;${AWS::StackName}-upload-${AWS::AccountId}&quot;</code> が解決していること（バケット名のグローバルユニーク問題）</li>
<li>「再帰呼び出し」警告の意味と、今回は無視してよい理由</li>
<li>S3バケット削除時に「先に空にする」が必要な理由</li>
</ul>
<hr>
<h2><span id="toc2">SAM vs コンソール：どれだけ違うか</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>バケット名の一意性確保</strong></td>
<td><code>!Sub &quot;...-${AWS::AccountId}&quot;</code> で自動</td>
<td><strong>手動でグローバルユニークな名前を考える</strong></td>
</tr>
<tr>
<td><strong>S3イベント通知設定</strong></td>
<td><code>Type: S3</code> の1行</td>
<td><strong>Lambda → トリガーを追加（画面操作）</strong></td>
</tr>
<tr>
<td><strong>リソースベースポリシー</strong></td>
<td>自動追加</td>
<td><strong>トリガー追加時に自動追加（画面の警告を確認する必要あり）</strong></td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td>バケットを空にしてから <code>sam delete</code></td>
<td><strong>S3オブジェクト削除 → バケット削除 → Lambda削除 × 個別操作</strong></td>
</tr>
</tbody>
</table>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc3">構築するもの</span></h2>
<p>SAM版と全く同じ構成・機能のファイルアップロードトリガー環境を構築します。</p>
<pre><code class="language-plaintext">ファイルアップロード（コンソール / AWS CLI）
  ↓ S3 ObjectCreated イベント発火
S3 バケット（my-s3-event-upload）
  ↓ Lambda を呼び出し
Lambda（S3EventFunction / Python 3.12）
  ↓ ファイル情報（バケット名・ファイル名・サイズ）をログ出力
CloudWatch Logs</code></pre>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① S3 バケット作成
      ↓
② Lambda 関数作成（コード入力）
      ↓
③ S3 トリガーを Lambda に追加（リソースベースポリシーも自動設定）
      ↓
④ ファイルアップロードして動作テスト
⑤ リソースの削除（S3を先に空にする）</code></pre>
<blockquote>
<p><strong>順序の理由：</strong><br />③でS3トリガーを追加する際に「どのバケットを対象にするか」を選択するため、①でバケットを先に作成しておく必要があります。SQSハンズオンのようにARNのコピーが必要な場面はありませんが、バケットが存在しないとトリガー設定画面で選択できません。</p>
</blockquote>
<hr>
<h2><span id="toc5">① S3 バケット作成</span></h2>
<p><strong>AWSコンソール → S3 → 「バケットを作成」</strong></p>
<p><!-- ![S3 バケット作成画面](images/s3-create-bucket.jpg) --></p>
<h3><span id="toc6">1-1. バケットの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>バケット名</td>
<td><code>my-s3-event-upload</code>（任意。グローバルで一意な名前）</td>
</tr>
<tr>
<td>AWSリージョン</td>
<td><strong>アジアパシフィック（東京）ap-northeast-1</strong></td>
</tr>
<tr>
<td>オブジェクト所有者</td>
<td>ACL 無効（デフォルトのまま）</td>
</tr>
<tr>
<td>パブリックアクセスのブロック</td>
<td>すべてブロック（デフォルトのまま）</td>
</tr>
<tr>
<td>バージョニング</td>
<td>無効（デフォルトのまま）</td>
</tr>
<tr>
<td>暗号化</td>
<td>Amazon S3 マネージドキー（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「バケットを作成」をクリックします。</p>
<blockquote>
<p><strong>バケット名のルール（SAMとの違いが出るポイント）：</strong></p>
<p>S3のバケット名はAWS全体（全リージョン・全アカウント）でグローバルユニークである必要があります。</p>
<ul>
<li>小文字・数字・ハイフンのみ使用可（大文字・アンダースコアは使えない）</li>
<li><code>my-s3-event-upload</code> だと他のユーザーがすでに使っている可能性がある</li>
</ul>
<p><strong>一意にする推奨の方法：</strong></p>
<ul>
<li><code>my-s3-event-upload-自分のAWSアカウントID</code>（最も確実）</li>
<li><code>my-s3-event-upload-20260222</code>（日付を付ける）</li>
</ul>
<p>SAMでは <code>!Sub &quot;${AWS::StackName}-upload-${AWS::AccountId}&quot;</code> で自動的にアカウントIDを付加しています。コンソールではこのルールを頭の中で考えて手動入力する必要があります。</p>
</blockquote>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>バケット名（例: <code>my-s3-event-upload</code>）</li>
</ul>
<hr>
<h2><span id="toc7">② Lambda 関数作成</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<h3><span id="toc8">2-1. 基本設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>S3EventFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリックします。</p>
<blockquote>
<p><strong>実行ロールについて：</strong><br />今回の Lambda はS3イベントのメタデータ（バケット名・ファイル名・サイズ）を受け取るだけで、S3からファイルの<strong>中身を読み取る処理は行いません</strong>。<br />そのため、基本実行ロール（CloudWatch Logs への書き込み権限のみ）で動作します。<br />ファイルの中身を読み取りたい場合は、実行ロールに <code>s3:GetObject</code> 権限を追加する必要があります。</p>
</blockquote>
<h3><span id="toc9">2-2. コードの入力</span></h3>
<p>関数ページ → 「コード」タブ → コードエディタで <code>lambda_function.py</code> を開きます。</p>
<p>既存の内容を<strong>全て</strong>置き換えて以下を貼り付けます。</p>
<pre><code class="language-python">import json
import urllib.parse


def lambda_handler(event, context):
    results = []

    for record in event["Records"]:          # 複数ファイル同時アップロードに対応
        bucket = record["s3"]["bucket"]["name"]
        # キー名は URL エンコードされているためデコードが必要（日本語・スペース対応）
        key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
        size = record["s3"]["object"]["size"]
        event_name = record["eventName"]     # 例: "ObjectCreated:Put"
        event_time = record["eventTime"]     # 例: "2026-02-22T10:00:00.000Z"

        info = {
            "eventName": event_name,
            "bucket": bucket,
            "key": key,
            "sizeBytes": size,
            "eventTime": event_time,
        }

        print(json.dumps(info, ensure_ascii=False))
        results.append(info)

    print(json.dumps({"processedCount": len(results)}, ensure_ascii=False))
    return {"processedCount": len(results)}</code></pre>
<p>「Deploy」ボタンをクリックしてコードを保存します。</p>
<hr>
<h2><span id="toc10">③ S3 トリガーを Lambda に追加</span></h2>
<p>Lambdaコンソールからトリガーを追加する方法と、S3コンソールからイベント通知を設定する方法の2つがありますが、ここではLambdaコンソールから行います。</p>
<p><strong>Lambda → <code>S3EventFunction</code> → 「設定」タブ → 「トリガー」→「トリガーを追加」</strong></p>
<p><!-- ![Lambda S3トリガー追加画面](images/lambda-s3-trigger-add.jpg) --></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ソース</td>
<td><strong>S3</strong></td>
</tr>
<tr>
<td>バケット</td>
<td>① で作成したバケット（例: <code>my-s3-event-upload</code>）</td>
</tr>
<tr>
<td>イベントタイプ</td>
<td><strong>すべてのオブジェクト作成イベント</strong></td>
</tr>
<tr>
<td>プレフィックス</td>
<td>空欄（全フォルダが対象）</td>
</tr>
<tr>
<td>サフィックス</td>
<td>空欄（全ファイルタイプが対象）</td>
</tr>
<tr>
<td>再帰呼び出し</td>
<td>「このトリガーを確認しました」にチェック</td>
</tr>
</tbody>
</table>
<p>「追加」をクリックします。</p>
<blockquote>
<p><strong>「再帰呼び出し」の警告とは：</strong></p>
<p>S3バケットへのアップロードをトリガーに<strong>同じバケットへ書き込む Lambda</strong> を設定すると、無限ループが発生します。例えば「画像をアップロード → Lambdaがリサイズして同じバケットに保存 → それがまたトリガーになる → …」というパターンです。</p>
<p>今回の Lambda はS3への書き込みを行わず、ログを出力するだけなので問題ありません。「このトリガーを確認しました」にチェックして続行してください。</p>
<p><strong>SAMとの差分：</strong> SAMの <code>Type: S3</code> イベントでも同じ構成になっています。SAMは警告なしに設定されますが、同じリスクが存在します。</p>
</blockquote>
<blockquote>
<p><strong>自動設定されること：</strong><br />Lambdaのリソースベースポリシーに「S3からの呼び出しを許可するポリシー」が自動追加されます。<br />S3がLambdaを呼び出すためのIAM設定を手動で行う必要はありません。</p>
</blockquote>
<hr>
<h2><span id="toc11">④ 動作テスト</span></h2>
<h3><span id="toc12">4-1. テスト用ファイルの準備</span></h3>
<pre><code class="language-cmd">echo テストファイルです &gt; C:\test.txt</code></pre>
<h3><span id="toc13">4-2. ファイルのアップロード</span></h3>
<p><strong>方法A: S3 コンソールからアップロード</strong></p>
<p>S3 → <code>my-s3-event-upload</code> → 「アップロード」→「ファイルを追加」→ <code>test.txt</code> を選択 → 「アップロード」</p>
<p><strong>方法B: AWS CLI でアップロード</strong></p>
<pre><code class="language-cmd">aws s3 cp C:\test.txt s3://my-s3-event-upload/test.txt --region ap-northeast-1</code></pre>
<h3><span id="toc14">4-3. CloudWatch Logs でログを確認</span></h3>
<p>Lambda → <code>S3EventFunction</code> → 「モニタリング」タブ → 「CloudWatch Logs を表示」→ 最新のログストリームを開きます。</p>
<p><!-- ![CloudWatch Logsのログ確認](images/cloudwatch-logs-output.jpg) --></p>
<p><strong>期待するログ出力：</strong></p>
<pre><code class="language-json">{"eventName": "ObjectCreated:Put", "bucket": "my-s3-event-upload", "key": "test.txt", "sizeBytes": 28, "eventTime": "2026-02-22T10:00:00.000Z"}
{"processedCount": 1}</code></pre>
<p><strong>確認ポイント：</strong></p>
<ul>
<li><code>&quot;eventName&quot;: &quot;ObjectCreated:Put&quot;</code> — S3の Put（アップロード）が検知されている</li>
<li><code>&quot;key&quot;: &quot;test.txt&quot;</code> — アップロードしたファイル名が正しく取得されている</li>
<li><code>&quot;sizeBytes&quot;</code> — ファイルサイズが記録されている</li>
</ul>
<h3><span id="toc15">4-4. 日本語ファイル名のテスト（任意）</span></h3>
<pre><code class="language-cmd">echo 日本語テスト &gt; "C:\テスト.txt"
aws s3 cp "C:\テスト.txt" "s3://my-s3-event-upload/テスト.txt" --region ap-northeast-1</code></pre>
<p>ログで <code>&quot;key&quot;: &quot;テスト.txt&quot;</code> と正しくデコードされていることを確認します。</p>
<hr>
<h2><span id="toc16">⑤ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<blockquote>
<p><strong>S3バケット削除の重要な注意点：</strong><br /><strong>オブジェクトが残っているバケットは削除できません。</strong><br />先にバケット内のファイルをすべて削除してからバケットを削除してください。</p>
<p>SAMの <code>sam delete</code> でも同じ理由から「先にバケットを空にする」手順が必要です。この仕様はSAMを使っても変わりません。</p>
</blockquote>
<h3><span id="toc17">1. S3 バケット内のオブジェクトをすべて削除する</span></h3>
<p><strong>方法A: S3 コンソールから</strong></p>
<p>S3 → <code>my-s3-event-upload</code> → ファイルをすべて選択 → 「削除」→ 確認テキストを入力 → 「オブジェクトを削除」</p>
<p><strong>方法B: AWS CLI で一括削除（推奨）</strong></p>
<pre><code class="language-cmd">aws s3 rm s3://my-s3-event-upload --recursive --region ap-northeast-1</code></pre>
<h3><span id="toc18">2. S3 バケットを削除する</span></h3>
<p><strong>S3 → <code>my-s3-event-upload</code> を選択 → 「削除」→ バケット名を入力 → 「バケットを削除」</strong></p>
<h3><span id="toc19">3. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>S3EventFunction</code> を選択 → 「アクション」→「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<h3><span id="toc20">4. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>S3EventFunction-role-XXXX</code> を選択 → 「削除」→ ロール名を入力 → 「削除」</strong></p>
<p>Lambda を削除してもIAMロールはそのまま残ります。不要なら手動で削除します。</p>
<h3><span id="toc21">5. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/S3EventFunction</code> → 「アクション」→「ロググループの削除」</strong></p>
<hr>
<h2><span id="toc22">SAMとの対比まとめ</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Type: AWS::S3::Bucket</code></td>
<td>S3 → バケットを作成</td>
</tr>
<tr>
<td><code>!Sub &quot;${AWS::StackName}-upload-${AWS::AccountId}&quot;</code></td>
<td>手動でグローバルユニークなバケット名を考えて入力</td>
</tr>
<tr>
<td><code>Type: S3</code> イベント / <code>Events: s3:ObjectCreated:*</code></td>
<td>Lambda → トリガーを追加（S3・全オブジェクト作成イベント）</td>
</tr>
<tr>
<td>リソースベースポリシー（自動）</td>
<td>トリガー追加時に自動設定（「再帰呼び出し」警告にチェック）</td>
</tr>
<tr>
<td><code>DeletionPolicy: Delete</code></td>
<td>手動でバケットを空にしてからバケット削除</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>S3バケット・Lambda・IAMロール・ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc23">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>ファイルをアップロードしてもLambdaが起動しない</td>
<td>S3トリガーが設定されていない</td>
<td>③ の手順でトリガーを追加する</td>
</tr>
<tr>
<td>ログに <code>&quot;key&quot;</code> が <code>%XX%XX...</code> と表示される</td>
<td>URLデコードされていない</td>
<td><code>urllib.parse.unquote_plus(key)</code> でデコードしているか確認</td>
</tr>
<tr>
<td>バケット削除がエラーになる</td>
<td>バケット内にオブジェクトが残っている</td>
<td><code>aws s3 rm s3://バケット名 --recursive</code> で先に空にする</td>
</tr>
<tr>
<td>Lambda が 500 エラー</td>
<td>コードの構文エラーなど</td>
<td>CloudWatch Logs でエラー内容を確認</td>
</tr>
<tr>
<td>トリガー追加時に「再帰呼び出し」の警告が出る</td>
<td>同バケットへの書き込みトリガーへの注意</td>
<td>今回のLambdaはS3に書き込まないためチェックを入れて続行</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc24">まとめ</span></h2>
<h3><span id="toc25">コンソール操作で確認できたこと</span></h3>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソール操作で理解できたこと</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>!Sub &quot;...-${AWS::AccountId}&quot;</code></td>
<td>バケット名のグローバルユニーク問題を手動で解決する必要がある</td>
</tr>
<tr>
<td><code>Type: S3</code> イベント（自動）</td>
<td>トリガー追加画面で「再帰呼び出し警告」の意味を確認できる</td>
</tr>
<tr>
<td><code>DeletionPolicy: Delete</code></td>
<td>S3は「先に空にしてから削除」が必須ルール（SAMでも同じ）</td>
</tr>
</tbody>
</table>
<h3><span id="toc26">どちらを使うべきか</span></h3>
<table>
<thead>
<tr>
<th>シーン</th>
<th>推奨</th>
</tr>
</thead>
<tbody>
<tr>
<td>本番環境・チーム開発</td>
<td><strong>SAM</strong>（バケット名の管理・再現性・速度）</td>
</tr>
<tr>
<td>AWSを初めて学ぶ</td>
<td><strong>コンソール</strong>（各設定の意味を理解する）</td>
</tr>
<tr>
<td>構築済みリソースの確認・デバッグ</td>
<td><strong>コンソール</strong>（S3のオブジェクト確認・イベント通知設定の目視）</td>
</tr>
<tr>
<td>同じ構成を繰り返しデプロイ</td>
<td><strong>SAM</strong>（ミスゼロ・自動化）</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc27">関連記事</span></h2>
<ul>
<li>SAM版ハンズオン — コマンド数本でS3 + Lambdaトリガー環境を構築</li>
</ul>

<a rel="noopener" href="https://caymezon.com/aws-handson-s3-event-lambda/" title="AWSハンズオン - S3へのファイルアップロードをトリガーにLambdaを自動起動しよう【SAM版 / Windows対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-event-lambda-featured-a9f1dc-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-event-lambda-featured-a9f1dc-160x90.jpg 160w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-event-lambda-featured-a9f1dc-120x68.jpg 120w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-event-lambda-featured-a9f1dc-320x180.jpg 320w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-s3-event-lambda-featured-a9f1dc-376x212.jpg 376w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AWSハンズオン - S3へのファイルアップロードをトリガーにLambdaを自動起動しよう【SAM版 / Windows対応】</div><div class="blogcard-snippet internal-blogcard-snippet">はじめに「S3にファイルが上がったら自動で処理したい」というのは、AWSを使う現場でよく出てくる要件です。画像のリサイズ、CSVの集計、ログファイルの解析など、ファイルアップロードを起点にした自動処理はサーバーレス構成の代表的なユースケース...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://caymezon.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">caymezon.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.02.23</div></div></div></div></a>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-s3-event-lambda/">AWSコンソールだけでS3 + Lambdaファイルアップロードトリガーを構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-s3-event-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでSQS + Lambdaキュー処理を構築する手順【SAM版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-sqs-lambda-queue/</link>
					<comments>https://caymezon.com/aws-handson-console-sqs-lambda-queue/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 00:59:29 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[SQS]]></category>
		<category><![CDATA[キュー処理]]></category>
		<category><![CDATA[デッドレターキュー]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[非同期処理]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20198</guid>

					<description><![CDATA[<p>目次 はじめにSAM vs コンソール：どれだけ違うか構築するもの全体の作業順序① DLQ（デッドレターキュー）作成1-1. キューの設定② メインキュー作成2-1. キューの設定2-2. デッドレターキュー（DLQ）の [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-sqs-lambda-queue/">AWSコンソールだけでSQS + Lambdaキュー処理を構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-14" checked><label class="toc-title" for="toc-checkbox-14">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">構築するもの</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① DLQ（デッドレターキュー）作成</a><ol><li><a href="#toc6" tabindex="0">1-1. キューの設定</a></li></ol></li><li><a href="#toc7" tabindex="0">② メインキュー作成</a><ol><li><a href="#toc8" tabindex="0">2-1. キューの設定</a></li><li><a href="#toc9" tabindex="0">2-2. デッドレターキュー（DLQ）の設定</a></li></ol></li><li><a href="#toc10" tabindex="0">③ Lambda 関数作成</a><ol><li><a href="#toc11" tabindex="0">3-1. 基本設定</a></li><li><a href="#toc12" tabindex="0">3-2. タイムアウトの設定</a></li><li><a href="#toc13" tabindex="0">3-3. コードの入力</a></li></ol></li><li><a href="#toc14" tabindex="0">④ Lambda 実行ロールに SQS 権限を追加</a></li><li><a href="#toc15" tabindex="0">⑤ SQS トリガーを Lambda に追加</a></li><li><a href="#toc16" tabindex="0">⑥ 動作テスト</a><ol><li><a href="#toc17" tabindex="0">6-1. 正常処理テスト</a></li><li><a href="#toc18" tabindex="0">6-2. DLQテスト（失敗メッセージの振り分け確認）</a></li></ol></li><li><a href="#toc19" tabindex="0">⑦ リソースの削除</a><ol><li><a href="#toc20" tabindex="0">1. Lambda のトリガー（SQSイベントソースマッピング）を削除する</a></li><li><a href="#toc21" tabindex="0">2. Lambda 関数を削除する</a></li><li><a href="#toc22" tabindex="0">3. SQS キューを削除する（メインキューを先に、次にDLQ）</a></li><li><a href="#toc23" tabindex="0">4. IAM ロールを削除する（任意）</a></li><li><a href="#toc24" tabindex="0">5. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc25" tabindex="0">SAMとの対比まとめ</a></li><li><a href="#toc26" tabindex="0">トラブルシューティング</a></li><li><a href="#toc27" tabindex="0">まとめ</a><ol><li><a href="#toc28" tabindex="0">コンソール操作で確認できたこと</a></li><li><a href="#toc29" tabindex="0">どちらを使うべきか</a></li></ol></li><li><a href="#toc30" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>この記事は、<a href="https://caymezon.com/aws-handson-sqs-lambda-queue/">SAM版ハンズオン記事</a>の比較版です。</p>
<p>SAM版ではコマンド数本でSQS・DLQ・Lambda・IAM権限がまとめてデプロイできましたが、<strong>「SAMが裏で何をやっているのか？」「コンソールで手動操作するとどれだけ手間がかかるのか？」</strong> を実感してもらうために、全く同じ構成をAWSコンソールのみで手作業で構築する手順を解説します。</p>
<p><strong>この記事を読むとわかること：</strong></p>
<ul>
<li>SQS・DLQ・Lambda・IAMを個別に設定する依存関係と順序</li>
<li>SAMが <code>SQSPollerPolicy</code> 1行で解決している IAM 権限設定の実態</li>
<li>DLQをメインキューに紐づける <code>RedrivePolicy</code> 設定の実際の操作</li>
</ul>
<hr>
<h2><span id="toc2">SAM vs コンソール：どれだけ違うか</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>操作ステップ数</strong></td>
<td>約5ステップ</td>
<td><strong>6リソース × 複数画面</strong></td>
</tr>
<tr>
<td><strong>ARNのコピー</strong></td>
<td>不要（<code>!GetAtt</code> で自動参照）</td>
<td><strong>DLQ の ARN を手動コピー・貼り付け</strong></td>
</tr>
<tr>
<td><strong>IAM権限設定</strong></td>
<td><code>SQSPollerPolicy</code> 1行</td>
<td><strong>IAMコンソールでポリシーを手動アタッチ</strong></td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td><code>sam delete</code> 1コマンド</td>
<td><strong>5種のリソースを個別に手動削除</strong></td>
</tr>
</tbody>
</table>
<p><strong>コンソール操作で学べることの価値：</strong></p>
<ul>
<li>IAMロールが「どのサービスが何の権限を持っているか」の具体的なイメージが掴める</li>
<li>DLQとメインキューの紐付け（RedrivePolicy）の設定画面を実際に見ることができる</li>
<li>トラブル時に「どのリソースの設定を確認すればよいか」がわかるようになる</li>
</ul>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc3">構築するもの</span></h2>
<p>SAM版と全く同じ構成・機能のメッセージキュー処理環境を構築します。</p>
<pre><code class="language-plaintext">送信者（コンソール / AWS CLI）
  ↓ メッセージ送信
SQS キュー（BatchQueue）
  ↓ Lambda がポーリング（自動）
Lambda（ProcessFunction / Python 3.12）
  ↓ 処理成功 → メッセージ削除（自動）
  ↓ 処理失敗（3回）→ DLQに移動
SQS デッドレターキュー（BatchDLQ）
  ↓ ログ出力
CloudWatch Logs</code></pre>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<p>コンソールでは<strong>依存する順番通り</strong>に作成する必要があります。</p>
<pre><code class="language-plaintext">① DLQ（BatchDLQ）作成
      ↓（DLQのARNが必要）
② メインキュー（BatchQueue）作成 + DLQを設定
      ↓（キューARNが必要）
③ Lambda 関数（ProcessFunction）作成 + コード入力
      ↓
④ Lambda 実行ロールに SQS 権限を追加
      ↓
⑤ SQS トリガーを Lambda に追加
      ↓
⑥ 動作テスト（正常処理 / DLQ振り分け）
⑦ リソースの削除</code></pre>
<blockquote>
<p><strong>順序が重要な理由：</strong><br />メインキューの作成時に DLQ の ARN が必要です。<br />SAMでは <code>!GetAtt BatchDLQ.Arn</code> で自動解決されますが、コンソールでは DLQ を先に作成してARNをコピーしておく必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc5">① DLQ（デッドレターキュー）作成</span></h2>
<p><strong>AWSコンソール → SQS → 「キューを作成」</strong></p>
<p><!-- ![SQS DLQ 作成画面](images/sqs-dlq-create.jpg) --></p>
<h3><span id="toc6">1-1. キューの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td><strong>スタンダード</strong></td>
</tr>
<tr>
<td>名前</td>
<td><code>BatchDLQ</code></td>
</tr>
</tbody>
</table>
<p>「設定」セクション（メッセージ保持期間のみ変更）：</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メッセージ保持期間</td>
<td><strong>1 日</strong>（デフォルト4日。学習用なので短くしてよい）</td>
</tr>
<tr>
<td>その他</td>
<td>デフォルトのまま</td>
</tr>
</tbody>
</table>
<p>「キューを作成」をクリックします。</p>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>DLQ の ARN（例: <code>arn:aws:sqs:ap-northeast-1:123456789012:BatchDLQ</code>）</li>
</ul>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMの <code>BatchDLQ: Type: AWS::SQS::Queue</code> の部分をコンソールで手動作成しています。SAMでは <code>!GetAtt BatchDLQ.Arn</code> でARNを自動参照できますが、コンソールではここで控えたARNを次のステップで手動入力します。</p>
</blockquote>
<hr>
<h2><span id="toc7">② メインキュー作成</span></h2>
<p><strong>AWSコンソール → SQS → 「キューを作成」</strong></p>
<h3><span id="toc8">2-1. キューの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイプ</td>
<td><strong>スタンダード</strong></td>
</tr>
<tr>
<td>名前</td>
<td><code>BatchQueue</code></td>
</tr>
</tbody>
</table>
<p>「設定」セクション（可視性タイムアウトのみ変更）：</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>可視性タイムアウト</td>
<td><strong>180</strong> 秒</td>
</tr>
<tr>
<td>メッセージ保持期間</td>
<td>4 日（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>可視性タイムアウトについて：</strong><br />Lambda 関数のタイムアウト（30秒）× 6 以上を設定することがAWS推奨です。<br />処理中にタイムアウトが切れると、同じメッセージが再度キューに現れて二重処理が発生します。<br />今回は Lambda タイムアウト 30秒 × 6 = <strong>180秒</strong> に設定します。</p>
<p>SAMでは <code>VisibilityTimeout: 180</code> の1行ですが、コンソールでは手動入力が必要です。</p>
</blockquote>
<h3><span id="toc9">2-2. デッドレターキュー（DLQ）の設定</span></h3>
<p>「デッドレターキュー」セクション：</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>デッドレターキューを有効にする</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>デッドレターキューの ARN</td>
<td>① で控えた <code>BatchDLQ</code> の ARN を貼り付ける</td>
</tr>
<tr>
<td>最大受信数（maxReceiveCount）</td>
<td><strong>3</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>最大受信数（maxReceiveCount）について：</strong><br />同じメッセージが3回処理を試みて全て失敗した場合、DLQに移動します。<br />「1回目の失敗 → 可視性タイムアウト後に再試行 → 2回目の失敗 → 再試行 → 3回目の失敗 → DLQへ」という流れです。<br />SAMでは <code>maxReceiveCount: 3</code> の1行で同じ設定が完了します。</p>
</blockquote>
<p>「キューを作成」をクリックします。</p>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>BatchQueue の URL（例: <code>https://sqs.ap-northeast-1.amazonaws.com/123456789012/BatchQueue</code>）</li>
</ul>
<hr>
<h2><span id="toc10">③ Lambda 関数作成</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<h3><span id="toc11">3-1. 基本設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>ProcessFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリックします。</p>
<h3><span id="toc12">3-2. タイムアウトの設定</span></h3>
<p>関数ページ → 「設定」タブ → 「一般設定」→「編集」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイムアウト</td>
<td><strong>30</strong> 秒</td>
</tr>
</tbody>
</table>
<p>「保存」をクリックします。</p>
<h3><span id="toc13">3-3. コードの入力</span></h3>
<p>関数ページ → 「コード」タブ → コードエディタで <code>lambda_function.py</code> を開きます。</p>
<p>既存の内容を<strong>全て</strong>置き換えて以下を貼り付けます。</p>
<pre><code class="language-python">import json
import datetime


def lambda_handler(event, context):
    results = []

    for record in event["Records"]:       # SQSからの各メッセージを順番に処理
        message_id = record["messageId"]
        body = record["body"]

        if body.strip().lower() == "error":
            raise ValueError(f"意図的なエラー: messageId={message_id}, body={body}")

        now = datetime.datetime.now(datetime.timezone.utc)

        result = {
            "messageId": message_id,
            "body": body,
            "processedAt": now.isoformat(),
            "status": "processed",
        }

        print(json.dumps(result, ensure_ascii=False))
        results.append(result)

    print(json.dumps({"processedCount": len(results)}, ensure_ascii=False))
    return {"processedCount": len(results), "results": results}</code></pre>
<p>「Deploy」ボタンをクリックしてコードを保存します。</p>
<hr>
<h2><span id="toc14">④ Lambda 実行ロールに SQS 権限を追加</span></h2>
<p>デフォルトの実行ロールは <strong>CloudWatch Logs への書き込みしか持っていません</strong>。SQSからメッセージを取り出す権限を手動で追加する必要があります。</p>
<p><strong>Lambda → <code>ProcessFunction</code> → 「設定」タブ → 「アクセス権限」→ 実行ロール名のリンクをクリック</strong></p>
<p>（例: <code>ProcessFunction-role-XXXX</code>）→ IAMコンソールのロール画面が開きます。</p>
<p>「許可を追加」→「ポリシーをアタッチ」</p>
<p>検索ボックスに <code>SQS</code> と入力 → <strong><code>AWSLambdaSQSQueueExecutionRole</code></strong> にチェック → 「許可を追加」をクリックします。</p>
<p><!-- ![IAM ポリシーアタッチ画面](images/iam-policy-attach.jpg) --></p>
<blockquote>
<p><strong><code>AWSLambdaSQSQueueExecutionRole</code> に含まれる権限：</strong></p>
<ul>
<li><code>sqs:ReceiveMessage</code> — キューからメッセージを取り出す</li>
<li><code>sqs:DeleteMessage</code> — 処理完了後にメッセージを削除する</li>
<li><code>sqs:GetQueueAttributes</code> — キューの属性情報を取得する</li>
</ul>
</blockquote>
<blockquote>
<p><strong>SAMとの差分：</strong><br />SAMでは <code>SQSPollerPolicy: QueueName: !GetAtt BatchQueue.QueueName</code> の2行で上記3権限が自動付与されます。コンソールでは IAMコンソールへの画面遷移 → ポリシー検索 → アタッチの操作が必要です。</p>
</blockquote>
<hr>
<h2><span id="toc15">⑤ SQS トリガーを Lambda に追加</span></h2>
<p><strong>Lambda → <code>ProcessFunction</code> → 「設定」タブ → 「トリガー」→「トリガーを追加」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ソース</td>
<td><strong>SQS</strong></td>
</tr>
<tr>
<td>SQS キュー</td>
<td><code>BatchQueue</code>（② で作成したキュー）</td>
</tr>
<tr>
<td>バッチサイズ</td>
<td><strong>5</strong></td>
</tr>
<tr>
<td>バッチウィンドウ</td>
<td><strong>0</strong> 秒（デフォルト）</td>
</tr>
<tr>
<td>トリガーの有効化</td>
<td>オン</td>
</tr>
</tbody>
</table>
<p>「追加」をクリックします。</p>
<p><!-- ![Lambda SQSトリガー設定画面](images/lambda-sqs-trigger.jpg) --></p>
<blockquote>
<p><strong>バッチサイズとバッチウィンドウについて：</strong></p>
<table>
<thead>
<tr>
<th>設定</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td>バッチサイズ=5</td>
<td>キューに溜まったメッセージを最大5件まとめてLambdaに渡す</td>
</tr>
<tr>
<td>バッチウィンドウ=0</td>
<td>メッセージが来たらすぐにLambdaを呼び出す（待機なし）</td>
</tr>
</tbody>
</table>
<p>バッチサイズを大きくするとLambdaの呼び出し回数が減りコスト節約になりますが、1件でも失敗するとバッチ全体が再試行される点に注意してください。</p>
</blockquote>
<blockquote>
<p><strong>SAMとの差分：</strong><br />SAMの <code>Type: SQS</code> / <code>BatchSize: 5</code> の設定がここに対応しています。コンソールではこの「トリガーを追加」画面で手動設定します。</p>
</blockquote>
<hr>
<h2><span id="toc16">⑥ 動作テスト</span></h2>
<h3><span id="toc17">6-1. 正常処理テスト</span></h3>
<p><strong>方法A: コンソールからメッセージ送信</strong></p>
<p>SQS → <code>BatchQueue</code> → 「メッセージを送受信」→「メッセージを送信」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メッセージ本文</td>
<td><code>こんにちは、SQS！</code></td>
</tr>
</tbody>
</table>
<p>「メッセージを送信」をクリックします。</p>
<p><strong>方法B: AWS CLI でメッセージ送信</strong></p>
<pre><code class="language-cmd">aws sqs send-message ^
  --queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/BatchQueue ^
  --message-body "こんにちは、SQS！" ^
  --region ap-northeast-1</code></pre>
<p><strong>CloudWatch Logs でログを確認（数秒後）：</strong></p>
<p>Lambda → <code>ProcessFunction</code> → 「モニタリング」タブ → 「CloudWatch Logs を表示」</p>
<p><strong>期待するログ出力：</strong></p>
<pre><code class="language-json">{"messageId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "body": "こんにちは、SQS！", "processedAt": "2026-02-22T10:00:00.000000+00:00", "status": "processed"}
{"processedCount": 1}</code></pre>
<p><code>&quot;status&quot;: &quot;processed&quot;</code> が表示されれば正常処理完了です。</p>
<h3><span id="toc18">6-2. DLQテスト（失敗メッセージの振り分け確認）</span></h3>
<p>メッセージ本文を <code>error</code> にして送信すると、Lambda が例外を発生させてDLQに移動します。</p>
<pre><code class="language-cmd">aws sqs send-message ^
  --queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/BatchQueue ^
  --message-body "error" ^
  --region ap-northeast-1</code></pre>
<p><strong>処理の流れ：</strong></p>
<ol>
<li>Lambda が <code>error</code> を受信 → 例外発生（処理失敗）</li>
<li>可視性タイムアウト（180秒）が切れると再度キューに現れる</li>
<li>3回失敗 → <code>BatchDLQ</code> に移動</li>
</ol>
<blockquote>
<p><strong>注意：DLQに移動するまで最大180秒 × 3回 = 最大9分かかります。</strong><br />すぐに確認したい場合は、BatchQueue の可視性タイムアウトを一時的に短く（例: 10秒）して再試行するとよいです。</p>
</blockquote>
<p><strong>DLQにメッセージが届いたか確認：</strong></p>
<p>SQS → <code>BatchDLQ</code> → 「メッセージを送受信」→「メッセージをポーリング」</p>
<p><code>error</code> のメッセージが表示されれば <strong>DLQ動作確認完了</strong>です。</p>
<p><!-- ![DLQ メッセージポーリング確認](images/sqs-dlq-message.jpg) --></p>
<hr>
<h2><span id="toc19">⑦ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除してください。</strong></p>
<h3><span id="toc20">1. Lambda のトリガー（SQSイベントソースマッピング）を削除する</span></h3>
<p><strong>Lambda → <code>ProcessFunction</code> → 「設定」タブ → 「トリガー」→ SQSトリガーを選択 → 「削除」</strong></p>
<h3><span id="toc21">2. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>ProcessFunction</code> を選択 → 「アクション」→「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<h3><span id="toc22">3. SQS キューを削除する（メインキューを先に、次にDLQ）</span></h3>
<p><strong>SQS → <code>BatchQueue</code> を選択 → 「削除」→ キュー名を入力 → 「削除」</strong></p>
<p><strong>SQS → <code>BatchDLQ</code> を選択 → 「削除」→ キュー名を入力 → 「削除」</strong></p>
<h3><span id="toc23">4. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>ProcessFunction-role-XXXX</code> を選択 → 「削除」→ ロール名を入力 → 「削除」</strong></p>
<blockquote>
<p>Lambda を削除しても自動作成された IAM ロールはそのまま残ります。厳密に削除したい場合は IAM コンソールで手動削除します。</p>
</blockquote>
<h3><span id="toc24">5. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/ProcessFunction</code> → 「アクション」→「ロググループの削除」</strong></p>
<blockquote>
<p><strong>SAMとの差分：</strong><br />SAMの <code>sam delete</code> はCloudFormationスタックを削除することで、SQS×2・Lambda・IAMロール・S3を一括削除します。コンソールでは上記5手順を個別に実行する必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc25">SAMとの対比まとめ</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>BatchDLQ: Type: AWS::SQS::Queue</code></td>
<td>SQS → キューを作成（BatchDLQ）</td>
</tr>
<tr>
<td><code>RedrivePolicy: maxReceiveCount: 3</code></td>
<td>メインキューのDLQ設定で「最大受信数 = 3」を入力</td>
</tr>
<tr>
<td><code>VisibilityTimeout: 180</code></td>
<td>メインキューの設定で可視性タイムアウト = 180秒を入力</td>
</tr>
<tr>
<td><code>SQSPollerPolicy</code>（SAM組み込み）</td>
<td>IAMコンソールで <code>AWSLambdaSQSQueueExecutionRole</code> を手動アタッチ</td>
</tr>
<tr>
<td><code>Type: SQS</code> イベント / <code>BatchSize: 5</code></td>
<td>Lambda → トリガー追加（SQS・バッチサイズ5）</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>Lambda・SQS×2・IAMロール・ロগগループを個別に削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc26">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lambdaが実行されない</td>
<td>実行ロールにSQS権限がない</td>
<td>④ の手順で <code>AWSLambdaSQSQueueExecutionRole</code> をアタッチ</td>
</tr>
<tr>
<td>メッセージがキューに残り続ける</td>
<td>SQSトリガーが設定されていない</td>
<td>⑤ の手順でトリガーを追加する</td>
</tr>
<tr>
<td>DLQにメッセージが届かない</td>
<td>可視性タイムアウトが長すぎて待機中</td>
<td>しばらく待つ（最大180秒 × 3回 ≒ 9分）</td>
</tr>
<tr>
<td>Lambda が 500 エラー</td>
<td>コードの構文エラーなど</td>
<td>CloudWatch Logs でエラー内容を確認</td>
</tr>
<tr>
<td><code>error</code> 送信後すぐにDLQを確認したい</td>
<td>可視性タイムアウトが長い</td>
<td>テスト目的でキューの可視性タイムアウトを10秒に変更する</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc27">まとめ</span></h2>
<h3><span id="toc28">コンソール操作で確認できたこと</span></h3>
<p>コンソール操作を通じて、SAMが裏側で自動処理している内容が明確になりました：</p>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>SQSPollerPolicy</code>（1行）</td>
<td>IAMコンソールでポリシーを手動検索・アタッチ</td>
</tr>
<tr>
<td><code>!GetAtt BatchDLQ.Arn</code>（自動参照）</td>
<td>DLQ作成後にARNをコピー・貼り付け</td>
</tr>
<tr>
<td><code>sam delete</code>（1コマンド）</td>
<td>5種のリソースを個別に手動削除</td>
</tr>
</tbody>
</table>
<h3><span id="toc29">どちらを使うべきか</span></h3>
<table>
<thead>
<tr>
<th>シーン</th>
<th>推奨</th>
</tr>
</thead>
<tbody>
<tr>
<td>本番環境・チーム開発</td>
<td><strong>SAM</strong>（再現性・Git管理・速度）</td>
</tr>
<tr>
<td>AWSを初めて学ぶ</td>
<td><strong>コンソール</strong>（IAMや各サービスの設定の意味を理解する）</td>
</tr>
<tr>
<td>構築済みリソースの確認・デバッグ</td>
<td><strong>コンソール</strong>（目視確認）</td>
</tr>
<tr>
<td>同じ構成を繰り返しデプロイ</td>
<td><strong>SAM</strong>（ミスゼロ・自動化）</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc30">関連記事</span></h2>
<ul>
<li>SAM版ハンズオン — コマンド数本でSQS + Lambda + DLQ環境を構築</li>
</ul>

<a rel="noopener" href="https://caymezon.com/aws-handson-sqs-lambda-queue/" title="AWSハンズオン - SQS + Lambdaでメッセージキュー処理を実装しよう【SAM版 / Windows対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-sqs-lambda-queue-featured-25fc3c-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-sqs-lambda-queue-featured-25fc3c-160x90.jpg 160w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-sqs-lambda-queue-featured-25fc3c-120x68.jpg 120w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-sqs-lambda-queue-featured-25fc3c-320x180.jpg 320w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-sqs-lambda-queue-featured-25fc3c-376x212.jpg 376w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AWSハンズオン - SQS + Lambdaでメッセージキュー処理を実装しよう【SAM版 / Windows対応】</div><div class="blogcard-snippet internal-blogcard-snippet">はじめに「メッセージキューって何に使うの？」「エラーが起きたメッセージをどうやって管理するの？」という疑問を持っている方向けに、Amazon SQS + Lambda によるメッセージキュー処理をゼロから構築するハンズオンを紹介します。今回...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://caymezon.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">caymezon.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.02.23</div></div></div></div></a>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-sqs-lambda-queue/">AWSコンソールだけでSQS + Lambdaキュー処理を構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-sqs-lambda-queue/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでEventBridge + Lambda定期バッチを構築する手順【SAM版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-eventbridge-lambda-batch/</link>
					<comments>https://caymezon.com/aws-handson-console-eventbridge-lambda-batch/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 22 Feb 2026 08:07:22 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[EventBridge]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[スケジュール実行]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[バッチ処理]]></category>
		<category><![CDATA[初心者]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20192</guid>

					<description><![CDATA[<p>目次 はじめにSAM vs コンソール：どれだけ違うか構築するもの全体の作業順序① Lambda 関数作成1-1. 基本設定1-2. コードの入力1-3. 動作確認（テスト実行）② EventBridge スケジュール作 [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-eventbridge-lambda-batch/">AWSコンソールだけでEventBridge + Lambda定期バッチを構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-16" checked><label class="toc-title" for="toc-checkbox-16">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">構築するもの</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① Lambda 関数作成</a><ol><li><a href="#toc6" tabindex="0">1-1. 基本設定</a></li><li><a href="#toc7" tabindex="0">1-2. コードの入力</a></li><li><a href="#toc8" tabindex="0">1-3. 動作確認（テスト実行）</a></li></ol></li><li><a href="#toc9" tabindex="0">② EventBridge スケジュール作成</a><ol><li><a href="#toc10" tabindex="0">2-1. スケジュールの名前と説明</a></li><li><a href="#toc11" tabindex="0">2-2. スケジュールパターンの設定</a></li><li><a href="#toc12" tabindex="0">2-3. ターゲットの選択</a></li><li><a href="#toc13" tabindex="0">2-4. 設定</a></li><li><a href="#toc14" tabindex="0">2-5. 確認と作成</a></li></ol></li><li><a href="#toc15" tabindex="0">③ CloudWatch Logs で動作確認</a><ol><li><a href="#toc16" tabindex="0">3-1. ログの確認</a></li><li><a href="#toc17" tabindex="0">3-2. 実行回数の確認</a></li></ol></li><li><a href="#toc18" tabindex="0">④ リソースの削除</a><ol><li><a href="#toc19" tabindex="0">1. EventBridge スケジュールを削除する</a></li><li><a href="#toc20" tabindex="0">2. Lambda 関数を削除する</a></li><li><a href="#toc21" tabindex="0">3. EventBridge Scheduler の実行ロールを削除する（任意）</a></li><li><a href="#toc22" tabindex="0">4. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc23" tabindex="0">SAMとの対比まとめ</a></li><li><a href="#toc24" tabindex="0">トラブルシューティング</a></li><li><a href="#toc25" tabindex="0">まとめ</a><ol><li><a href="#toc26" tabindex="0">今回の手順で確認したこと</a></li><li><a href="#toc27" tabindex="0">コンソール操作で学べたこと</a></li><li><a href="#toc28" tabindex="0">どちらを使うべきか</a></li></ol></li><li><a href="#toc29" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>この記事は、<a href="https://caymezon.com/aws-handson-eventbridge-lambda-batch/">SAM版ハンズオン記事</a>の比較版です。</p>
<p>SAM版ではコマンド数本でインフラが完成しましたが、<strong>「その裏で何が起きているのか？」「SAMを使わない場合はどれだけ手間がかかるのか？」</strong> を実感してもらうために、全く同じEventBridge + Lambda定期バッチ構成をAWSコンソールのみで手作業で構築する手順を詳細に解説します。</p>
<p><strong>この記事を読むとわかること：</strong></p>
<ul>
<li>AWS各サービス（Lambda・EventBridge）を個別に設定する流れ</li>
<li>SAMが裏側で自動処理していること（IAMロール・EventBridgeターゲット設定・権限付与など）</li>
<li>SAMとコンソール手動操作、それぞれの使いどころ</li>
</ul>
<hr>
<h2><span id="toc2">SAM vs コンソール：どれだけ違うか</span></h2>
<p>まず差分を数字で確認します。</p>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>操作ステップ数</strong></td>
<td>約5ステップ</td>
<td><strong>約20〜30クリック</strong></td>
</tr>
<tr>
<td><strong>所要時間</strong></td>
<td>5〜10分</td>
<td><strong>15〜30分</strong></td>
</tr>
<tr>
<td><strong>ミスのリスク</strong></td>
<td>低い（テンプレート通り）</td>
<td><strong>高い</strong>（クリック漏れ・設定誤り）</td>
</tr>
<tr>
<td><strong>再現性</strong></td>
<td>完全（同じ結果が保証）</td>
<td><strong>低い</strong>（毎回手作業）</td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td><code>sam delete</code> 1コマンド</td>
<td><strong>複数サービスを個別に手動削除</strong></td>
</tr>
<tr>
<td><strong>コード管理</strong></td>
<td>Git で管理可能</td>
<td><strong>管理不可</strong>（画面操作は記録されない）</td>
</tr>
</tbody>
</table>
<p>「それでもコンソール操作を知っておく価値はあるか？」という問いに対して、答えは <strong>Yes</strong> です。</p>
<p><strong>コンソール操作が特に有効な場面：</strong></p>
<ul>
<li><strong>障害調査</strong> — 実際にどのリソースがどう設定されているか目視確認する</li>
<li><strong>SAMのデバッグ</strong> — SAMでデプロイしたリソースをコンソールで確認・修正する</li>
<li><strong>初学習</strong> — 各サービスの設定項目を理解するための最初の一歩</li>
</ul>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc3">構築するもの</span></h2>
<p>SAM版と全く同じ構成・機能のバッチ実行環境を構築します。</p>
<pre><code class="language-plaintext">EventBridge スケジュールルール（rate: 1分ごと）
  ↓ イベント発火
Lambda（BatchFunction / Python 3.12）
  ↓ ログ出力
CloudWatch Logs</code></pre>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<p>SAMは依存関係を自動解決しますが、コンソールでは<strong>依存する順番通りに</strong>作成する必要があります。</p>
<pre><code class="language-plaintext">① Lambda 関数作成（コードをコンソールで直接入力）
      ↓（関数ARNが必要）
② EventBridge スケジュール作成・ターゲット設定
      ↓
③ CloudWatch Logs で動作確認</code></pre>
<p>この順序を守らないと、設定画面で参照先リソースが見つからずエラーになります。</p>
<hr>
<h2><span id="toc5">① Lambda 関数作成</span></h2>
<p><strong>AWSコンソール → Lambda → 関数 → 「関数の作成」</strong></p>
<p><!-- ![Lambda 関数作成画面](images/lambda-create-function.jpg) --></p>
<h3><span id="toc6">1-1. 基本設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>BatchFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリックします。</p>
<blockquote>
<p><strong>実行ロールについて：</strong><br />デフォルトで <code>BatchFunction-role-XXXX</code> という IAM ロールが自動作成されます。<br />このロールには <code>AWSLambdaBasicExecutionRole</code> が付与されており、CloudWatch Logs への書き込み権限が含まれます。<br />今回は DynamoDB などの外部サービスを使わないため、このデフォルトロールで十分です。</p>
</blockquote>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMでは <code>AWSLambdaBasicExecutionRole</code> はすべての <code>AWS::Serverless::Function</code> に自動付与されます。コンソールでは「基本的なアクセス権限で新しいロールを作成」を選択することで同じ設定が適用されます。</p>
</blockquote>
<h3><span id="toc7">1-2. コードの入力</span></h3>
<p>関数ページ → 「コード」タブ → コードエディタが表示されます。</p>
<p><code>lambda_function.py</code> に以下のコードを貼り付けます（既存の内容を<strong>全て</strong>置き換えてください）。</p>
<pre><code class="language-python">import json
import datetime
import random


def lambda_handler(event, context):
    now_utc = datetime.datetime.now(datetime.timezone.utc)

    # JST（UTC+9）に変換
    jst = datetime.timezone(datetime.timedelta(hours=9))
    now_jst = now_utc.astimezone(jst)

    # バッチ処理のシミュレーション（ランダムな処理件数）
    processed_count = random.randint(10, 100)

    result = {
        "status": "success",
        "executedAt": {
            "utc": now_utc.isoformat(),
            "jst": now_jst.strftime("%Y-%m-%d %H:%M:%S JST"),
        },
        "processedCount": processed_count,
        "message": f"{processed_count}件の処理が完了しました",
        "triggeredBy": event.get("source", "manual"),
    }

    print(json.dumps(result, ensure_ascii=False))
    return result</code></pre>
<p>「Deploy」ボタンをクリックしてコードを保存します。</p>
<h3><span id="toc8">1-3. 動作確認（テスト実行）</span></h3>
<p>EventBridge のスケジュール設定前に、Lambda 単体で動くか確認します。</p>
<p>「テスト」タブ → 「テストイベントを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>イベント名</td>
<td><code>test-event</code></td>
</tr>
<tr>
<td>テンプレート</td>
<td><code>hello-world</code>（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「テスト」ボタンをクリックします。</p>
<p><strong>期待する結果（実行結果の展開）：</strong></p>
<pre><code class="language-json">{
  "status": "success",
  "executedAt": {
    "utc": "2026-02-22T10:00:00.000000+00:00",
    "jst": "2026-02-22 19:00:00 JST"
  },
  "processedCount": 42,
  "message": "42件の処理が完了しました",
  "triggeredBy": "manual"
}</code></pre>
<p><code>Status: Succeeded</code> が表示されれば Lambda 関数は正常に動作しています。</p>
<p><strong>控えておく情報：</strong></p>
<ul>
<li>関数 ARN（例: <code>arn:aws:lambda:ap-northeast-1:123456789012:function:BatchFunction</code>）</li>
</ul>
<hr>
<h2><span id="toc9">② EventBridge スケジュール作成</span></h2>
<blockquote>
<p><strong>EventBridge Scheduler と EventBridge ルールの違い：</strong><br />コンソールには「スケジュール」と「ルール」の2種類があります。</p>
<ul>
<li><strong>スケジュール</strong> (EventBridge Scheduler): 新しいサービス。タイムゾーン設定・フレックスタイムウィンドウあり</li>
<li><strong>ルール</strong> (EventBridge Events): 旧サービス。SAMの <code>Type: Schedule</code> はこちらを内部で使用</li>
</ul>
<p>このコンソール手順では新しい「スケジュール」を使います。</p>
</blockquote>
<p><strong>AWSコンソール → EventBridge → スケジュール → 「スケジュールを作成」</strong></p>
<p><!-- ![EventBridge スケジュール作成画面](images/eventbridge-create-schedule.jpg) --></p>
<h3><span id="toc10">2-1. スケジュールの名前と説明</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>batch-schedule-1min</code></td>
</tr>
<tr>
<td>説明</td>
<td>1分ごとにBatchFunctionを実行（任意）</td>
</tr>
<tr>
<td>スケジュールグループ</td>
<td>default（変更不要）</td>
</tr>
</tbody>
</table>
<p>「次へ」をクリックします。</p>
<h3><span id="toc11">2-2. スケジュールパターンの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>スケジュールの発生</td>
<td><strong>定期的なスケジュール</strong></td>
</tr>
<tr>
<td>タイムゾーン</td>
<td>(UTC+09:00) Asia/Tokyo（任意）</td>
</tr>
<tr>
<td>スケジュールの種類</td>
<td><strong>rateベースのスケジュール</strong></td>
</tr>
<tr>
<td>レート式</td>
<td><code>1</code> 分</td>
</tr>
<tr>
<td>フレックスタイムウィンドウ</td>
<td><strong>オフ</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>フレックスタイムウィンドウについて：</strong><br />「オフ」を選択すると指定した時刻に正確に実行されます。<br />「5分」などを設定すると、指定時刻から5分以内のランダムな時刻に実行されます（大量スケジュールの負荷分散用）。<br />ハンズオン目的では<strong>オフ</strong>でよいです。</p>
</blockquote>
<blockquote>
<p><strong>rateベースとcronベースの違い：</strong></p>
<ul>
<li>rateベース: 「X分ごと」などシンプルな繰り返し → <code>1 分</code> と入力するだけ</li>
<li>cronベース: 「毎日9時」など複雑なスケジュール → 分・時・日・月・曜日・年を全て入力する必要がある</li>
</ul>
<p>1分ごとの繰り返しには<strong>rateベース</strong>が最もシンプルです。<br />cronベースで「1分ごと」を設定するには全フィールドへの入力が必要で複雑になります。</p>
</blockquote>
<p>「次へ」をクリックします。</p>
<h3><span id="toc12">2-3. ターゲットの選択</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ターゲットのAPIを選択</td>
<td><strong>テンプレート済みターゲット</strong></td>
</tr>
<tr>
<td>ターゲット</td>
<td><strong>Lambda: 関数を呼び出す</strong></td>
</tr>
<tr>
<td>関数</td>
<td><code>BatchFunction</code></td>
</tr>
<tr>
<td>ペイロード</td>
<td>以下のJSONを入力</td>
</tr>
</tbody>
</table>
<p>ペイロードに以下を入力します（どこから実行されたかをログで確認できるようにするための設定です）。</p>
<pre><code class="language-json">{"source": "eventbridge-scheduler"}</code></pre>
<p>「次へ」をクリックします。</p>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMの <code>Type: Schedule</code> では EventBridge → Lambda のターゲット設定と権限付与が自動で行われます。コンソールでは2-3の「ターゲット選択」画面で手動設定します。</p>
</blockquote>
<h3><span id="toc13">2-4. 設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>スケジュールの状態</td>
<td><strong>有効</strong></td>
</tr>
<tr>
<td>アクションの再試行</td>
<td>デフォルトのまま</td>
</tr>
<tr>
<td>実行ロール</td>
<td><strong>このスケジュールの新しいロールを作成</strong></td>
</tr>
</tbody>
</table>
<p>「次へ」をクリックします。</p>
<blockquote>
<p><strong>実行ロールについて：</strong><br />EventBridge Scheduler が Lambda を呼び出すための IAM ロール（<code>Amazon_EventBridge_Scheduler_LAMBDA_XXXX</code>）が自動作成されます。削除時に一緒に削除します。</p>
</blockquote>
<h3><span id="toc14">2-5. 確認と作成</span></h3>
<p>内容を確認して「スケジュールを作成」をクリックします。</p>
<hr>
<h2><span id="toc15">③ CloudWatch Logs で動作確認</span></h2>
<h3><span id="toc16">3-1. ログの確認</span></h3>
<p>スケジュール作成後、最大1分待つとLambdaが自動実行されます。</p>
<p><strong>確認方法 1: Lambda コンソールから</strong></p>
<p>Lambda → <code>BatchFunction</code> → 「モニタリング」タブ → 「CloudWatch Logs を表示」</p>
<p><strong>確認方法 2: CloudWatch Logs コンソールから</strong></p>
<p>CloudWatch → ロググループ → <code>/aws/lambda/BatchFunction</code> → 最新のログストリームを開く</p>
<p><!-- ![CloudWatch Logs ログ確認画面](images/cloudwatch-logs-output.jpg) --></p>
<p><strong>期待するログ出力：</strong></p>
<pre><code class="language-json">{"status": "success", "executedAt": {"utc": "2026-02-22T10:00:00.000000+00:00", "jst": "2026-02-22 19:00:00 JST"}, "processedCount": 57, "message": "57件の処理が完了しました", "triggeredBy": "eventbridge-scheduler"}</code></pre>
<p><code>&quot;triggeredBy&quot;: &quot;eventbridge-scheduler&quot;</code> となっていれば EventBridge Scheduler から自動実行されています。<br />（2-3でペイロードに <code>{&quot;source&quot;: &quot;eventbridge-scheduler&quot;}</code> を設定したため、Lambda がこの値を受け取ります。）</p>
<h3><span id="toc17">3-2. 実行回数の確認</span></h3>
<p>Lambda → <code>BatchFunction</code> → 「モニタリング」タブ → 「呼び出し」グラフで実行回数が確認できます。<br />1分ごとに増えていれば正常動作しています。</p>
<hr>
<h2><span id="toc18">④ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除してください。</strong></p>
<blockquote>
<p><strong>注意：</strong> <code>rate(1 minute)</code> は毎分実行されるため、放置すると CloudWatch Logs のログが蓄積します。ハンズオン完了後は速やかに削除してください。</p>
</blockquote>
<h3><span id="toc19">1. EventBridge スケジュールを削除する</span></h3>
<p><strong>EventBridge → スケジュール → <code>batch-schedule-1min</code> を選択 → 「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<h3><span id="toc20">2. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>BatchFunction</code> を選択 → 「アクション」→「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<blockquote>
<p>Lambda を削除しても、自動作成された IAM ロール（<code>BatchFunction-role-XXXX</code>）はそのまま残ります。<br />厳密に削除する場合は IAM → ロール → <code>BatchFunction-role-XXXX</code> も削除します。</p>
</blockquote>
<h3><span id="toc21">3. EventBridge Scheduler の実行ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>Amazon_EventBridge_Scheduler_LAMBDA_XXXX</code> を選択 → 「削除」→ ロール名を入力 → 「削除」</strong></p>
<p>2-4 で自動作成された Scheduler 専用の実行ロールです。不要なら削除します。</p>
<h3><span id="toc22">4. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/BatchFunction</code> → 「アクション」→「ロググループの削除」</strong></p>
<p>Lambda を削除してもロググループは残るため、不要なら手動で削除します。</p>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMの <code>sam delete</code> は CloudFormation スタックを削除することで、S3・Lambda・EventBridgeルール・IAMロールを一括で削除します。コンソールでは各リソースを個別に手動削除する必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc23">SAMとの対比まとめ</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Type: Schedule</code> / <code>Schedule: rate(1 minute)</code></td>
<td>EventBridge Scheduler → スケジュール作成（rateベース・1分）</td>
</tr>
<tr>
<td><code>Enabled: true</code></td>
<td>スケジュールの状態を「有効」に設定</td>
</tr>
<tr>
<td><code>AWSLambdaBasicExecutionRole</code>（自動付与）</td>
<td>Lambda作成時「基本的なアクセス権限で新しいロールを作成」を選択</td>
</tr>
<tr>
<td>EventBridgeのターゲット設定（自動）</td>
<td>2-3 でターゲットに Lambda を選択・ペイロード設定</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>スケジュール・Lambda・IAMロール×2・ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>SAM版との内部サービスの違い：</strong><br />SAMの <code>Type: Schedule</code> は旧サービスの「EventBridge ルール（EventBridge Events）」を使用します。<br />このコンソール版では新しい「EventBridge Scheduler」を使用しており、UIや設定項目が異なります。<br />どちらも「定期実行」の機能は同じです。</p>
</blockquote>
<hr>
<h2><span id="toc24">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lambda が実行されない</td>
<td>EventBridgeスケジュールが無効になっている</td>
<td>EventBridge → スケジュール → スケジュールを選択 → 「有効化」</td>
</tr>
<tr>
<td>ログが出ない</td>
<td>ロググループが作成されていない</td>
<td>Lambda を一度テスト実行してロググループを作成する</td>
</tr>
<tr>
<td><code>&quot;triggeredBy&quot;</code> が <code>&quot;manual&quot;</code> のまま</td>
<td>EventBridgeからまだ実行されていない</td>
<td>最大1分待つ</td>
</tr>
<tr>
<td>Lambda が 500 エラー</td>
<td>コードの構文エラーなど</td>
<td>CloudWatch Logs でエラー内容を確認</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc25">まとめ</span></h2>
<h3><span id="toc26">今回の手順で確認したこと</span></h3>
<p>コンソール操作を通じて、SAMが裏側で自動処理している内容が明確になりました：</p>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Type: Schedule</code>（1行）</td>
<td>EventBridgeスケジュール作成 → ターゲット設定（2画面）</td>
</tr>
<tr>
<td><code>AWSLambdaBasicExecutionRole</code>（自動）</td>
<td>Lambda作成時にデフォルトロール選択</td>
</tr>
<tr>
<td><code>sam delete</code>（1コマンド）</td>
<td>スケジュール・Lambda・IAMロール×2を個別手動削除</td>
</tr>
</tbody>
</table>
<h3><span id="toc27">コンソール操作で学べたこと</span></h3>
<ul>
<li><strong>IAMロールの自動作成</strong> — Lambda作成時とEventBridgeスケジュール作成時にそれぞれ別のIAMロールが自動作成される仕組み</li>
<li><strong>EventBridge Schedulerの仕組み</strong> — rateベース・cronベースの違いと、フレックスタイムウィンドウの概念</li>
<li><strong>ペイロードの役割</strong> — EventBridgeからLambdaに渡すパラメータで実行元を識別できる</li>
<li><strong>リソース間の依存関係</strong> — Lambda作成 → EventBridge設定の順序が決まっている理由</li>
</ul>
<h3><span id="toc28">どちらを使うべきか</span></h3>
<table>
<thead>
<tr>
<th>シーン</th>
<th>推奨</th>
</tr>
</thead>
<tbody>
<tr>
<td>本番環境・チーム開発</td>
<td><strong>SAM</strong>（再現性・Git管理・速度）</td>
</tr>
<tr>
<td>AWSを初めて学ぶ</td>
<td><strong>コンソール</strong>（各設定の意味を理解する）</td>
</tr>
<tr>
<td>構築済みリソースの確認・デバッグ</td>
<td><strong>コンソール</strong>（目視確認）</td>
</tr>
<tr>
<td>同じ構成を繰り返しデプロイ</td>
<td><strong>SAM</strong>（ミスゼロ・自動化）</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc29">関連記事</span></h2>
<ul>
<li>SAM版ハンズオン — VS Codeでコマンド数本デプロイ</li>
</ul>

<a rel="noopener" href="https://caymezon.com/aws-handson-eventbridge-lambda-batch/" title="AWSハンズオン - EventBridge + LambdaでCronバッチを自動実行しよう【SAM版 / Windows対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-eventbridge-lambda-batch-featured-55250a-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-eventbridge-lambda-batch-featured-55250a-160x90.jpg 160w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-eventbridge-lambda-batch-featured-55250a-120x68.jpg 120w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-eventbridge-lambda-batch-featured-55250a-320x180.jpg 320w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-eventbridge-lambda-batch-featured-55250a-376x212.jpg 376w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AWSハンズオン - EventBridge + LambdaでCronバッチを自動実行しよう【SAM版 / Windows対応】</div><div class="blogcard-snippet internal-blogcard-snippet">はじめに「定期的にデータを処理したい」「夜中に自動でバッチを動かしたい」と思ったことはありませんか？AWSには、定期実行のための仕組みが標準で備わっています。Amazon EventBridgeのスケジュール機能を使えば、Linuxのcro...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://caymezon.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">caymezon.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.02.22</div></div></div></div></a>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-eventbridge-lambda-batch/">AWSコンソールだけでEventBridge + Lambda定期バッチを構築する手順【SAM版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-eventbridge-lambda-batch/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSコンソールだけでメモアプリAPIを構築する手順【Lambda＋API Gateway＋DynamoDB / SAMとの比較付き】</title>
		<link>https://caymezon.com/aws-handson-console-lambda-apigateway-dynamodb/</link>
					<comments>https://caymezon.com/aws-handson-console-lambda-apigateway-dynamodb/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 11:13:34 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[API Gateway]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[DynamoDB]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20175</guid>

					<description><![CDATA[<p>目次 はじめにSAM vs コンソール：どれだけ違うか構築するもの全体の作業順序① DynamoDB テーブル作成設定値② IAM ロール作成（Lambda実行用）2-1. 信頼ポリシーの設定2-2. 許可ポリシーのアタ [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-lambda-apigateway-dynamodb/">AWSコンソールだけでメモアプリAPIを構築する手順【Lambda＋API Gateway＋DynamoDB / SAMとの比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-18" checked><label class="toc-title" for="toc-checkbox-18">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">構築するもの</a></li><li><a href="#toc4" tabindex="0">全体の作業順序</a></li><li><a href="#toc5" tabindex="0">① DynamoDB テーブル作成</a><ol><li><a href="#toc6" tabindex="0">設定値</a></li></ol></li><li><a href="#toc7" tabindex="0">② IAM ロール作成（Lambda実行用）</a><ol><li><a href="#toc8" tabindex="0">2-1. 信頼ポリシーの設定</a></li><li><a href="#toc9" tabindex="0">2-2. 許可ポリシーのアタッチ（CloudWatch Logs 用）</a></li><li><a href="#toc10" tabindex="0">2-3. ロール名を設定して作成</a></li><li><a href="#toc11" tabindex="0">2-4. DynamoDB CRUD 権限をインラインポリシーで追加</a></li></ol></li><li><a href="#toc12" tabindex="0">③ Lambda 関数作成</a><ol><li><a href="#toc13" tabindex="0">3-1. Lambdaコードをzipファイルに圧縮する（ローカル作業）</a></li><li><a href="#toc14" tabindex="0">3-2. Lambda 関数の作成</a></li><li><a href="#toc15" tabindex="0">3-3. コードのアップロード</a></li><li><a href="#toc16" tabindex="0">3-4. ハンドラーの設定</a></li><li><a href="#toc17" tabindex="0">3-5. 環境変数の設定</a></li><li><a href="#toc18" tabindex="0">3-6. タイムアウトの設定</a></li></ol></li><li><a href="#toc19" tabindex="0">④ API Gateway 作成・設定・デプロイ</a><ol><li><a href="#toc20" tabindex="0">4-1. REST API の作成</a></li><li><a href="#toc21" tabindex="0">4-2. リソース /memos の作成</a></li><li><a href="#toc22" tabindex="0">4-3. POST /memos メソッドの作成</a></li><li><a href="#toc23" tabindex="0">4-4. GET /memos メソッドの作成</a></li><li><a href="#toc24" tabindex="0">4-5. リソース /memos/{id} の作成</a></li><li><a href="#toc25" tabindex="0">4-6. GET /memos/{id} メソッドの作成</a></li><li><a href="#toc26" tabindex="0">4-7. PUT /memos/{id} メソッドの作成</a></li><li><a href="#toc27" tabindex="0">4-8. DELETE /memos/{id} メソッドの作成</a></li><li><a href="#toc28" tabindex="0">4-9. API のデプロイ</a></li></ol></li><li><a href="#toc29" tabindex="0">⑤ Lambda に API Gateway からの実行許可を確認・付与</a></li><li><a href="#toc30" tabindex="0">テスト（CMDでの動作確認）</a><ol><li><a href="#toc31" tabindex="0">POST /memos — メモを作成する</a></li><li><a href="#toc32" tabindex="0">GET /memos — メモ一覧を取得する</a></li><li><a href="#toc33" tabindex="0">GET /memos/{id} — メモ1件を取得する</a></li><li><a href="#toc34" tabindex="0">PUT /memos/{id} — メモを更新する</a></li><li><a href="#toc35" tabindex="0">DELETE /memos/{id} — メモを削除する</a></li></ol></li><li><a href="#toc36" tabindex="0">⑥ リソースの削除（コンソール）</a><ol><li><a href="#toc37" tabindex="0">1. API Gateway を削除する</a></li><li><a href="#toc38" tabindex="0">2. Lambda を削除する</a></li><li><a href="#toc39" tabindex="0">3. IAM ロールを削除する</a></li><li><a href="#toc40" tabindex="0">4. DynamoDB テーブルを削除する</a></li></ol></li><li><a href="#toc41" tabindex="0">まとめ</a><ol><li><a href="#toc42" tabindex="0">今回の手順で確認したこと</a></li><li><a href="#toc43" tabindex="0">コンソール操作で学べたこと</a></li><li><a href="#toc44" tabindex="0">どちらを使うべきか</a></li></ol></li><li><a href="#toc45" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>この記事は、<a href="https://caymezon.com/aws-handson-lambda-apigateway-dynamodb-memo-api/">SAM版ハンズオン記事</a>の比較版です。</p>
<p>SAM版ではコマンド数本でインフラが完成しましたが、<strong>「その裏で何が起きているのか？」「SAMを使わない場合はどれだけ手間がかかるのか？」</strong> を実感してもらうために、全く同じメモアプリAPIをAWSコンソールのみで手作業で構築する手順を詳細に解説します。</p>
<p><strong>この記事を読むとわかること：</strong></p>
<ul>
<li>AWS各サービス（DynamoDB・IAM・Lambda・API Gateway）を個別に設定する流れ</li>
<li>SAMが裏側で自動処理していること（IAMロール・API Gatewayルーティング・権限付与など）</li>
<li>SAMとコンソール手動操作、それぞれの使いどころ</li>
</ul>
<hr>
<h2><span id="toc2">SAM vs コンソール：どれだけ違うか</span></h2>
<p>まず差分を数字で確認します。</p>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>操作ステップ数</strong></td>
<td>約5ステップ</td>
<td><strong>約50〜60クリック</strong></td>
</tr>
<tr>
<td><strong>所要時間</strong></td>
<td>5〜10分</td>
<td><strong>30〜60分</strong></td>
</tr>
<tr>
<td><strong>ミスのリスク</strong></td>
<td>低い（テンプレート通り）</td>
<td><strong>高い</strong>（クリック漏れ・設定誤り）</td>
</tr>
<tr>
<td><strong>再現性</strong></td>
<td>完全（同じ結果が保証）</td>
<td><strong>低い</strong>（毎回手作業）</td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td><code>sam delete</code> 1コマンド</td>
<td><strong>4サービスを個別に手動削除</strong></td>
</tr>
<tr>
<td><strong>コード管理</strong></td>
<td>Git で管理可能</td>
<td><strong>管理不可</strong>（画面操作は記録されない）</td>
</tr>
<tr>
<td><strong>環境の複製</strong></td>
<td><code>sam deploy</code> だけ</td>
<td><strong>最初から全手順繰り返し</strong></td>
</tr>
</tbody>
</table>
<p>「それでもコンソール操作を知っておく価値はあるか？」という問いに対して、答えは <strong>Yes</strong> です。</p>
<p><strong>コンソール操作が特に有効な場面：</strong></p>
<ul>
<li><strong>障害調査</strong> — 実際にどのリソースがどう設定されているか目視確認する</li>
<li><strong>SAMのデバッグ</strong> — SAMでデプロイしたリソースをコンソールで確認・修正する</li>
<li><strong>初学習</strong> — 各サービスの設定項目を理解するための最初の一歩</li>
</ul>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc3">構築するもの</span></h2>
<p>SAM版と全く同じ構成・機能のAPIを構築します。</p>
<pre><code class="language-plaintext">インターネット
  ↓ HTTPS
API Gateway（Prod ステージ）
  ↓ Lambdaプロキシ統合
Lambda（MemoFunction / Python 3.12）
  ↓ boto3
DynamoDB（memo-api-dynamodb-stack-Memos テーブル）</code></pre>
<table>
<thead>
<tr>
<th>メソッド</th>
<th>パス</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>/memos</td>
<td>メモ作成</td>
</tr>
<tr>
<td>GET</td>
<td>/memos</td>
<td>メモ一覧取得</td>
</tr>
<tr>
<td>GET</td>
<td>/memos/{id}</td>
<td>メモ1件取得</td>
</tr>
<tr>
<td>PUT</td>
<td>/memos/{id}</td>
<td>メモ更新</td>
</tr>
<tr>
<td>DELETE</td>
<td>/memos/{id}</td>
<td>メモ削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">全体の作業順序</span></h2>
<p>SAMは依存関係を自動解決しますが、コンソールでは<strong>依存する順番通りに</strong>作成する必要があります。</p>
<pre><code class="language-plaintext">① DynamoDB テーブル作成
      ↓（テーブル名が必要）
② IAM ロール作成（Lambda実行用）
      ↓（ロールARNが必要）
③ Lambda 関数作成（zipアップロード・環境変数設定）
      ↓（関数ARNが必要）
④ API Gateway 作成・リソース・メソッド設定・デプロイ
      ↓
⑤ Lambda に API Gateway からの実行許可を確認・付与</code></pre>
<p>この順序を守らないと、設定画面で参照先リソースが見つからずエラーになります。</p>
<hr>
<h2><span id="toc5">① DynamoDB テーブル作成</span></h2>
<p><strong>AWSコンソール → DynamoDB → テーブル → 「テーブルの作成」</strong></p>
<p><!-- ![DynamoDB テーブル作成画面](images/dynamodb-create-table.jpg) --></p>
<h3><span id="toc6">設定値</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>テーブル名</td>
<td><code>memo-api-dynamodb-stack-Memos</code></td>
</tr>
<tr>
<td>パーティションキー</td>
<td><code>memoId</code>（タイプ: 文字列）</td>
</tr>
<tr>
<td>テーブル設定</td>
<td>「設定のカスタマイズ」を選択</td>
</tr>
<tr>
<td>キャパシティーモード</td>
<td><strong>オンデマンド</strong>（PAY_PER_REQUEST）</td>
</tr>
<tr>
<td>その他</td>
<td>デフォルトのまま</td>
</tr>
</tbody>
</table>
<p>「テーブルの作成」ボタンをクリック。作成完了まで数十秒待ちます。</p>
<p><strong>▶ 控えておく情報：</strong></p>
<ul>
<li>テーブル名: <code>memo-api-dynamodb-stack-Memos</code></li>
</ul>
<blockquote>
<p><strong>キャパシティーモードはオンデマンドを選ぶ理由：</strong><br />デフォルトの「プロビジョンド」はあらかじめ読み書き容量を指定して課金されます。学習目的ではアクセスがない時間も課金されてしまうため、アクセスがあった分だけ課金される「オンデマンド」を選択します。SAMの <code>BillingMode: PAY_PER_REQUEST</code> に相当します。</p>
</blockquote>
<hr>
<h2><span id="toc7">② IAM ロール作成（Lambda実行用）</span></h2>
<p><strong>AWSコンソール → IAM → ロール → 「ロールを作成」</strong></p>
<p>SAMでは <code>DynamoDBCrudPolicy</code> を1行書くだけで自動生成されていたIAMロールを、ここでは手動で作成します。</p>
<h3><span id="toc8">2-1. 信頼ポリシーの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>信頼されたエンティティタイプ</td>
<td><strong>AWS のサービス</strong></td>
</tr>
<tr>
<td>ユースケース</td>
<td><strong>Lambda</strong></td>
</tr>
</tbody>
</table>
<p>「次へ」をクリックします。</p>
<h3><span id="toc9">2-2. 許可ポリシーのアタッチ（CloudWatch Logs 用）</span></h3>
<p>検索ボックスに <code>AWSLambdaBasicExecutionRole</code> と入力してチェックを入れます。</p>
<p>→ 「次へ」</p>
<h3><span id="toc10">2-3. ロール名を設定して作成</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ロール名</td>
<td><code>memo-api-lambda-role</code></td>
</tr>
</tbody>
</table>
<p>「ロールを作成」をクリックします。</p>
<h3><span id="toc11">2-4. DynamoDB CRUD 権限をインラインポリシーで追加</span></h3>
<p>作成したロール <code>memo-api-lambda-role</code> を開き → 「許可を追加」→「インラインポリシーを作成」→「JSON」タブ を選択して以下を貼り付けます：</p>
<pre><code class="language-json">{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:UpdateItem",
        "dynamodb:DeleteItem",
        "dynamodb:Scan",
        "dynamodb:Query"
      ],
      "Resource": "arn:aws:dynamodb:ap-northeast-1:*:table/memo-api-dynamodb-stack-Memos"
    }
  ]
}</code></pre>
<p>ポリシー名（例: <code>DynamoDBCrudPolicy-Memos</code>）を入力して「ポリシーの作成」をクリックします。</p>
<p><strong>▶ 控えておく情報：</strong></p>
<ul>
<li>ロール ARN（例: <code>arn:aws:iam::123456789012:role/memo-api-lambda-role</code>）</li>
</ul>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMの <code>DynamoDBCrudPolicy</code> は必要な6つのDynamoDBアクションとCloudWatch Logs権限を1行で自動付与します。コンソールでは「管理ポリシーのアタッチ」と「インラインポリシーの作成」の2手順が必要です。</p>
</blockquote>
<hr>
<h2><span id="toc12">③ Lambda 関数作成</span></h2>
<h3><span id="toc13">3-1. Lambdaコードをzipファイルに圧縮する（ローカル作業）</span></h3>
<p><code>src/app.py</code> と <code>src/requirements.txt</code> を zip 圧縮します。</p>
<p><strong>Windowsエクスプローラーでの操作：</strong></p>
<ol>
<li><code>src/</code> フォルダを開く</li>
<li><code>app.py</code> と <code>requirements.txt</code> を両方選択</li>
<li>右クリック → 「ZIPファイルに圧縮」</li>
<li><code>lambda.zip</code> という名前で保存</li>
</ol>
<blockquote>
<p><strong>【注意】フォルダごとではなくファイルを直接zipする</strong></p>
<p><code>src/</code> フォルダ自体を右クリックしてzipすると、中身のパスが <code>src/app.py</code> になります。LambdaはCodeUri直下に <code>app.py</code> があることを期待するため、<strong>フォルダの中身のファイルを選択してからzip</strong>してください。フォルダごと圧縮するとパスが変わって <code>Handler: app.lambda_handler</code> が見つからずエラーになります。</p>
</blockquote>
<p>コードの内容は<a href="https://caymezon.com/aws-handson-lambda-apigateway-dynamodb-memo-api/#step3">SAM版ハンズオン記事のStep 3</a>を参照してください。</p>
<h3><span id="toc14">3-2. Lambda 関数の作成</span></h3>
<p><strong>AWSコンソール → Lambda → 関数 → 「関数の作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>MemoFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「既存のロールを使用する」→ <code>memo-api-lambda-role</code> を選択</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリックします。</p>
<h3><span id="toc15">3-3. コードのアップロード</span></h3>
<p>関数ページ → 「コードソース」セクション → 「アップロード元」→「.zip ファイル」→ <code>lambda.zip</code> を選択 → 「保存」</p>
<h3><span id="toc16">3-4. ハンドラーの設定</span></h3>
<p>「コード」タブ → 画面を下にスクロール → 「ランタイム設定」→「編集」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ハンドラ</td>
<td><code>app.lambda_handler</code></td>
</tr>
</tbody>
</table>
<p>「保存」をクリックします。</p>
<blockquote>
<p><strong>ハンドラーを変更する理由：</strong><br />Lambda のデフォルトハンドラーは <code>lambda_function.lambda_handler</code>（<code>lambda_function.py</code> を参照）。本ハンズオンのコードは <code>app.py</code> なので、変更しないと <code>No module named &#39;lambda_function&#39;</code> エラーになります。</p>
</blockquote>
<h3><span id="toc17">3-5. 環境変数の設定</span></h3>
<p>「設定」タブ → 「環境変数」→「編集」→「環境変数を追加」</p>
<table>
<thead>
<tr>
<th>キー</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>TABLE_NAME</code></td>
<td><code>memo-api-dynamodb-stack-Memos</code></td>
</tr>
</tbody>
</table>
<p>「保存」をクリックします。</p>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMでは <code>template.yaml</code> の <code>Environment.Variables.TABLE_NAME: !Ref MemosTable</code> が自動でテーブル名を解決して設定します。コンソールでは①で作成したテーブル名を手動でコピーして貼り付ける必要があります。</p>
</blockquote>
<h3><span id="toc18">3-6. タイムアウトの設定</span></h3>
<p>「設定」タブ → 「一般設定」→「編集」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>タイムアウト</td>
<td>0分 <strong>30秒</strong></td>
</tr>
<tr>
<td>メモリ</td>
<td>128 MB</td>
</tr>
</tbody>
</table>
<p>「保存」をクリックします。</p>
<p><strong>▶ 控えておく情報：</strong></p>
<ul>
<li>関数 ARN（例: <code>arn:aws:lambda:ap-northeast-1:123456789012:function:MemoFunction</code>）</li>
</ul>
<hr>
<h2><span id="toc19">④ API Gateway 作成・設定・デプロイ</span></h2>
<p>ここが<strong>最も手順が多い</strong>セクションです。5エンドポイント × 複数設定 = 大量のクリック作業になります。SAMが <code>Events:</code> セクションの数行で自動処理していた部分を全て手動で設定します。</p>
<h3><span id="toc20">4-1. REST API の作成</span></h3>
<p><strong>AWSコンソール → API Gateway → 「APIを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>API タイプ</td>
<td><strong>REST API</strong>（「構築」ボタン）</td>
</tr>
<tr>
<td>API 名</td>
<td><code>MemoApi</code></td>
</tr>
<tr>
<td>エンドポイントタイプ</td>
<td>リージョン</td>
</tr>
</tbody>
</table>
<p>「APIを作成」をクリックします。</p>
<h3><span id="toc21">4-2. リソース /memos の作成</span></h3>
<p>「リソース」→「リソースを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソースパス</td>
<td><code>/</code></td>
</tr>
<tr>
<td>リソース名</td>
<td><code>memos</code></td>
</tr>
<tr>
<td>CORS</td>
<td>チェックしない</td>
</tr>
</tbody>
</table>
<p>「リソースを作成」をクリックします。</p>
<h3><span id="toc22">4-3. POST /memos メソッドの作成</span></h3>
<p><code>/memos</code> リソースを選択 →「メソッドを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メソッドタイプ</td>
<td><strong>POST</strong></td>
</tr>
<tr>
<td>統合タイプ</td>
<td><strong>Lambda 関数</strong></td>
</tr>
<tr>
<td>Lambda プロキシ統合</td>
<td><strong>オン</strong>（重要）</td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>MemoFunction</code> を選択</td>
</tr>
</tbody>
</table>
<p>「メソッドを作成」をクリックします。</p>
<blockquote>
<p><strong>「Lambda プロキシ統合」をオンにする理由：</strong><br />オンにすると、HTTPリクエスト全体（メソッド・パス・ボディ・ヘッダー）がそのままLambdaの <code>event</code> に渡されます。オフにすると、マッピングテンプレートを別途設定する必要があり手順が大幅に増えます。SAMはデフォルトでプロキシ統合を使用します。</p>
</blockquote>
<h3><span id="toc23">4-4. GET /memos メソッドの作成</span></h3>
<p><code>/memos</code> リソースを選択 →「メソッドを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メソッドタイプ</td>
<td><strong>GET</strong></td>
</tr>
<tr>
<td>統合タイプ</td>
<td>Lambda 関数</td>
</tr>
<tr>
<td>Lambda プロキシ統合</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>MemoFunction</code></td>
</tr>
</tbody>
</table>
<p>「メソッドを作成」をクリックします。</p>
<h3><span id="toc24">4-5. リソース /memos/{id} の作成</span></h3>
<p><code>/memos</code> リソースを選択 →「リソースを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソース名</td>
<td><code>{id}</code></td>
</tr>
</tbody>
</table>
<p>「リソースを作成」をクリックします。</p>
<blockquote>
<p><strong><code>{id}</code> は波括弧ごと入力する</strong><br /><code>{id}</code> と入力することで API Gateway がパスパラメータとして認識し、Lambda の <code>event[&#39;pathParameters&#39;][&#39;id&#39;]</code> で受け取れるようになります。</p>
</blockquote>
<h3><span id="toc25">4-6. GET /memos/{id} メソッドの作成</span></h3>
<p><code>/memos/{id}</code> リソースを選択 →「メソッドを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メソッドタイプ</td>
<td><strong>GET</strong></td>
</tr>
<tr>
<td>統合タイプ</td>
<td>Lambda 関数</td>
</tr>
<tr>
<td>Lambda プロキシ統合</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>MemoFunction</code></td>
</tr>
</tbody>
</table>
<p>「メソッドを作成」をクリックします。</p>
<h3><span id="toc26">4-7. PUT /memos/{id} メソッドの作成</span></h3>
<p><code>/memos/{id}</code> リソースを選択 →「メソッドを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メソッドタイプ</td>
<td><strong>PUT</strong></td>
</tr>
<tr>
<td>統合タイプ</td>
<td>Lambda 関数</td>
</tr>
<tr>
<td>Lambda プロキシ統合</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>MemoFunction</code></td>
</tr>
</tbody>
</table>
<p>「メソッドを作成」をクリックします。</p>
<h3><span id="toc27">4-8. DELETE /memos/{id} メソッドの作成</span></h3>
<p><code>/memos/{id}</code> リソースを選択 →「メソッドを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>メソッドタイプ</td>
<td><strong>DELETE</strong></td>
</tr>
<tr>
<td>統合タイプ</td>
<td>Lambda 関数</td>
</tr>
<tr>
<td>Lambda プロキシ統合</td>
<td><strong>オン</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>MemoFunction</code></td>
</tr>
</tbody>
</table>
<p>「メソッドを作成」をクリックします。</p>
<h3><span id="toc28">4-9. API のデプロイ</span></h3>
<p>「APIをデプロイ」ボタンをクリックします。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ステージ</td>
<td><strong>新しいステージ</strong></td>
</tr>
<tr>
<td>ステージ名</td>
<td><code>Prod</code></td>
</tr>
</tbody>
</table>
<p>「デプロイ」をクリックします。</p>
<p>ステージ画面の「呼び出し URL」に表示されるURLを控えておきます：</p>
<pre><code class="language-plaintext">https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod</code></pre>
<p><strong>▶ 控えておく情報：</strong></p>
<ul>
<li>呼び出し URL（テストで使います）</li>
</ul>
<hr>
<h2><span id="toc29">⑤ Lambda に API Gateway からの実行許可を確認・付与</span></h2>
<p>API GatewayがLambdaを呼び出す権限を確認します。</p>
<p><strong>Lambda プロキシ統合でメソッドを作成した際に「Lambda関数に権限を追加しますか？」という確認ダイアログが表示されて「OK」をクリックした場合は、この手順は自動で完了しています。</strong></p>
<p>もし <code>403 Forbidden</code> エラーが出た場合は、以下の手順で手動付与します：</p>
<p><strong>Lambda → 対象関数 → 「設定」タブ → 「リソースベースのポリシーステートメント」→「追加」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>プリンシパル</td>
<td><code>apigateway.amazonaws.com</code></td>
</tr>
<tr>
<td>ソース ARN</td>
<td><code>arn:aws:execute-api:ap-northeast-1:*:*/Prod/*/*</code></td>
</tr>
<tr>
<td>アクション</td>
<td><code>lambda:InvokeFunction</code></td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc30">テスト（CMDでの動作確認）</span></h2>
<p>テスト手順はSAM版と同じです。コンソールで取得した呼び出し URLを使って実行します。</p>
<pre><code class="language-cmd">set API_URL=https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod</code></pre>
<h3><span id="toc31">POST /memos — メモを作成する</span></h3>
<pre><code class="language-cmd">curl -s -X POST "%API_URL%/memos" -H "Content-Type: application/json" -d "{\"title\":\"初めてのメモ\",\"content\":\"DynamoDBに保存されます\"}"</code></pre>
<p>レスポンス例：</p>
<pre><code class="language-json">{
  "memoId": "6150433b-4834-4cfe-81f5-266d3dad9e57",
  "title": "初めてのメモ",
  "content": "DynamoDBに保存されます",
  "createdAt": "2026-02-20T10:00:00.000000+00:00",
  "updatedAt": "2026-02-20T10:00:00.000000+00:00"
}</code></pre>
<h3><span id="toc32">GET /memos — メモ一覧を取得する</span></h3>
<pre><code class="language-cmd">curl -s "%API_URL%/memos"</code></pre>
<h3><span id="toc33">GET /memos/{id} — メモ1件を取得する</span></h3>
<pre><code class="language-cmd">curl -s "%API_URL%/memos/6150433b-4834-4cfe-81f5-266d3dad9e57"</code></pre>
<h3><span id="toc34">PUT /memos/{id} — メモを更新する</span></h3>
<pre><code class="language-cmd">curl -s -X PUT "%API_URL%/memos/6150433b-4834-4cfe-81f5-266d3dad9e57" -H "Content-Type: application/json" -d "{\"title\":\"更新後タイトル\",\"content\":\"内容も更新しました\"}"</code></pre>
<h3><span id="toc35">DELETE /memos/{id} — メモを削除する</span></h3>
<pre><code class="language-cmd">curl -s -X DELETE "%API_URL%/memos/6150433b-4834-4cfe-81f5-266d3dad9e57"</code></pre>
<blockquote>
<p>CMDでのテストの詳細な注意点（変数未設定によるCloudFront 400エラーなど）は<a href="https://caymezon.com/aws-handson-lambda-apigateway-dynamodb-memo-api/#step9">SAM版ハンズオン記事のStep 9</a>を参照してください。</p>
</blockquote>
<hr>
<h2><span id="toc36">⑥ リソースの削除（コンソール）</span></h2>
<p><strong>削除する順番が重要です（依存関係の逆順）。</strong> SAMなら <code>sam delete</code> 1コマンドで完了するところを、4サービスを個別に手動削除します。</p>
<h3><span id="toc37">1. API Gateway を削除する</span></h3>
<p><strong>API Gateway → <code>MemoApi</code> を選択 → 「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<h3><span id="toc38">2. Lambda を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>MemoFunction</code> を選択 → 「アクション」→「削除」→ 確認テキストを入力 → 「削除」</strong></p>
<h3><span id="toc39">3. IAM ロールを削除する</span></h3>
<p><strong>IAM → ロール → <code>memo-api-lambda-role</code> を選択 → 「削除」→ ロール名を入力 → 「削除」</strong></p>
<h3><span id="toc40">4. DynamoDB テーブルを削除する</span></h3>
<p><strong>DynamoDB → テーブル → <code>memo-api-dynamodb-stack-Memos</code> → 「削除」→ テーブル名を入力して確認 → 「削除」</strong></p>
<blockquote>
<p><strong>SAMとの差分：</strong> SAMの <code>sam delete</code> は CloudFormation スタックを削除することで、S3・Lambda・API Gateway・DynamoDB・IAMロールを一括で削除します。コンソールでは依存関係の逆順に4サービスを個別に削除する必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc41">まとめ</span></h2>
<h3><span id="toc42">今回の手順で確認したこと</span></h3>
<p>コンソール操作を通じて、SAMが裏側で自動処理している内容が明確になりました：</p>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>BillingMode: PAY_PER_REQUEST</code></td>
<td>DynamoDB作成時に「オンデマンド」を選択</td>
</tr>
<tr>
<td><code>DynamoDBCrudPolicy</code></td>
<td>IAMロール作成 + インラインポリシーのJSON作成</td>
</tr>
<tr>
<td><code>Handler: app.lambda_handler</code></td>
<td>Lambda作成 + zipアップロード + 環境変数設定</td>
</tr>
<tr>
<td><code>Events: Type: Api</code></td>
<td>API Gateway作成 + リソース5個 + メソッド5個 + デプロイ</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>4サービスを依存関係の逆順に個別削除</td>
</tr>
</tbody>
</table>
<h3><span id="toc43">コンソール操作で学べたこと</span></h3>
<ul>
<li><strong>IAMロールの構造</strong> — 信頼ポリシー（誰がロールを使えるか）とアクセス許可ポリシー（何ができるか）の2層構造</li>
<li><strong>API Gatewayの仕組み</strong> — リソース（パス）とメソッド（HTTPメソッド）を組み合わせてエンドポイントを定義する</li>
<li><strong>Lambdaプロキシ統合</strong> — リクエスト全体をeventとしてLambdaに渡す仕組み</li>
<li><strong>リソース間の依存関係</strong> — 作成順序・削除順序が決まっている理由</li>
</ul>
<h3><span id="toc44">どちらを使うべきか</span></h3>
<table>
<thead>
<tr>
<th>シーン</th>
<th>推奨</th>
</tr>
</thead>
<tbody>
<tr>
<td>本番環境・チーム開発</td>
<td><strong>SAM</strong>（再現性・Git管理・速度）</td>
</tr>
<tr>
<td>AWSを初めて学ぶ</td>
<td><strong>コンソール</strong>（各設定の意味を理解する）</td>
</tr>
<tr>
<td>構築済みリソースの確認・デバッグ</td>
<td><strong>コンソール</strong>（目視確認）</td>
</tr>
<tr>
<td>同じ構成を繰り返しデプロイ</td>
<td><strong>SAM</strong>（ミスゼロ・自動化）</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc45">関連記事</span></h2>
<ul>
<li>SAM版ハンズオン — VS Codeで全自動デプロイ</li>
</ul>

<a rel="noopener" href="https://caymezon.com/aws-handson-lambda-apigateway-dynamodb-memo-api/" title="AWS初心者ハンズオン - Lambda＋API Gateway＋DynamoDBでメモアプリAPIを作ろう【Windows対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-lambda-apigateway-dynamodb-memo-api-featured-1b1cce-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://caymezon.com/wp-content/uploads/2026/02/aws-handson-lambda-apigateway-dynamodb-memo-api-featured-1b1cce-160x90.jpg 160w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-lambda-apigateway-dynamodb-memo-api-featured-1b1cce-120x68.jpg 120w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-lambda-apigateway-dynamodb-memo-api-featured-1b1cce-320x180.jpg 320w, https://caymezon.com/wp-content/uploads/2026/02/aws-handson-lambda-apigateway-dynamodb-memo-api-featured-1b1cce-376x212.jpg 376w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AWS初心者ハンズオン - Lambda＋API Gateway＋DynamoDBでメモアプリAPIを作ろう【Windows対応】</div><div class="blogcard-snippet internal-blogcard-snippet">はじめに「AWSのサーバーレスを試してみたい」「Lambda・API Gateway・DynamoDBを組み合わせて何か作ってみたい」と思っていませんか？この記事では、AWS SAM（Serverless Application Model...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://caymezon.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">caymezon.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.02.20</div></div></div></div></a>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-lambda-apigateway-dynamodb/">AWSコンソールだけでメモアプリAPIを構築する手順【Lambda＋API Gateway＋DynamoDB / SAMとの比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-lambda-apigateway-dynamodb/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
