適当にIAMポリシーを設定したら動かなかった話。
[UnauthorizedOperationエラー]
停止中のEC2インスタンスIDを取得して対象のインスタンスを起動する、という処理を実装する必要があった。
EC2のDescribeInstancesAPIを利用したNode.jsのコードをAWS Lambda関数で実行したところ、次のエラーが出た。
UnauthorizedOperation: You are not authorized to perform this operation.
ちゃんとIAMロールには必要な権限のポリシーをつけているはずなのに、変だな……と思いながら確認すると、問題のLambda関数には以下のポリシーが設定されていた。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "test", "Effect": "Allow", "Action": [ "ec2:StartInstances", "ec2:DescribeInstances" ], "Resource": [ "arn:aws:ec2:ap-northeast-1:123456789012:instance/*" ] } ] }
リソース指定のAWSアカウントIDはダミーのものに変更しているが、他は実際に利用していたポリシーそのままである。
ちゃんとAllow
で"ec2:DescribeInstances"
アクションが指定されている。これなら動くはずだ、と思い何度か試してみたが、同じエラーメッセージが表示され続けた。
[Visual editorの警告]
何か手がかりがないか、と思いポリシーの表示をJSON方式からVisual editorに変更したところ、以下のように警告が表示された。
▶︎をクリックしてアコーディオンを開くと、詳細なエラーメッセージが表示された。
The actions in your policy do not support resource-level permissions and require you to choose All resources.
「このアクションはリソースレベルの権限をサポートしていないので、全てのリソースを選択する必要がある」と書かれている。
JSONエディタの画面下部にも警告が表示される欄はあるのに、なぜ同じエラーメッセージを表示してくれないのか……。
IAMに関するトラブルシューティングの記事を見ると、2番目にリソースレベルでのアクセス許可を確認すること、とある。なるほど。
上記の記事に書かれているIAMポリシーのトラブルシューティング手順の概要は以下のとおり。
- API の呼び出し元に対し適切なアクセス許可が与えられているか検証
- リソースレベルでのアクセス許可を確認(アクションによっては指定不可)
- IAM ポリシーで使用されている条件を見直す
- サービス固有のコントロールを確認する
[ステートメントを分割する]
トラブルシューティング記事にしたがって、DescribeInstances
のリソースの指定をアスタリスクに変更する。
同時に、StartInstancesのリソース指定は残しておきたかったので、以下のようにステートメントを2つに分割した。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "test1", "Effect": "Allow", "Action": [ "ec2:DescribeInstances" ], "Resource": "*" }, { "Sid": "test2", "Effect": "Allow", "Action": [ "ec2:StartInstances" ], "Resource": [ "arn:aws:ec2:ap-northeast-1:123456789012:instance/*" ] } ] }
これで問題なくLambda関数を動かして、目的の操作を実行できた!🎉
[まとめ]
- UnauthorizedOperationエラーがでた場合のポリシー確認手順は以下の通り
- API の呼び出し元に対し適切なアクセス許可が与えられているか検証
- リソースレベルでのアクセス許可を確認(アクションによっては指定不可)
- IAM ポリシーで使用されている条件を見直す
- サービス固有のコントロールを確認する
- Visual editorを利用すると問題のある箇所が確認できる場合がある