小ネタです。
AWS IAM Policy を作成する際に以下の様なエラーが発生することがあります。
An error occurred (MalformedPolicyDocument) when calling the CreatePolicy operation: The policy failed legacy parsing
このエラー自体は汎用的なメッセージであり、発生原因はいくつか存在するようです。
JSONとしては正しいが、IAM Policy の仕様上許可されない場合に出力されるようです。
少し謎な仕様があったのでメモ。
基本
AWSマネジメントコンソールの Policy editor で表示される雛形です。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [],
"Resource": []
}
]
}
文法に関する諸々は公式ドキュメントにまとまっています。
IAM JSON ポリシーリファレンス - AWS Identity and Access Management
先頭は { で始まる必要があります。
よくある話です。
空白や改行が先頭にあるとエラーになります。
Policy editor 上では少し詳しいメッセージ出力となり、作成時に “JSON strings must not have leading spaces” が出力されます。

作成時に と書いたのは、Validation 時点で判明せず、 “Next” ボタン押下時に出力されるためです。
CLI や SDK での実行では “The policy failed legacy parsing” としか教えてくれません。 access-analyzer での ValidatePolicy も通ります。
Statement は配列 である必要があります。
本題です。Statement 要素は 配列 です。
"Statement": [{...},{...},{...}]
だがしかし、1オブジェクトでの作成は許可されます。
“Statement” が1つで済むポリシーは、値部分が配列である必要はなく、オブジェクトでも作成できます。

尚、この記述方法は公式ドキュメント上でも普通に使われています。
- JSON ポリシー概要
JSON ポリシー構文の例
だがしかしだがしかし、オブジェクトの場合は Version 要素が先頭である必要があります。
本題の本題です。
公式ドキュメント上の "ポリシーの文法に関する注意事項" に要素順は問わないとあるのですが、通りません。
- IAM JSON ポリシー言語の文法 - AWS Identity and Access Management
ブロックは任意の順序で記述できます。
+ cat policy.object.error.json
{
"Statement": {
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket"
},
"Version": "2012-10-17"
}
+ aws iam create-policy --policy-name example-policy.object.error --policy-document file://policy.object.error.json
An error occurred (MalformedPolicyDocument) when calling the CreatePolicy operation: The policy failed legacy parsing
Policy editor での”Next”ボタン押下は通り、その後の “Create policy” ボタン押下後にエラーになります。

尚、 “Statement” が配列であれば通ります。

まとめ
余計なトラブルの回避のため Statement 要素は配列, Version は先頭 にしておくのが良さそうです。