IAMと最小権限|クラウドの基本・IAM・責任
このページはプロモーション(広告)を含みます。
クラウドの基本・IAM・責任(中級・読む35分+演習40分)
この授業のゴール
- IAMポリシー(JSON/YAML)の各要素(主体・効果・操作・資源)を読み、ある要求が許可されるか拒否されるかを説明できる
- 「明示的な拒否が最優先、どれにも当たらなければ拒否」という評価規則をPythonで実装し、具体的な要求で検査できる
- 役割(運用・利用者・管理者)ごとに、仕事に必要な操作だけを許すポリシーを設計できる
- 人のアカウントとアプリ用の主体(サービスアカウント)を分け、アプリの利用者の権限とクラウドの権限を混同しない設計を説明できる
仕事でどう使うか
クラウドの事故で特に多いのが権限の与えすぎです。「動かないから管理者権限を付けた」設定が残り、鍵が漏れたときに全資源が消される・請求が膨らむ、といった被害につながります。IAM(Identity and Access Management:誰がどの資源に何をできるかの管理)は、クラウドを使う全員が触れる基本です。
| 路線 | この授業の使いどころ |
|---|---|
| DS | 分析者には「分析用の保存場所の読み取りだけ」を申請し、本番DBの削除権限を持たない |
| ML | 学習ジョブ用の主体に「学習データの読み取り+モデル保存先への書き込み」だけを与える |
| DX | 委託先・運用・利用部門の役割表を作り、権限の申請・承認・棚卸しの手順を決める |
| RS | 共同研究者に、期限付きでデータの読み取りだけを渡し、終了時に取り消す |
この授業のポリシーは、主要なクラウドの考え方をもとにした教材用の簡略形式です。実際のサービスでは、操作名・資源の書き方・評価の細部が提供者ごとに異なり、変わり得ます。実環境では公式の説明で確認してください。評価はすべてPythonによる模擬で、実アカウントは使いません。
前提
次の言葉を使います。不安があれば戻ってください。
- 認証(本人であることの確認)と認可(何を許すかの決定)、トークン → 「認証・認可・レート制限」(有料版)
- 最小権限の原則、ロール、棚卸し → 「最小権限」(有料版)
- オブジェクト保存とバケット → 計算・保存・ネットワーク
- JSON(データを
{"キー": 値}の形で書く形式)→ 「JSONとスキーマ」(有料版)
Pythonでは、辞書とリスト、for 文、any() を使います。fnmatchcase(文字列, パターン) は、* を「任意の文字列」として一致を判定する標準ライブラリの関数です(戻り値は True/False)。
身近な状況:教材配信係に「管理者」を付けてしまう
架空の学習サービス「あおば学習」では、教材のWebページ(静的サイト:あらかじめ作ったHTMLや画像を配るだけのサイト)をオブジェクト保存に置き、配信網(CDN:Content Delivery Network。利用者の近くにコピーを置いて速く配る仕組み)で配っています。
新しく入った教材配信係のAさんが、教材を更新できないと相談してきました。急いでいた管理者は、Aさんに管理者権限(すべての資源に、すべての操作)を付けました。
翌月、次のことが起きました。
- Aさんがテストのつもりで作った保存場所が、誰でも読める公開設定のまま残っていた。
- Aさんのアクセスキー(プログラムからの認証に使う秘密の文字列)を誤って公開リポジトリに載せてしまい、第三者に計算資源を大量に作られた。請求額が急増し、顧客DBの削除も可能な状態だった。
Aさんの仕事に必要だったのは、たった3つです。
- 教材の保存場所
edu-siteのファイルを読む・書く・一覧する - 配信網のキャッシュ(古いコピー)を更新する
- それ以外は何もしない(とくに請求設定・公開設定・DBの削除は絶対にしない)
この授業では、これをポリシーとして書き、模擬の評価で「本当にそれしかできないか」を確かめます。
直感的な説明:社員証と、部屋ごとの許可リスト
オフィスビルの入館管理にたとえます。
- 主体(principal)は「誰か」:社員証を持つ人、または来訪者用の一時入館証。人だけでなく、プログラム(アプリや定期ジョブ)にも専用の入館証を発行します。
- ポリシーは「許可リスト」:「この人は、3階の資料室に入って、資料を読んでよい」のように、どの部屋(資源)で、何をしてよいか(操作)を書きます。
- ロールは「役職ごとの許可リストの束」:「配信係」「分析者」のような役割に許可をまとめ、人をその役割に割り当てます。異動したら役割を外すだけで済みます。
門番のルールは2つだけです。
- リストにないことは、させない(既定拒否)。
- 「禁止」と書かれたことは、他の許可があっても、させない(明示的な拒否が最優先)。
注意:アプリの利用者(あおば学習にログインする受講者)は、この入館管理の対象ではありません。受講者が「自分の成績だけ見られる」ことはアプリの中で管理し(「認証・認可・レート制限」(有料版))、アプリ自体は「アプリ用の入館証」1枚で必要な資源にアクセスします。受講者ごとにクラウドの権限を配ったり、管理者本人の入館証をアプリに埋め込んだりしてはいけません。
正確な定義:ポリシーの要素と評価規則
- 主体(principal):要求を出す者。ユーザー(人)、グループ(ユーザーの集まり)、ロール(一時的に引き受ける権限の束)、サービスアカウント(アプリやジョブ用の、人ではない主体)。
- ポリシー(policy):1つ以上の文(statement)の集まり。各文は次の要素を持ちます。
| 要素 | 意味 | 例 |
|---|---|---|
| Effect(効果) | 許可(Allow)か拒否(Deny)か | "Allow" |
| Action(操作) | 何をするか。サービス:動詞 の形 |
"storage:GetObject" |
| Resource(資源) | どの対象に | "bucket/edu-site/*" |
| Condition(条件・任意) | いつ・どこからなら | 送信元のアドレス範囲、時刻、多要素認証の有無 |
*(ワイルドカード)は「任意の文字列」。storage:*は保存サービスの全操作、*単独はすべて。この模擬では*は/も含めて一致します。- 評価規則(この教材の模擬。主要なクラウドで一般的な考え方):
1. 要求(主体・操作・資源)に当てはまる文を集める。
2. 当てはまる文に Deny が1つでもあれば拒否(明示的な拒否)。
3. Deny がなく、Allow が1つ以上あれば許可。
4. どれにも当てはまらなければ拒否(既定拒否、暗黙の拒否)。 - 最小権限の原則:仕事に必要な操作だけを、必要な資源に対して、必要な期間だけ許す。
教材配信係のポリシー(JSON):
{
"Version": "edu-1",
"Statement": [
{"Sid": "SiteReadWrite", "Effect": "Allow",
"Action": ["storage:GetObject", "storage:PutObject", "storage:ListObjects"],
"Resource": ["bucket/edu-site/*"]},
{"Sid": "CacheRefresh", "Effect": "Allow",
"Action": ["cdn:InvalidateCache"], "Resource": ["cdn/edu-site"]},
{"Sid": "NeverBillingOrPublicChange", "Effect": "Deny",
"Action": ["billing:*", "storage:PutBucketPolicy", "db:Delete*"],
"Resource": ["*"]}
]
}
同じ内容はYAML(インデントで構造を表す書式。構成ファイルでよく使う)でも書けます。最初の文だけを示します。
Statement:
- Sid: SiteReadWrite
Effect: Allow
Action: [storage:GetObject, storage:PutObject, storage:ListObjects]
Resource: [bucket/edu-site/*]
Sid(Statement ID)は文の名札で、何のための文かを人が読めるようにします。storage:PutBucketPolicy は保存場所の公開範囲を変える操作として扱っています。
段階付き例題:要求ごとに許可・拒否をたどる
問題:上の配信係ポリシーで、次の4つの要求は許可されるか。
| # | 操作 | 資源 |
|---|---|---|
| 1 | storage:PutObject | bucket/edu-site/lesson1.html |
| 2 | storage:DeleteObject | bucket/edu-site/lesson1.html |
| 3 | storage:PutBucketPolicy | bucket/edu-site |
| 4 | storage:GetObject | bucket/hr-data/salary.csv |
ステップ1(要求1):SiteReadWrite の Action に storage:PutObject があり、Resource bucket/edu-site/* に一致 → Allow。Deny 文は billing:*・storage:PutBucketPolicy・db:Delete* のどれにも一致しない → 許可。
ステップ2(要求2):storage:DeleteObject はどの Allow 文の Action にもない。Deny 文にもない → どれにも当てはまらない → 拒否(既定拒否)。教材の削除が仕事に必要なら、追加を申請して承認を得る。
ステップ3(要求3):Deny 文の storage:PutBucketPolicy と Resource * に一致 → 拒否(明示的な拒否)。仮に誰かが別のポリシーで storage:* を許可しても、Deny が優先されて拒否のままです。
ステップ4(要求4):GetObject は SiteReadWrite にあるが、資源 bucket/hr-data/... は bucket/edu-site/* に一致しない → 拒否。
結果をまとめます。
| # | 結果 | 決め手 |
|---|---|---|
| 1 | 許可 | Allow に一致、Deny に不一致 |
| 2 | 拒否 | どの文にも不一致(既定拒否) |
| 3 | 拒否 | Deny に一致(明示的な拒否) |
| 4 | 拒否 | 資源が Allow のパターンに不一致(既定拒否) |
意味:配信係は教材の更新とキャッシュ更新だけができ、請求・公開設定・他部署のデータには触れません。このような要求と期待結果の表を作っておくと、ポリシーを変更するたびに同じ検査を自動で再実行できます。次の節で、この評価をPythonで自動化します。
操作して理解する:役割表を作り、権限を比べる
前の節の評価規則を関数 evaluate(policy, action, resource)(戻り値は "ALLOW" か "DENY")として書き、例題の要求も含めて、あおば学習の3つの役割を比べます。運用(教材配信係)、利用者(受講者向けアプリのサービスアカウント。教材を読むだけ)、管理者(権限と請求の管理。日常作業には使わない)です。
from fnmatch import fnmatchcase
def matches(patterns, value): # どれかのパターンに一致すれば True
return any(fnmatchcase(value, p) for p in patterns)
def evaluate(policy, action, resource):
allowed = False
for st in policy["Statement"]:
if matches(st["Action"], action) and matches(st["Resource"], resource):
if st["Effect"] == "Deny":
return "DENY" # 明示的な拒否は最優先
allowed = True
return "ALLOW" if allowed else "DENY" # 何にも当たらなければ既定拒否
publisher = {
"Version": "edu-1",
"Statement": [
{"Sid": "SiteReadWrite", "Effect": "Allow",
"Action": ["storage:GetObject", "storage:PutObject", "storage:ListObjects"],
"Resource": ["bucket/edu-site/*"]},
{"Sid": "CacheRefresh", "Effect": "Allow",
"Action": ["cdn:InvalidateCache"],
"Resource": ["cdn/edu-site"]},
{"Sid": "NeverBillingOrPublicChange", "Effect": "Deny",
"Action": ["billing:*", "storage:PutBucketPolicy", "db:Delete*"],
"Resource": ["*"]}
]
}
app_reader = {"Statement": [
{"Effect": "Allow", "Action": ["storage:GetObject"], "Resource": ["bucket/edu-site/*"]}]}
admin = {"Statement": [
{"Effect": "Allow", "Action": ["*"], "Resource": ["*"]}]}
roles = {"運用(配信係)": publisher, "利用者(アプリ)": app_reader, "管理者": admin}
checks = [
("storage:GetObject", "bucket/edu-site/a.html"),
("storage:PutObject", "bucket/edu-site/a.html"),
("storage:DeleteObject", "bucket/edu-site/a.html"),
("storage:GetObject", "bucket/hr-data/salary.csv"),
("storage:PutBucketPolicy", "bucket/edu-site"),
("billing:UpdatePayment", "account/main"),
("db:DeleteTable", "db/learners"),
]
print("操作".ljust(24), *[r for r in roles])
for action, resource in checks:
print(action.ljust(24), *[evaluate(p, action, resource).ljust(8) for p in roles.values()])
出力:
操作 運用(配信係) 利用者(アプリ) 管理者
storage:GetObject ALLOW ALLOW ALLOW
storage:PutObject ALLOW DENY ALLOW
storage:DeleteObject DENY DENY ALLOW
storage:GetObject DENY DENY ALLOW
storage:PutBucketPolicy DENY DENY ALLOW
billing:UpdatePayment DENY DENY ALLOW
db:DeleteTable DENY DENY ALLOW
試してみましょう。
- 4つ目の要求(
bucket/hr-data/salary.csvの読み取り)は、運用もアプリも拒否です。app_readerの Resource を["*"]に変えると、アプリの列が ALLOW に変わり、他部署のデータまで読めるようになります。 - 管理者の列はすべて ALLOW です。だからこそ管理者権限は少人数・多要素認証必須・日常作業では使わないように運用し、使った記録を残します(責任共有とログ)。
発展:条件・一時的な認証情報・権限の上限
- 条件(Condition):「社内ネットワークのアドレス範囲からのときだけ」「多要素認証を済ませたときだけ」のように、許可に条件を付けられます。条件を満たさない要求は、その文に当てはまらないものとして扱われます。
- 一時的な認証情報:長期間有効なアクセスキーを人やアプリに配るより、ロールを引き受けて数時間で失効する認証情報を使う方式が推奨されることが一般的です。クラウド上で動くアプリには、提供者が自動で一時的な認証情報を渡す仕組みがあることが多く、鍵をコードや設定ファイルに書く必要がなくなります(秘密情報の扱いは 「鍵と秘密情報」(有料版))。
- 権限の上限:組織全体や部署単位に「この範囲を超える許可は、個別に付けても無効」という上限を設ける仕組みがあります(名称は提供者ごとに異なる)。管理者が誤って広い権限を付けても、上限で止まります。
- 権限の昇格:IAMの設定を変更できる権限(ポリシーの付与など)を持つ主体は、自分に管理者権限を付けられます。
iam:で始まる書き込み操作は、管理者権限と同等に扱って厳しく制限します。
よくある失敗
失敗1:アプリのサービスアカウントに `*` を付ける
誤った設定:受講者向けアプリが教材を読めなかったので、アプリ用の主体に {"Action": ["*"], "Resource": ["*"]} を付けた。
from fnmatch import fnmatchcase
def matches(patterns, value): # どれかのパターンに一致すれば True
return any(fnmatchcase(value, p) for p in patterns)
def evaluate(policy, action, resource):
allowed = False
for st in policy["Statement"]:
if matches(st["Action"], action) and matches(st["Resource"], resource):
if st["Effect"] == "Deny":
return "DENY" # 明示的な拒否は最優先
allowed = True
return "ALLOW" if allowed else "DENY" # 何にも当たらなければ既定拒否
app_bad = {"Statement": [{"Effect": "Allow", "Action": ["*"], "Resource": ["*"]}]}
for a, r in [("storage:GetObject", "bucket/edu-site/a.html"),
("db:DeleteTable", "db/learners"),
("compute:CreateInstance", "region/any")]:
print(a, r, "->", evaluate(app_bad, a, r))
出力はすべて ALLOW です。アプリに入力検証の不備があり攻撃者に操られると、受講者DBの削除や計算資源の大量作成までできてしまいます。
直し方:アプリが実際に呼ぶ操作を書き出し(ここでは storage:GetObject を bucket/edu-site/* に対してだけ)、それだけを許可する。動かないときは拒否された操作名をログで確認して、その1つだけを追加する。
失敗2:管理者本人の認証情報をアプリに埋め込む
誤った実装:試作を急いで、管理者自身のアクセスキーをアプリの設定ファイルに書き、そのまま本番に出した。
# 誤り:人(管理者)の長期キーをアプリに埋め込んでいる
ACCESS_KEY = "ADMIN-KEY-1234" # 架空の値
なぜ誤りか:(1) アプリが管理者と同じ全権限で動く。(2) 操作の記録上、アプリの操作と管理者本人の操作が区別できない(ログに同じ主体として残る)。(3) 管理者が退職・異動してキーを無効にするとアプリが止まる。(4) 設定ファイルの漏洩がそのまま全権限の漏洩になる。
直し方:アプリ専用のサービスアカウントを作り、必要な操作だけを許可する。認証情報はコードに書かず、実行環境が渡す一時的な認証情報か、秘密情報の保管庫から読む。人の権限・アプリの権限・アプリの利用者の権限の3つを別々に設計する。
失敗3:資源のパターンを広く書きすぎる
誤った設定:bucket/edu-site/* と書くべきところを bucket/edu-site* と書いた。
from fnmatch import fnmatchcase
good, bad = "bucket/edu-site/*", "bucket/edu-site*"
for res in ["bucket/edu-site/a.html", "bucket/edu-site-private/answers.csv"]:
print(res, "| 正:", fnmatchcase(res, good), "| 誤:", fnmatchcase(res, bad))
出力:
bucket/edu-site/a.html | 正: True | 誤: True
bucket/edu-site-private/answers.csv | 正: False | 誤: True
/ が1文字ないだけで、名前が edu-site で始まる別の保存場所(ここでは解答を置いた edu-site-private)まで一致します。
直し方:資源のパターンは区切り文字まで書く。ポリシーを変えたら、「許可されるべき要求」だけでなく「拒否されるべき要求」(似た名前の別資源など)もテストに入れて確認する。
まとめ
- IAMは「誰が(主体)・どの資源に・何をできるか(操作)」を、ポリシーの文(Effect・Action・Resource・Condition)で定める。
- 評価は「明示的な拒否が最優先、許可が1つあれば許可、何にも当たらなければ拒否」。文の順番に依存しない。
- 最小権限:仕事に必要な操作だけを、必要な資源に、必要な期間だけ。資源のパターンは区切りまで書く。
- 人の権限・アプリ(サービスアカウント)の権限・アプリの利用者の権限を分ける。人の鍵をアプリに埋め込まない。
- ポリシーは「許可されるべき要求」と「拒否されるべき要求」の表で模擬評価し、点検を自動化する。
用語
- IAM(Identity and Access Management)
誰(主体)がどの資源にどの操作をできるかを管理する仕組み。
- 主体(principal)
要求を出す者。ユーザー、グループ、ロール、サービスアカウントなど。
- ポリシー(policy)
Effect・Action・Resource(・Condition)からなる文の集まりで、許可と拒否を定める文書。
- サービスアカウント(service account)
アプリやジョブが使う、人ではない主体。
- 明示的な拒否(explicit deny)
Deny の文に一致したことによる拒否。ほかの許可より優先される。
- 既定拒否(暗黙の拒否)(implicit deny)
どの文にも一致しない要求を拒否すること。
よくある質問
なぜ最初から全部許可して、困ったら絞る方式ではいけないのですか?
広い権限は、使われていなくても、鍵の漏洩・誤操作・アプリの乗っ取りのときに被害の上限を決めてしまうからです。また、一度広く付けた権限は「何が必要か」が誰にもわからなくなり、絞れなくなります。狭く始めて、拒否された操作を特定して足すほうが、結果的に安全で管理も楽です。
ロールとグループの違いは何ですか?
グループは「人の集まり」に権限を付ける仕組みで、所属している間はずっと有効です。ロールは「権限の束」を必要なときに一時的に引き受ける仕組みで、人だけでなくアプリやジョブも使えます。提供者によって用語の意味が少し異なるので、実環境では公式の説明を確認してください。
Deny をたくさん書けば安全になりますか?
Deny は「絶対にさせない」ことを明示する安全装置として有効です(請求設定、公開設定、本番DBの削除など)。ただし、許可の側を最小にするのが基本で、Deny は抜けに対する二重の守りです。Deny が多すぎると、正当な作業が止まった原因を探しにくくなります。
退職者や異動者の権限はどうなりますか?
自動では消えません。人事の手続きと連動して無効化する手順と、定期的な棚卸し(「最小権限」(有料版))が必要です。長期のアクセスキーは特に残りやすいので、最終使用日を確認して未使用のものを無効にします。
仕事でポリシーをレビューするとき、何を見ればよいですか?
(1) * を含む Allow(とくに Action と Resource の両方)、(2) IAMの書き込み操作、(3) 公開設定・請求・削除に関わる操作、(4) 資源のパターンの区切り、(5) 人用かアプリ用か、(6) 期限があるか、の6点です。さらに「許可されるべき要求」と「拒否されるべき要求」の表で模擬評価を回し、結果を記録します。
確認問題
問1 あるポリシーに「storage: を bucket/edu-site/ に Allow」と「storage:DeleteObject を bucket/edu-site/archive/* に Deny」がある。bucket/edu-site/archive/old.html の削除要求はどうなるか。
- ① 許可(Allowが先に書かれているから)
- ② 拒否(明示的な拒否が優先されるから)
- ③ 許可(storage:* はすべての操作を含むから)
- ④ 設定によらず必ずエラーになる
解答と解説
正解:②
要求に一致する文に Deny が1つでもあれば、Allow の有無や順番に関係なく拒否です。
問2 どのポリシーの文にも一致しない操作を要求した場合の結果はどれか。
- ① 許可される
- ② 拒否される(既定拒否)
- ③ 管理者に自動で確認が行く
- ④ 読み取りなら許可、書き込みなら拒否
解答と解説
正解:②
許可の根拠がない要求は拒否されます。必要なら、操作名を特定して申請・承認のうえ追加します。
問3 受講者向けWebアプリが教材を読むための権限設計として最も適切なのはどれか。
- ① 受講者1人ずつにクラウドのユーザーを作り、保存場所の読み取りを付ける
- ② 開発者本人のアクセスキーをアプリに設定する
- ③ アプリ専用のサービスアカウントを作り、教材の保存場所の読み取りだけを許可し、受講者ごとの制御はアプリ内で行う
- ④ アプリに管理者権限を付け、受講者の制御もクラウドの管理画面で行う
解答と解説
正解:③
アプリの利用者の権限(アプリ内の認可)と、アプリ自体のクラウド権限(サービスアカウント)を分けます。
問4 パターン bucket/edu-site* について正しい説明はどれか(* は任意の文字列)。
- ① bucket/edu-site の中のファイルだけに一致する
- ② bucket/edu-site-private/answers.csv にも一致してしまう
- ③ どの資源にも一致しない
- ④ bucket/edu-site そのものには一致しない
解答と解説
正解:②
/ がないため、edu-site で始まる別の保存場所の名前にも一致します。区切り文字まで書く必要があります。
問5 IAMポリシーの付与(例:iam:AttachPolicy)を許可された主体について、最も注意すべき点はどれか。
- ① 読み取りしかできないので安全
- ② 自分や他者に管理者権限を付けられるため、実質的に管理者と同等に扱うべき
- ③ 保存場所の操作ができないので影響はない
- ④ 請求には影響しない
解答と解説
正解:②
権限を変更できる権限は、権限の昇格につながります。管理者権限と同じ厳しさで制限・記録します。
問6 分析者が「動かないので権限を広げてほしい」と依頼してきた。最も適切な対応はどれか。
- ① とりあえず管理者権限を付け、あとで外す
- ② 拒否された操作名と資源をログやエラーで確認し、仕事に必要なものだけを期限付きで追加する
- ③ 依頼をすべて断る
- ④ 別の人のアカウントを貸す
解答と解説
正解:②
最小権限は「必要な操作を、必要な資源に、必要な期間だけ」。拒否された内容を特定して最小限を追加します。
次に学ぶこと
次は 責任共有とログ で、提供者と利用者の責任の分担と、公開設定の確認、操作の記録(監査ログ)の読み方を学びます。
秘密情報(アクセスキー)の保管は 「鍵と秘密情報」(有料版)、API側での利用者の認可は 「認証・認可・レート制限」(有料版) に戻って確認できます。保存場所ごとのアクセス制御は 「鮮度とアクセス制御」(有料版)、環境ごとの権限と秘密の分離は 「環境分離と秘密」(有料版) で深めます。
キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。
アプリを無料で開く有料版と無料版の違い