SQSキューポリシーの明示的な拒否の定義に失敗して、SQSにアクセスできなくなった話

本記事は 夏休みクラウド自由研究 8/3付の記事です

こんにちは、SCSK齋藤です。

今回は、SQSキューポリシーに明示的な拒否を設定しましたが、考えが甘かったせいで、SQSにアクセスできなくなったお話を書いていきます。
そして、その教訓からIAMのポリシー定義について、再び学びを深めてみたいと思います。

何が起こったか?

SQS→Lambdaへと連携するようなサーバレスアーキテクチャを開発している時に、SQSに次の2点のアクセス制御を実施したいと考えました。

  1. SQSへメッセージを送受信するリソースを、特定のLambdaのみにしたい
  2. 人手による運用が入るのを考慮し、マネジメントコンソール経由で全IAMユーザーからのアクセスは許可したい。

そのため、実際に定義したキューポリシーは下記の通りです。

# # ------------------------------------------------------------#
# # SQSQueuePolicy
# # ------------------------------------------------------------#
  SQSPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref SQS
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          #IAMユーザと必要リソース以外のアクセスを拒否
          - Effect: Deny
            Principal: "*"
            Action: "sqs:*"
            Resource: !GetAtt SampleSQS.Arn
            Condition:
              StringNotEquals:
                aws:UserAgent:
                  - aws-internal-console
              ArnNotLike:
                aws:SourceArn:
                  - !Sub "arn:aws:lambda:*:${AWS::AccountId}:function:sample-lambda-*"

上記ポリシーを設定し、SQSをSAMテンプレートから作成してみましたが、管理者権限を持ったIAMユーザーからでは、マネジメントコンソール上に作成したSQSが表示されません。

なお、CloudShellを開き、SQSのリストをAWS CLIで表示してみたら、リストの一覧には出てきました。
AWS CLI上だけ見えるのも変だと思いながらも、そのままAWS CLIで削除コマンドを実施しましたが、Access Deniedになり、削除できませんでした。

まさしく、八方塞がりな状態でした。。。

 

暫定対処

上記の状態に陥ったので、ひとまずキューを削除する方法を考えました。

① 特定のLambdaのみからアクセスできるようにする意図で、キューポリシーを書いていたので、そのLambdaからキューを削除することができないか?
→実際に試してみましたが、こちらもAccess Deniedされてしまいました。。なぜだ。。。。

② ルートユーザーから削除できないか?
→こちらは成功いたしました。やはり最後の頼みの綱は、ルートユーザーなんだなと感じました。

 

キューポリシーを振り返る

一旦削除はできたので、改めて定義したキューポリシーの何がいけなかったのかを考察していきます。

ポイントは、2つです。

IAMユーザーからマネジメントコンソールで閲覧させる権限の記述の誤り

ポリシーの中の、下記が問題でした。

StringNotEquals:
   aws:UserAgent:
      - aws-internal-console

こちらを書いた意図としては、IAMユーザーがマネジメントコンソール経由でSQSの操作ができるようにするために記載しました。

元々は、PrincipalをNotPrincipalにする下記の記載方式を検討していましたが、NotPrincipal内ではuserに*は使えないとのことで作成ができませんでした。

NotPrincipal: arn:aws:iam::111122223333:user/*

 

また、事後調査でわかりましたが、下記のようなドキュメントも見つけたので、NotPrincipalとDenyはそもそも相性が悪いんだということもわかりました。

AWS JSON ポリシーの要素: NotPrincipal - AWS Identity and Access Management
AWS JSON ポリシー言語の NotPrincipal 要素を定義します。

 

そのため、チャット式の生成AIに聞いたら、aws:UserAgentを用いた書き方を提案されたので、今回のような書き方をしました。。。

しかし、インターネットで調べてもこのような書き方は出てこないので、嘘情報だったのではと思います。
実際、今回記載した内容は「aws-internal-console」というアプリケーションからのHTTPリクエストという意味になるそうです。

マネジメントコンソール上でHTTPヘッダーを確認しましたが、aws-internal-consoleという情報は出てこなかったです。
これでは、マネジメントコンソールからアクセスできませんね。。。

Denyステートメント内でのLambdaへの権限の記述誤り

Lambdaについては、下記のように記載していました。

ArnNotLike:
  aws:SourceArn:
    - !Sub "arn:aws:lambda:*:${AWS::AccountId}:function:sample-lambda-*"

これは、LambdaのARNを指定して、Denyから回避しようとしてました。

しかし、正しくはLambdaにアタッチされているIAMロールをNotとして回避させてあげないといけません。
あくまでLambdaからSQSへ操作する実行主体は、IAMロールなので、それに対する権限の記載をしないといけなかったという訳です。

 

正しい記載は何か?

いろいろ調査した結果、正しい記載は下記ではないかと考えられます。

{
  “Version”: “2012-10-17",
  “Statement”: [
    {
      “Effect”: “Deny”,
      “Principal”: “*”,
      “Action”: “sqs:*“,
      “Resource”: “arn:aws:sqs:ap-northeast-1:${AWS::AccountId}:SampleQueue”,
      “Condition”: {
        “ArnNotEquals”: {
          “aws:PrincipalArn”: [
            “arn:aws:iam::${AWS::AccountId}:user/*“,
            “arn:aws:iam::${AWS::AccountId}:role/service-role/example-role”
          ]
        }
      }
    }
  ]
}

ArnNotEqualsの中身は、aws:PrincipalArnで統一をします。

その中で、下記2つを記載して、それぞれのことを実現します。

  • “arn:aws:iam::${AWS::AccountId}:user/*“・・・そのアカウント内の全IAMユーザーへのアクセス制御を実現。
  • “arn:aws:iam::${AWS::AccountId}:role/service-role/example-role”・・・Lambdaに付与しているIAMロールへのアクセス制御を実現。

 

今回の教訓

今回アクセス拒否されてしまった事象の教訓としては、下記がございます。

  1.  Lambdaへのアクセス制御は、付与しているIAMロールへのアクセス制御が必要。
    ・実行権限を付与する主体が何なのかは、今後権限付与する際にしっかり調査する必要があると感じました。
  2. NotPrincipalとDenyはそもそも相性が悪い。
    ・AWS側も非推奨としているので、DenyをするならConditionの中にaws:PrincipalArnを書く方法を採用すべきですね。
  3. ポリシー作成後に検証して動作確認するとはいえ、安易に生成AIのいうことを聞いてはいけない。
    ・今回は明示的な拒否のため、アクセスできなくなるリスクが孕んでおり、そういう場合には慎重に調査をすべきと感じました。

 

まとめ

今回は、SQSへのアクセスができなくなった事象についてまとめました。

IAMの記述方式は複雑であり、非常に奥が深いことを再実感しました。
正しい仕様を理解することはやはり重要ですね。

著者について

フロントエンドもバックエンドも両方少しずつ勉強して、フルスタックエンジニアを目指してます。
サーバレス開発の楽しさを実感中!

ANGEL Dojo 2021 ANGEL賞、ベストアーキテクチャ賞ダブル受賞
2023 Japan AWS Jr. Champions
2022〜24 Japan AWS All Certifications Engineers

齋藤友宏をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AWSクラウド
シェアする
タイトルとURLをコピーしました