CloudFormation を YAML で書く時、当然ながら YAML の仕様も理解しないといけないんだなと感じたきっかけ等についてお話します。
得た結論としては以下です。
- CloudFormation を YAML で書く時は YAML の仕様にも注意
- AWSアカウントIDはクォートするのが無難
発生した事象
以下のようなテンプレートで CloudFormation スタックを作成すると、リソースの作成に失敗しました。
Parameters: ReceiverAccountId: Type: String Default: 012345678901 Resources: Policy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: 'events:PutEvents' Resource: !Sub "arn:aws:events:us-east-1:${ReceiverAccountId}:event-bus/default"
対象リソース(IAM Policy)作成時、以下のようなエラーが発生していました。
The policy failed legacy parsing (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; Proxy: null)

よく見るとパラメータ「ReceiverAccountId」のデフォルト値が、012345678901 -> 1.2345678901E10
というように指数表示に変換されてしまったようです。

解決した方法
以下のように Default 値をクオーテーションで囲むと本来の「012345678901」となり、デプロイが成功しました。
Parameters:
ReceiverAccountId:
Type: String
Default: '012345678901'
気づいたこと
上記事象について、当初は「数値だけ書くとおかしくなるからクォートすればいいんだな」としか考えてなかったのですが、本記事を書くにあたりいくつか検証したところ気づくことがありました。
以下テンプレート(一部)の場合は該当のパラメータが「1」になりました。
まぁ、ゼロが取り除かれちゃったのかな?
Parameters:
ReceiverAccountId:
Type: String
Default: 000000000001
以下の場合は「9」でした。
??
Parameters:
ReceiverAccountId:
Type: String
Default: 000000000011
以下の場合は「10」でした。
ここでようやく、どうやら8進数になってるらしいぞと気づきました。
Parameters:
ReceiverAccountId:
Type: String
Default: 000000000012
更に調べると、以下のような情報も見つけました。
どうやら YAML の解釈プロセスによって値が変換されていたようです。
YAML Version 1.1 – 2.4. Tags ※1
Example 2.19. Integers
canonical: 12345
decimal: +12,345
sexagesimal: 3:25:45
octal: 014
hexadecimal: 0xC
最初の 012345678901 -> 1.2345678901E10
という変換についてはハッキリとした答えを見つけられませんでした。
ただ、「012345678901」という値については「0から始まっているが」「8以上の数が含まれている=8進数ではない」という点がポイントなのかなと思っています。
※1 CloudFormation は YAML 1.1 に対応
AWS CloudFormation テンプレート形式
AWS CloudFormation は、いくつかの例外を除き、YAML バージョン 1.1 の仕様をサポートしています。
まとめ
再掲ですが、下記となります。
- CloudFormation を YAML で書く時は YAML の仕様にも注意
- AWSアカウントIDはクォートするのが無難
投稿者プロフィール
- 2015年8月入社。弊社はインフラ屋ですが、アプリも作ってみたいです。