Linterを使ってCloudFormationの間違いに爆速で気づく

CloudFormation、使ってますか?

私はAWSの環境を手早く構築するために、CloudFormationをむちゃくちゃ使います。

CFnテンプレートを書いてCFnスタックを作る際に、こんな経験はありませんか?


「我ながら完璧なテンプレートができてしまった…。CFnスタック作ったろ。」ポチ

「うわー恥ずかしい。Cdirだってよ。スペルミスしてるじゃん…。」


こういった簡単な間違いはCFnテンプレート書きながらLinterでさっさと見つけましょう。というお話です。

Linterとは

ざっくりいうと、記述しているソースコード(CFnテンプレート)が妥当かどうかチェックしてくれるツールです。

例えば、「パラメーターが無い」なんて問題がエディタ上で一瞬でわかります。

CloudFormationのLinter

CloudFormationのLinterは2つあります。

1つ目が cfn-python-lint です。pythonで書かれたCloudFormationテンプレートのLinterです。

https://github.com/aws-cloudformation/cfn-python-lint

2つ目が cfn-lint です。jsで書かれたLinterです。

https://github.com/martysweet/cfn-lint

この2つのLinterは、同じ cfn-lint コマンドで動きますが、全く別の物です。注意してください。

今回はエディタプラグインが豊富に開発されているので、cfn-python-lintを使用します。

cfn-python-lintのインストール

pipを使ってインストールできます。

$ pip install cfn-lint

cfn-python-lintの使い方

こういったCFnテンプレートがあった場合、

---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'My CloudFormation Template.'

Parameters:
  MyCidrBlock:
    Type: String
    Default: 192.0.2.0/24

Resources:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref MyCdirBlock

CFnテンプレート名を引数に cfn-lint コマンドを実行すると、

$ cfn-lint template.yml

CFnテンプレートのおかしなところを出力してくれます。

W2001 Parameter MyCidrBlock not used.
template.yml:6:3

E1012 Ref MyCdirBlock not found as a resource or parameter
template.yml:14:7

エディタのプラグインを入れる

CFnテンプレートのチェックをするのに、いちいちコマンド打つのはめんどくさいです。
もっとリアルタイムで指摘が欲しいです。

そういう時は、エディタのプラグインを入れましょう。エディタ上でチェックできるようになります。
以下エディタのプラグインが開発されているようです。

  • Atom
  • NeoVim 0.2.0+/Vim 8
    • ALE
    • Syntastic
  • Sublime
  • Visual Studio Code
  • IntelliJ IDEA

私はIntelliJ IDEAが好きで、Pythonを書くこともあるのでPyCharm CE(Community Edition)を使用しています。ありがたいことに無料で使えます。

https://www.jetbrains.com/pycharm/download/

IntelliJ IDEAを使う場合、あわせてCloudFormationプラグインも使うと便利です。 IntelliJ IDEAのCloudFormationプラグインについては弊社ブログを御覧ください。

InteliJ IDEAのCloudFormationプラグインを使ってみた

PyCharmプラグイン導入手順

プラグインブラウザでcfn-lintを探してインストールします。

プラグインのインストールが終わったらCFNLintの設定が必要です。

設定画面でcfnlintで検索して、設定を有効(enable)にします。
cfn-lint exeには cfn-lint コマンドのフルパスを入れてください。パスは $ which cfn-lint で確認してください。
WarningとErrorを目立たせたいんで下2つにもチェック入れます。

CFnテンプレートをチェックしてみる

テンプレートを書きながら、Linterの使用感を確認していきます。

例えば、DynamoDBのCFnテンプレートを書いてみます。

---
AWSTemplateFormatVersion: '2010-09-09'

Resources:
  DynamoDB:
    Type: "AWS::DynamoDB::Table"
    Properties:
      TableName: "MyDynamoDB"
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "String"
      KeySchema:
        - AttributeName: "ArtistId"
          KeyType: "HASH"

DynamoDBのAttributeTypeって何があるんだっけ?Stringだっけ?
覚えていないので、とりあえずStringとか適当に書いてしまいます。

すると、Valid values are ['B', 'N', 'S'] って怒られます。これで間違いにもすぐ気づけます。

次はEC2のCFnテンプレートを書いてみます。

---
AWSTemplateFormatVersion: "2010-09-09"

Resources:
  MyEC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      ImageId: "ami-0f9ae750e8274075b"
      IamInstanceProfile: !Ref Ec2Role
  Ec2Role:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          -
            Effect: "Allow"
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: "root"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              -
                Effect: "Allow"
                Action: "*"
                Resource: "*"

EC2作って、なんでもできるRoleをつけて…と。

すると、"IamInstanceProfile" can Ref to resources of type [AWS::IAM::InstanceProfile] と怒られています。 忘れがちな、InstanceProfileの存在にもすぐに気づけます。

おわりに

Linterを使ってCFnテンプレートの間違いにすばやく気づき、即修正のループを回していくことで、 圧倒的にCFnテンプレートが書きやすくなります。

ぜひお試しください。