AWS

Snyk IaCとcfn-nagを比較する

ryo

はじめまして、今年4月に新卒入社したryoと申します!

DWSではAWS環境を構築する際にIaCを用いています。
非常に便利なIaCですが、セキュアなAWS環境を作成するためには使用者がベストプラクティスを熟知しておく必要があります。
その際に便利なのが、IaCのコードに対して静的解析を行い、セキュリティ上のリスクを検知してくれるツールです。

このブログでは、実際のプロジェクトに導入した際に調査したcfn-nagSnyk IaC という2つのツールの比較を行います。
2つの優劣をつける目的ではなく、あくまでそれぞれの違いについてフォーカスを当てます。
IaCは全てAWS CloudFormationの使用を想定しています。

IaCに対して静的解析を行う意義

AWSに限らず、クラウド環境における設定のミスは大きなセキュリティインシデントに直結します。
記憶に新しいものとして、ある企業のS3バケットがパブリックに公開されたまま、バケット内の情報にアクセス出来る状態で放置してしまっていたというインシデントがありました。

このようなリスクを事前に検知するために活躍するのが、静的解析です。
IaCに対する静的解析は、様々なセキュリティリスクを開発者にフィードバックすることで、安全なクラウド環境構築の手助けになります。

Snyk IaCとcfn-nagの比較

  • 料金
  • 使用方法
  • 検知内容や挙動の違い

上記項目について比較を行います。

使用するCLIのバージョンは以下になります。

  • cnf-nag
$ cfn_nag_scan --version
0.8.10
  • Snyk CLI
$ snyk --version
1.1061.0

料金

cfn-nag

cfn-nagの場合はOSSとして公開されていて、無料で利用が可能です。

Snyk IaC

Snykの場合はSaaSとして提供されているのでログインが必要になります。
有償のプランも存在しますが、IaCスキャンは無償で利用可能です。無償プランの場合はIaCの一ヶ月の解析回数に制限があるなど注意が必要です。
プラン毎の違いはこちらのリンクをご参照ください。
https://snyk.io/plans/

利用方法について

cfn-nag

cfn-nagの場合はCLIやVSCode Pluginを通じて利用可能です。
CLIのインストールについてはこちらをご参照ください。
https://github.com/stelligent/cfn_nag#installation

CLIで利用する場合は以下のコマンドで実行可能です。

$ cfn_nag_scan --input-path `ファイルパス`

重要度として、WarningsとFailuresという2つが存在しており、それぞれ警告が表示された場合でCLIのexit codeが変わります。

  • Failuresの場合は0以外
  • Warningsの場合は0

Snyk IaC

Snyk IaCの場合はGitリポジトリや各種IDEとの統合、CLIなど様々な方法で利用が可能です。
またSaaSのため、Web UIも用意されており、より気軽に利用が可能になっています。

CLIの場合は以下のコマンドになります。

$ snyk iac test `ファイルパス`

重要度としてLow、Medium、High、Criticalの4つが存在しており、それに応じてCLIのexit codeが変わる仕組みは同じになります。

  • 何かしらの脆弱性が検出された場合は1
  • 脆弱性が発見されなかった場合は0

という形になっています。
詳しくはこちらを参照ください。
https://docs.snyk.io/snyk-cli/commands/iac-test#exit-codes

CLIにフォーカスした場合、使い心地はほぼ変わりありません。
違いとして、CLIのexit codeの挙動や、CLI以外の利用方法の豊富さが挙げられます。

検知内容の違い

以下のテンプレートに対して、CLIを利用したスキャンを行うことを想定します。
こちらはAuroraのクラスターを作成するだけのCloudFormationになっています。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  Username:
    Type: String
  Password:
    Type: String
    NoEcho: true
Resources:
  DBCluster:
    Type: AWS::RDS::DBCluster
    DeletionPolicy: Retain
    Properties:
      DBClusterIdentifier: my-cluster1
      DeletionProtection: true
      Engine: aurora-mysql
      EngineVersion: 5.7.mysql_aurora.2.09.2
      MasterUsername: !Ref Username
      MasterUserPassword: !Ref Password
      StorageEncrypted: false # 意図的にfalseにしてみる

cfn-nag

cfn-nagにてルール一覧を確認する際は以下のコマンドを実行します。

# 全てのルールを表示する
$ cfn_nag_rules

# サービス毎に表示する
$ cfn_nag_rules | grep RDS

全てのルールが一覧で表示されるため、AWSサービス毎に確認する場合はgrep推奨です

cfn-nagでIaCの解析を行います。

❯ cfn_nag_scan --input-path template.yml
------------------------------------------------------------
template.yml
------------------------------------------------------------------------------------------------------------------------
| FAIL F26
|
| Resource: ["DBCluster"]
| Line Numbers: [14]
|
| RDS DBCluster should have StorageEncrypted enabled

Failures count: 1
Warnings count: 0

cfn-nagでは、

  • 暗号化オプションが無効化されていること

のみがセキュリティリスクとして指摘されました。

Snyk IaC

Snyk IaCの場合は、以下のページにルールがまとまっています。
こちらは各サービス毎にルールが見やすくまとまっています。
https://snyk.io/security-rules/

Snyk CLIを使いテンプレートの解析を行なってみます。

❯ snyk iac test template.yml

Snyk Infrastructure as Code

✔ Test completed.

Issues

Medium Severity Issues: 2

  [Medium] RDS cluster does not have encryption enabled
  Info:    RDS cluster does not have encryption enabled which means data is stored on cluster in plaintext. In the occurrence of a data breach, sensitive data stored on the RDS cluster will be accessible
  Rule:    https://snyk.io/security-rules/SNYK-CC-AWS-439
  Path:    [DocId: 0] > Resources[DBCluster] > Properties > StorageEncrypted
  File:    template.yml
  Resolve: Set `Properties.StorageEncrypted` attribute to `true`

  [Medium] IAM authentication for RDS cluster is disabled
  Info:    IAM authentication for RDS cluster is disabled. IAM integration allows you to avoid using passwords in favour of short lived tokens.
  Rule:    https://snyk.io/security-rules/SNYK-CC-AWS-710
  Path:    [DocId: 0] > Resources[DBCluster] > Properties > EnableIAMDatabaseAuthentication
  File:    template.yml
  Resolve: Set `Properties.EnableIAMDatabaseAuthentication` attribute to `true`

-------------------------------------------------------

Test Summary

  Organization: xxxxxxxxxx
  Project name: xxxxxxxxxxx

✔ Files without issues: 0
✗ Files with issues: 1
  Ignored issues: 0
  Total issues: 2 [ 0 critical, 0 high, 2 medium, 0 low ]

-------------------------------------------------------

Snykの場合だと

  • 暗号化オプションが無効化されていること
  • DBのIAM認証が無効化されていること

の2点がセキュリティリスクとして検知されています。
それに加えて、セキュリティリスクに対する対応策も教えてくれるので開発者フレンドリーに感じます。

このように同じテンプレートに対する静的解析だとしても、両者で検出項目はかなり異なるので、使用する前に検知ルールについて把握しておく必要があります。

Parametersを含めた場合の挙動

またCloudFormationのParametersを使用した場合の挙動が両者では異なります。

ここでは以下のテンプレートを想定します。最初のテンプレートとの違いは StorageEncrypted の値がParameters経由で渡されていることです。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  StorageEncrypted:
    Type: String
  Username:
    Type: String
  Password:
    Type: String
    NoEcho: true
Resources:
  DBCluster:
    Type: AWS::RDS::DBCluster
    DeletionPolicy: Retain
    Properties:
      DBClusterIdentifier: my-cluster1
      DeletionProtection: true
      Engine: aurora-mysql
      EngineVersion: 5.7.mysql_aurora.2.09.2
      MasterUsername: !Ref Username
      MasterUserPassword: !Ref Password
      StorageEncrypted: !Ref StorageEncrypted

cfn-nag

cnf-nagにて、Parametersを含めた静的解析を行う場合は、ParametersをJSONファイルに書く必要があります。
https://github.com/stelligent/cfn_nag#setting-template-parameter-values

今回はStorageEncryptedのみなのでJSONファイルは以下の形になります。

{
    "Parameters": {
      "StorageEncrypted": "false"
    }
}

--parameter-values-path 'JSONファイルのパス'をコマンドに付与することでParametersの指定が可能です。
まず"StorageEncrypted": "false"でスキャンを行なってみます。

❯ cfn_nag_scan --input-path template.yml --parameter-values-path param.json
------------------------------------------------------------
template.yml
------------------------------------------------------------------------------------------------------------------------
| FAIL F26
|
| Resource: ["DBCluster"]
| Line Numbers: [14]
|
| RDS DBCluster should have StorageEncrypted enabled

Failures count: 1
Warnings count: 0

falseの場合はこのように、リスクとして検出されました。

次は "StorageEncrypted": "true" でスキャンを行います。

❯ cfn_nag_scan --input-path template.yml --parameter-values-path param.json
------------------------------------------------------------
template.yml
------------------------------------------------------------
Failures count: 0
Warnings count: 0

今度は、検出無しという結果になりました。cfn-nagではParametersの値を考慮した上での解析が可能になっています。
cfn-nagでは他にもConditionsやMappingsなどいくつかのCloudFormationの機能にも対応しています。
詳しくはREADMEをご確認ください

Snyk IaC

Snyk CLIの場合はParametersを渡すオプションは存在せず、テンプレートファイルからParametersを参照している場合はセキュリティリスクとして検出されてしまいます。

❯ snyk iac test template.yml

Snyk Infrastructure as Code

✔ Test completed.

Issues

Medium Severity Issues: 2

  [Medium] RDS cluster does not have encryption enabled
  Info:    RDS cluster does not have encryption enabled which means data is stored on cluster in plaintext. In the occurrence of a data breach, sensitive data stored on the RDS cluster will be accessible
  Rule:    https://snyk.io/security-rules/SNYK-CC-AWS-439
  Path:    [DocId: 0] > Resources[DBCluster] > Properties > StorageEncrypted
  File:    template.yml
  Resolve: Set `Properties.StorageEncrypted` attribute to `true`

  [Medium] IAM authentication for RDS cluster is disabled
  Info:    IAM authentication for RDS cluster is disabled. IAM integration allows you to avoid using passwords in favour of short lived tokens.
  Rule:    https://snyk.io/security-rules/SNYK-CC-AWS-710
  Path:    [DocId: 0] > Resources[DBCluster] > Properties > EnableIAMDatabaseAuthentication
  File:    template.yml
  Resolve: Set `Properties.EnableIAMDatabaseAuthentication` attribute to `true`

-------------------------------------------------------

Test Summary

  Organization: ryo.sakurai
  Project name: go_decentralized_service

✔ Files without issues: 0
✗ Files with issues: 1
  Ignored issues: 0
  Total issues: 2 [ 0 critical, 0 high, 2 medium, 0 low ]

-------------------------------------------------------

この場合は、該当ルールのignoreなどの対応が必要になると思われます。

まとめ

この記事では、料金・使用方法・検出項目・CFnパラメータがあった場合の挙動の比較を行いました。
同じ目的のツールでも様々な違いがあり、実際に技術選定を行う場合はこの他にも、カスタムルールの作成・CI/CD・IDEとのインテグレーションなど様々な要素があると思います。
次のブログでそのあたりも書けたらなと思っています。
技術選定の参考になれば幸いでございます。

AUTHOR
ryo
ryo
記事URLをコピーしました