0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【IAM】最小権限で Terraform apply したら s3:GetBucket* では足りなかった話

0
Posted at

はじめに

GitHub Actions から Terraform を apply する構成を作っていて、apply 用の IAM ロールを「最小権限」で組んでいました。S3 の権限も「使うものだけ」を意識して s3:GetBucket* のように列挙していたのですが、フル apply の途中でこんなエラーで止まりました。

AccessDenied: ... is not authorized to perform:
s3:GetAccelerateConfiguration on resource:
"arn:aws:s3:::aws-study-alb-logs-xxxx"

GetBucket* で読み取り系はカバーしたつもりなのに、なんで GetAccelerateConfiguration で弾かれるんだ…?」としばらく悩みました。

先に結論:s3:GetBucket* は「GetBucket で始まるアクション」しか拾いませんs3:GetAccelerateConfiguration は名前が GetBucket始まっていないので、ワイルドカードに当たっていませんでした。

環境

  • Terraform v1.10 / AWS プロバイダ v6 系
  • GitHub Actions から OIDC で apply ロールを引き受けて実行
  • 対象に S3 バケット(ALB アクセスログ用など)を含む
  • リージョン: ap-northeast-1(東京)

(S3 バケット周りの読み取り動作は provider の世代で変わることがあるので、バージョンを添えておきます。)

起きたこと

apply ロールの S3 権限を、こんな感じで「読み取りは GetBucket 系」と思って書いていました(抜粋・一部)。

actions = [
  "s3:CreateBucket", "s3:DeleteBucket", "s3:ListBucket",
  "s3:GetBucket*", "s3:PutBucket*",
  "s3:GetObject", "s3:PutObject", "s3:DeleteObject",
  # ...
]
resources = [
  "arn:aws:s3:::aws-study-*",
  "arn:aws:s3:::aws-study-*/*",
]

ところがフル apply の途中、provider が S3 バケットの状態を読みにいくところで s3:GetAccelerateConfiguration が拒否され、apply が失敗しました。

原因:動詞のワイルドカードは「前方一致」

IAM のアクション名のワイルドカードは、指定した文字列で始まるアクションにマッチします。s3:GetBucket* がマッチするのは、

  • s3:GetBucketPolicy
  • s3:GetBucketAcl
  • s3:GetBucketPublicAccessBlock … など

といった GetBucket で始まるアクションだけです。

一方、今回弾かれたのは s3:GetAccelerateConfiguration。これは S3 の「転送高速化(Transfer Acceleration)」の設定を読むアクションですが、アクション名が GetBucket… ではなく GetAccelerate… から始まります。なので GetBucket* の前方一致には引っかかりません。

Terraform の AWS provider は、S3 バケットを作成したり refresh したりするときに、バケットの各種サブ設定(公開ブロック、暗号化、そして accelerate など)を読みにいきます。そのうちの1つが、自分のワイルドカードの“すき間”に落ちていた、というわけでした。「GetBucket* で読み取りは網羅できている」という思い込みが原因です。

対処:アクションは広げ、リソースで絞る

最小権限を「アクションを細かく列挙して絞る」方向で頑張ると、こういう取りこぼしがどうしても起きます。そこで方針を変えて、

  • アクションは s3:Get* / s3:Put* / s3:List* に広げる
  • そのかわり リソースは aws-study-* に限定したままにする

という形にしました(変更点の抜粋)。

actions = [
  "s3:CreateBucket", "s3:DeleteBucket", "s3:DeleteObject",
  "s3:Get*", "s3:Put*", "s3:List*",
]
resources = [
  "arn:aws:s3:::aws-study-*",
  "arn:aws:s3:::aws-study-*/*",
]

これで apply は通りました。ポイントは、「最小権限=アクションを絞ること」だけではないところです。アクションを Get*/Put*/List* と広めにしても、リソースを自分のプロジェクトのバケット(aws-study-*)に限定していれば、「他人のバケットには触れない」という肝心の絞りは効きます。

ただし、これは「リソースで絞れば常に安全」という話ではありません。注意点が2つあります。

  • すべての S3 アクションがバケット ARN で絞れるわけではない。AWS のサービス認可リファレンスを見ると、アクションごとに指定できるリソースタイプが違い、中には Resource: "*" を要求するものもあります。Get*/Put*/List* を使うときは、各アクションが自分の ARN で絞れるかを確認し、絞れないものは条件キーや別ステートメントで分離する、という検討が要ります。
  • s3:Put* は「書き込み」だけでなく設定変更系も含む(バケットポリシーや公開設定の変更など)。広げる前に「何が含まれるか」を一度見ておくと安心です。

今回は学習用途で範囲も aws-study-* に閉じているので広めにしましたが、本番では apply が通ったあとに CloudTrail や拒否ログで“実際に使われたアクション”を確認し、不要な権限を削っていくのが本筋だと思います。「広げて通す」で終わらせない、というのを次の宿題にしました。

学び

  • IAM のアクション・ワイルドカードは 前方一致s3:GetBucket*GetAccelerate… を拾わない。
  • S3 のサブ設定系アクションは、名前が GetBucket… で始まるとは限らない(GetAccelerateConfiguration など)。
  • Terraform provider は作成・refresh 時にバケットのサブ設定をまとめて読むので、読み取り権限の取りこぼしが apply で表面化する。
  • 最小権限は「アクションを列挙して絞る」だけでなく、リソースで絞るのも有効。ただし 全アクションが ARN で絞れるわけではないResource:"*" 必須のものもある)ので、サービス認可リファレンスで確認する。
  • 広げたら広げっぱなしにせず、使われた権限を確認して削るのが最小権限の本筋。

おわりに

「読み取りはカバーしたつもり」が一番あぶないな、と反省した一件でした😅 最小権限を頑張るほどワイルドカードの“すき間”を踏みやすいので、アクションの粒度・リソースの限定・あとからの削り込みをセットで考えるようになりました🙌

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?