継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

CloudFormation テンプレートがルールに準拠しているかをチェックする CLI ツール『CloudFormation Guard』

タダです.

現在プレビューですが,「CloudFormation Guard」というコマンドラインツールが使えるようになりました.このツールは CloudForamtion テンプレートが定めたポリシーと照らして設定値として正しいのかをチェックします.

公式ブログ aws.amazon.com

GitHubリポジトリ github.com

CloudFormation Guard」 は3つのツールが提供されています.

  • CloudFormation Guard : 宣言型構文を使ったポリシーに適合しているかのチェック CLI ツール(cfn-guard)
  • CloudFormation Guard Lambda : Lambda での「CloudFormation Guard」チェックツール(cfn-guard-lambda)
  • CloudFormation Guard Rulegen : 既存のテンプレートから 「CloudFormation Guard」のルールを生成するツール(cfn-guard-rulegen)

この記事でcfn-guardの導入とチュートリアルを通してcfn-guardをどう使うのかついて学んだことをまとめていきます.

cfn-guard の初期セットアップ

cfn-guard の導入には Rust を入れておく必要があります.自分は macOS なので下記コマンドで Rust を導入しました.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

info: downloading installer

Welcome to Rust!
~中略~
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1
~中略~
Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell run source $HOME/.cargo/env
» rustc --version
rustc 1.44.0 (49cae5576 2020-06-01)

参考情報

www.rust-lang.org

次に,リポジトリをクローンしてcfn-guardディレクトリに移動後ビルドを行ないます.これでcfn-guardコマンドを使えるようにします.

github.com

» make
cargo build --release; cp target/release/cfn-guard ./bin
~中略~   
Compiling cfn-guard v0.5.0 (/Users/tada/aws-tools/cloudformation-guard/cfn-guard)
    Finished release [optimized] target(s) in 10m 08s

bin 配下にパスを通してあげれば使えるようになります.

cfn-guard --help
CloudFormation Guard 0.5.0
Check CloudFormation templates against rules

USAGE:
    cfn-guard [FLAGS] --rule_set <RULE_SET_FILE> --template <TEMPLATE_FILE>

FLAGS:
    -h, --help             Prints help information
    -s, --strict-checks    Fail resources if they're missing the property that a rule checks
    -v                     Sets the level of verbosity - add v's to increase output
    -V, --version          Prints version information
    -w, --warn_only        Show results but return an exit code of 0 regardless of rule violations

OPTIONS:
    -r, --rule_set <RULE_SET_FILE>    Rules to check the template against
    -t, --template <TEMPLATE_FILE>    CloudFormation Template

cfn-guard のチュートリアルで使い方を学ぶ

リポジトリExamples配下に WAF と EBS のテンプレートとポリシールールが配置されているのでチェックを走らせてみます.EBS のテンプレートをチェックしてみると6つの違反が検出されました.

» cfn-guard -t Examples/ebs_volume_template.json -r Examples/ebs_volume_template.ruleset
"[NewVolume2] failed because [Encrypted] is [false] and the permitted value is [true]"
"[NewVolume2] failed because [Size] is [99] and the permitted value is [100]"
"[NewVolume2] failed because [us-west-2c] is not in [us-east-1a,us-east-1b,us-east-1c] for [AvailabilityZone]"
"[NewVolume] failed because [Encrypted] is [false] and the permitted value is [true]"
"[NewVolume] failed because [Size] is [101] and the permitted value is [100]"
"[NewVolume] failed because [us-west-2b] is not in [us-east-1a,us-east-1b,us-east-1c] for [AvailabilityZone]"
Number of failures: 6

EBS のポリシーセットとテンプレート詳細

EBS のポリシーを見てみると以下のルールがあります.

  • EBS の暗号化が必須
  • EBS の Availability Zone の指定
  • EBS ボリュームサイズが 100 GiB を固定化
let encryption_flag = true
let allowed_azs = [us-east-1a,us-east-1b,us-east-1c]

AWS::EC2::Volume AvailabilityZone IN %allowed_azs
AWS::EC2::Volume Encrypted == %encryption_flag
AWS::EC2::Volume Size == 100

EBS テンプレートをみると以下の定義となっていました.

{Resources”: {NewVolume” : {Type” : “AWS::EC2::Volume”,
            “Properties” : {Size” : 101,
                “Encrypted”: false,
                “AvailabilityZone” : “us-west-2b”
            }
        },
        “NewVolume2” : {Type” : “AWS::EC2::Volume”,
            “Properties” : {Size” : 99,
                “Encrypted”: false,
                “AvailabilityZone” : “us-west-2c”
            }
        }
    }
}

ポリシールールとの違反ポイントを整理しました.

  • テンプレートでは EBS の暗号化をしない
    • EBS の暗号化が必須になるポリシーに違反
  • テンプレートでは EBS ボリュームの Availability Zone の指定が us-west-2b と us-west-2c
    • Availability Zone の指定 が us-east-1a,us-east-1b,us-east-1c のいずれかなのでポリシーに違反
  • テンプレートでは EBS ボリュームサイズは 101 GiB と 99 GiB
    • 100 GiB の指定でないためポリシーに違反

この結果を見ると,プロジェクトや組織内でのルールに準拠したテンプレートを開発できているかどうかのチェックを動化しやすいと感じました.リポジトリにも記載がありましたが,次のようなユースケースが載っています.

Q: Why should you use Guard?

A: Guard solves a number of use-cases:

It can be used to check repositories of CloudFormation templates for policy violations with automation. It can be a deployment gate in a CI/CD pipeline. It allows you to define a single source-of-truth for what constitutes valid infrastructure definitions. Define rules once and have them run both locally and as lambdas in your AWS account for integration with other AWS services. It allows for pre-deployment safety checks of your CloudFormation template resources. You can both require settings to be included and prohibit configurations that have caused issues previously. It’s easy to get started. You can extract rules you want from existing, known-good templates using the CloudFormation Guard Rulegen auto-generation tool.

テンプレートの違反チェックの自動化,CI/CD パイプラインへの組み込み,既存のテンプレートにも適用してのチェックなどが挙がっていました.加えて複数人の開発においてローカルとリポジトリにあげた後等にチェックする機構に有効かと思います.

cfn-guard の実践(EC2 の CloudFormation テンプレートチェック)

cfn-guardを実践してみます.簡単な EC2 の CloudFormation テンプレートをチェックするルールを作っていきます.Amazon Linux2 の t3.small で EBS ボリュームとして 20 GiB がアタッチされるサーバーを作るテンプレートを用意します.

Resources:
  TestEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: "ami-0a1c2ec61571737db"
      KeyName: "testkey"
      InstanceType: t3.small
      BlockDeviceMappings:
      - DeviceName: "/dev/sda1"
        Ebs:
          VolumeType: "gp2"
          VolumeSize: "20"

テンプレートのルールの記法は <CloudFormation Resource Type> <Property> == <Value> が基本です.簡単な次のルールを作ってみました.

  • AMI の ID は指定のものを使う
  • インスタンスタイプ は t3.micro に固定
  • EBS ボリュームサイズも 20 GiB に固定
let ami_id = ami-0a1c2ec61571737db

AWS::EC2::Instance ImageId == %ami_id
AWS::EC2::Instance InstanceType == t3.micro
AWS::EC2::Volume Size == 20

記法ルールの解説ページ github.com

意図的にインスタンスタイプのみが違反するように作ったので,インスタンスタイプが違反する結果になりました.

» cfn-guard -t test-ec2_template.yaml -r test-ec2_template.ruleset
"[TestEC2Instance] failed because [InstanceType] is [t3.small] and the permitted value is [t3.micro]"
Number of failures: 1

まとめ

CloudFormation Guard」のセットアップとチュートリアルを通して使い方を学べました.このツールは下記の issue でも述べられていますが「CloudFormation Guard」関連のツールcfn-lint と「CloudFormation Guard」を相互補完的に使うことでに静的解析しつつガバメントを有効に利かせるツールになりそうです.

github.com

関連情報

@toricls さんもcfn-guardの ECS サンプルを公開されているので気になる人は要チェックです!

github.com