LoginSignup
4
0

More than 3 years have passed since last update.

CodeCommit + CodeBuildでAWS CloudFormation Guardを試してみた

Last updated at Posted at 2020-12-17

はじめに

UL Systems Advent Calendar 2020 の18日目です。

CloudFormationテンプレートでEC2を作成した際、うっかりEBSの暗号化を忘れてしまい作り直しになった経験はあるのではないでしょうか。
暗号化以外にもプロジェクトルールで決まっている設定が漏れていた。なんてこともあるのではないでしょうか。
レビューでこれらの漏れを防ぐことも重要ですが、できれば自動でチェックする仕組みが欲しいですよね?

そんな時に使えるコマンドラインツールに、AWS CloudFormation Guardがあります。
AWSによる紹介ブログはこちら

どんなものなのか、実際に確かめてみました。

実行環境構築

ローカルマシンで実行するだけでは面白くないため、CodeCommit + CodeBuildで実行できる環境にしました。
ソースプロバイダにCodeCommitを、buildspec.ymlに以下の内容を指定していしたCodeBuildプロジェクトを作成。

buildspec.yml
version: 0.2

phases:
  install:
    commands:
       - wget https://github.com/aws-cloudformation/cloudformation-guard/releases/download/1.0.0/cfn-guard-linux-1.0.0.tar.gz
       - tar -xvf cfn-guard-linux-1.0.0.tar.gz
  build:
    commands:
       - ./cfn-guard-linux/cfn-guard --version
       - ./cfn-guard-linux/cfn-guard check -t ebs_volume_template.yml -r ebs_volume_template.ruleset

How it worksにあるサンプルコードではjsonですが、yamlに置き換えたebs_volume_template.ymlとebs_volume_template.rulesetをCodeCommitにpush。
ビルドを実行し、3件のエラーが発生することを確認。

result1.png

AWS::EC2::Instanceで試してみる

CFnテンプレートの作成

サンプルではEBSだが、実運用ではEC2 Instanceで作成することが多い。同様のチェックをEC2 Instanceでも試してみる。
適当なEC2を作成するCFnテンプレートを作成。

ec2_template.yml
Resources:
  NewInstance1:
    Type: AWS::EC2::Instance
    Properties:
      DisableApiTermination: true
      SubnetId: subnet-XXXXXXXXX
      ImageId: ami-00f045aed21a55240
      InstanceInitiatedShutdownBehavior: stop
      InstanceType: t2.micro
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 500
            VolumeType: gp2
            Encrypted: false
        - DeviceName: /dev/sda2
          Ebs:
            VolumeSize: 50
            VolumeType: gp2
            Encrypted: false
        - DeviceName: /dev/sda3
          Ebs:
            VolumeSize: 10
            VolumeType: gp2
      KeyName: sample-key
      Monitoring: false
      SecurityGroupIds:
        - sg-XXXXXXXXXXXXXXXXX

ルールセットの作成

1からルールセットを記載するのは面倒なので、Rulegenコマンドでの自動生成を試してみた。

> cfn-guard rulegen sample-project/ec2_template.yml
AWS::EC2::Instance BlockDeviceMappings == [{"DeviceName":"/dev/sda1","Ebs":{"Encrypted":false,"VolumeSize":500,"VolumeType":"gp2"}},{"DeviceName":"/dev/sda2","Ebs":{"Encrypted":false,"VolumeSize":50,"VolumeType":"gp2"}},{"DeviceName":"/dev/sda3","Ebs":{"VolumeSize":10,"VolumeType":"gp2"}}]
AWS::EC2::Instance DisableApiTermination == true
AWS::EC2::Instance ImageId == ami-00f045aed21a55240
AWS::EC2::Instance InstanceInitiatedShutdownBehavior == stop
AWS::EC2::Instance InstanceType == t2.micro
AWS::EC2::Instance KeyName == sample-key
AWS::EC2::Instance Monitoring == false
AWS::EC2::Instance SecurityGroupIds == ["sg-XXXXXXXXXXXXXXXXX"]
AWS::EC2::Instance SubnetId == subnet-XXXXXXXXX

ImageIdなど単純な比較となる項目は自動生成でも問題ないが、BlockDeviceMappingsなどの多階層の項目の値をチェックには使えそうにないですね。
リスト、かつ他階層の項目のため、ワイルドカードを利用し、以下のようなルールセットを作成

ec2_template.ruleset
let encryption_flag = true

AWS::EC2::Instance BlockDeviceMappings.*.Ebs.Encrypted == %encryption_flag
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.VolumeSize <= 100

実行結果の確認

チェック対象のテンプレート、ルールセットが作成できたため、CodeCommitのリポジトリへpush。
チェック対象のテンプレートが変更になったため、buildspec.ymlの一部を修正。

buildspec.yml
version: 0.2

phases:
  install:
    commands:
       - wget https://github.com/aws-cloudformation/cloudformation-guard/releases/download/1.0.0/cfn-guard-linux-1.0.0.tar.gz
       - tar -xvf cfn-guard-linux-1.0.0.tar.gz
  build:
    commands:
       - ./cfn-guard-linux/cfn-guard --version
       - ./cfn-guard-linux/cfn-guard check -t ec2_template.yml -r ec2_template.ruleset

実行したところ、暗号化チェックでエラーが発生していない。
(failed because [Encrypted]~のメッセージがなく、失敗ケースが1件になっている。)
result2.png

原因調査、対応

ドキュメントをもう一度確認してみたところ、Wildcard Semanticsに比較時の注意点書いてますね。
先ほどの記載ではいづれかがtrueならば結果OKとなってしまうため、全てfalseではないという条件へ修正。

ec2_template.ruleset
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.Encrypted != false
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.VolumeSize <= 100

実行し、Encryptedのエラーが発生することを確認。

result3.png

Encryptedが指定されていないデバイスもエラーにしたい

「DeviceName: /dev/sda3」は「Encrypted」が指定されていないが、先ほどの結果ではOKと見なされている。
暗号化されていないディスクが作成されてしまうため、未指定も結果NGとなることが望ましい。
項目がない場合結果NGとなるよう--strict-checksオプションを指定するようbuildspec.ymlを修正。

buildspec.yml
version: 0.2

phases:
  install:
    commands:
       - wget https://github.com/aws-cloudformation/cloudformation-guard/releases/download/1.0.0/cfn-guard-linux-1.0.0.tar.gz
       - tar -xvf cfn-guard-linux-1.0.0.tar.gz
  build:
    commands:
       - ./cfn-guard-linux/cfn-guard --version
       - ./cfn-guard-linux/cfn-guard check -t ec2_template.yml -r ec2_template.ruleset --strict-checks

ビルド実行を行い、望む結果が得られたことを確認
result4.png

まとめ

実際に使ってみないとわからないことが多いので、とりあえず試すことは重要ですね。

また、現状ではサンプルでは1テンプレート、1rulesetになってますが、実運用を考慮した際、テンプレートごとにrulesetを作成することは現実的ではありません。

どの単位でCFnテンプレートを作成するのかにもよるが、Strict Checks用のrulesetとそれ以外のrulesetの2つで運用するのがベターなのかな?
ここら辺は運用しながら自分なりの答えを見つけたいと思います。

最後に今回作成したテンプレート、ルールセット、buildspec.ymlは以下となります。

ec2_template.yml
Resources:
  NewInstance1:
    Type: AWS::EC2::Instance
    Properties:
      DisableApiTermination: true
      SubnetId: subnet-XXXXXXXXX
      ImageId: ami-00f045aed21a55240
      InstanceInitiatedShutdownBehavior: stop
      InstanceType: t2.micro
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 500
            VolumeType: gp2
            Encrypted: false
        - DeviceName: /dev/sda2
          Ebs:
            VolumeSize: 50
            VolumeType: gp2
            Encrypted: false
        - DeviceName: /dev/sda3
          Ebs:
            VolumeSize: 10
            VolumeType: gp2
      KeyName: sample-key
      Monitoring: false
      SecurityGroupIds:
        - sg-XXXXXXXXXXXXXXXXX
ec2_template.ruleset
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.Encrypted != false
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.VolumeSize <= 100
buildspec.yml
version: 0.2

phases:
  install:
    commands:
       - wget https://github.com/aws-cloudformation/cloudformation-guard/releases/download/1.0.0/cfn-guard-linux-1.0.0.tar.gz
       - tar -xvf cfn-guard-linux-1.0.0.tar.gz
  build:
    commands:
       - ./cfn-guard-linux/cfn-guard --version
       - ./cfn-guard-linux/cfn-guard check -t ec2_template.yml -r ec2_template.ruleset --strict-checks
4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0