在介紹IAM之前,想先分享一個雲端的重要觀念,因為雲端服務只要牽涉到多個資源互相呼叫,就一定會碰到一個問題:「這個身份,有沒有資格做這件事?」 AWS 的答案很直接——預設拒絕一切。任何服務要碰另一個服務,都得先明確被授權,而負責管理這整套授權規則的機制,就是 IAM(Identity and Access Management)。
回到這個專案上,上一篇提到 Lambda 除了「被叫醒執行」,很多時候還要「呼叫別的 AWS 服務」——這裡最重要的就是呼叫 Bedrock 做 AI 分析,也就是讓我們用自由文字輸入的飲食自述可以餵給AI,而這正是需要 IAM 出場的地方。
用「大樓門禁系統」理解 IAM 的四個角色
IAM 有四個基本元件,可以直接對應到熟悉的門禁概念:
| IAM 元件 | 門禁比喻 | 白話意思 |
|---|---|---|
| User(使用者) | 一張員工證 | 給「人」用的身份,例如你自己在終端機操作 AWS 的帳號 |
| Group(群組) | 部門 | 把一群 User 歸在一起統一授權 |
| Policy(策略) | 門禁清單 | 一份 JSON,白紙黑字寫「允許/拒絕做哪些事」 |
| Role(角色) | 訪客證 | 不是給人用的,是借給服務用的臨時身份 |
這個專案主要會碰到頭尾兩層——一個是部署時用的 IAM User,另一個是執行時借用的 IAM Role,可以把它們想成蒖房子跟房子啟用後的兩個階段:
IAM User(部署時):
就是後面會提到的 ai-diet-copilot-deploy。在本機打 sam deploy 的那一刻,SAM CLI 拿的就是這個 User 的 Access Key——像蓋房子的工班,只有「動工」的當下才出現,把 Lambda、API Gateway 這些資源實際建出來。
IAM Role(執行時):
房子蓋好之後,每次使用者真的送出請求、Lambda 被叫醒執行的那一刻,才會自動借用這張「門禁卡」去呼叫 Bedrock、讀寫 S3,用完就放下,下次再借一次。這不是你手動操作的身份,而是 AWS 在背後自動幫 Lambda「借用」的。
簡單說,一個是「把東西蓋出來」的身份,一個是「蓋好的東西在運作時」的身份,兩者完全分開,權限也要分開檢查,不會互相影響。
Role 最容易搞混的地方:它其實有「兩面」
Role 之所以常常讓人卡關,是因為它同時回答兩個不同的問題,而且是分開設定的:
換句話說,光是「這個 Role 有沒有權限做 X」還不夠,得先確認「Lambda 有沒有資格借用這個 Role」。這兩件事都要對,Lambda 才真的拿得到、也用得了這張證。
理想中的 IAM:把權限切成一塊一塊
一開始我對 IAM 的期待很簡單:Lambda 執行時借用的 Role,應該只給它「真的會用到」的權限,例如只開放「呼叫 Bedrock」跟「讀寫某個 S3 bucket」,其他一律不給。在 template.yaml 裡,就是靠 Policies 這個欄位去指定這些明確的授權;SAM 會自動處理「這個 Role 信任 Lambda 服務」這一半,我只要專心寫「這個 Role 能做什麼」。
踩到的例外:不是所有服務都「一給權限就能用」
呼叫 Bedrock 上的 Anthropic 模型,除了 IAM Policy 要給 bedrock:InvokeModel 之外,因為這個模型是透過 AWS Marketplace 分銷的,帳號本身還要額外完成一次模型的「訂閱」流程,跟一般「給權限就能用」的服務不太一樣。這是比較少見的特例,之後 Day16 講 Bedrock 時會再細講。
實際檢查一輪:User 跟 Role,一個沒做到、一個做到了
上面講的是「理想上」該怎麼設定,寫完這篇之後,我把這個專案的 User 跟 Role 都回頭認真查了一次,兩邊的結果完全不一樣。
① 部署用的 User:開得跟 Root 差不多大
點進這個帳號的 Permissions policies,掛的是 AdministratorAccess
點進AdministratorAccess裡面的權限
也就是說,我確實有乖乖用 IAM 帳號做部署,沒有直接把 root 的金鑰丟出去用——這件事本身是對的。但這個 IAM 帳號被我圖方便掛了 AdministratorAccess,能做的事其實跟 root 差不多多,並沒有真的做到「只給用得到的權限」。(自我檢討QQ)
② 執行用的 Role:反而是真的照最小權限做的
再去查 Lambda 執行時借用的那個 Role(backend-NutritionPlanFunctionRole-cMZimlH0Oad4),結果完全相反——掛的權限只有 Bedrock 的 bedrock:InvokeModel、bedrock:InvokeModelWithResponseStream,而且限定在特定的 resource(inference-profile/* 跟 foundation-model/anthropic.claude-*),不是整個 Bedrock 服務都能動。

這個 Role 沒有多要任何用不到的權限——template.yaml 裡寫的 Policies 是真的照著最小權限的精神做出來的。
這樣算不算有做到 IAM 該做的事?
把兩邊放在一起看,答案很清楚:執行時借用的 Role 做對了,部署時用的 User 沒做到。
因為這是我自己一個人的 side project,沒有其他人共用這把 key,User 權限開大一點,短期內風險確實比多人團隊低很多。但「風險比較低」不等於「沒有風險」——這組 key 只要不小心外洩(例如誤 commit 上 GitHub),別人拿到後能做的事就是整個帳號的管理員,而不是被限制在「只能動 Lambda 跟 Bedrock」。之後如果要補,就是把這個 user 的 AdministratorAccess 換成只給 SAM 部署實際會用到的那幾個服務(Lambda、API Gateway、相關 IAM Role、S3、Bedrock~ 牽一髮動全身)。
理想上的 IAM,應該是「這個身份只能做它需要做的事」;但這次我自己的專案沒有真的做到——圖方便掛了大權限,跟 root 只差在「沒有直接用 root 的鑰匙」這件事。至少記得這一條底線:部署用的身份,最好跟平常登入看畫面的身份分開,這次雖然權限沒切乾淨,但這一步有守住,之後想補強也還有路可以走。這個血淋淋的經驗也提醒我之後IAM設定要再切分的更清楚。
下一篇要處理的是另一個問題:就算權限都對了,Lambda 真的在雲端跑起來之後,出了狀況要去哪裡看?