インフラ

cdk-nagを使ってテンプレートのセキュリティ的な問題を検出する

cdk

こんにちは、ちゃりおです。

CDKを色々なチームで使用していると、AWSにそこまで詳しくない人もCDKを書く機会が増えてきます。
そんなときには、危険な設定ができないようにするガードレールが欲しくなってきます。

SCPやPermissions Boundaryでアカウントレベルで、ルールを作るのもいいと思います。
しかし、上記の方法は「cdk deploy」するまでルールに準拠しているかわかりません。

そこで、AspectなどでTestを作ってテンプレート作成時点で検出するアプローチを行うことになると思います。
独自のルールをAspectで検出するのはいいと思うのですが、AWSのベストプラクティスのルールをすべて自分たちで定義するのは大変です。

そんなときに便利なのが、「cdk-nag」です。
今回は、「cdk-nag」について紹介します。

cdk-nagとは

githubで公開されています。
CDKで生成されるCloudFormationテンプレートにおけるベストプラクティスに沿っていない設定を検出してくれるツールです。

以下のルールに沿って、チェックしてくれます。

AWS Solutions
HIPAA Security
NIST 800-53 rev 4
NIST 800-53 rev 5
PCI DSS 3.2.1

デモ

cdk-nagを使って、ベストプラクティスに沿ったSQSを作成します。

SQSを普通に作ってcdk-nagでルールを検出してみる

cdk-nagをインストールします。

npm install cdk-nag

cdk v2を使っている場合は、「cdk-nag@^2.0.0」とかでv2のバージョンをインストールしてくれださい。(何も指定しないと2021/12時点では、v1のcdk-nagがインストールされます)

# bin/index.ts
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { SqsStack } from '../lib/sqs-stack';
import { Aspects } from 'aws-cdk-lib';
import { AwsSolutionsChecks } from 'cdk-nag';

const app = new cdk.App();
new SqsStack(app, 'CkdNagStack', {});

Aspects.of(app).add(new AwsSolutionsChecks()); #cdk-nagを使う
#lib/sqs-stack.ts
import { Stack, StackProps, Duration } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';

export class SqsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const queue = new sqs.Queue(this, 'Queue', {
      visibilityTimeout: Duration.seconds(300),
    });
  }
}

上記のファイルを用意したら、コマンドを実行します。

npm run cdk synth
[Error at /CkdNagStack/Queue/Resource] AwsSolutions-SQS2: The SQS Queue does not have server-side encryption enabled.

[Error at /CkdNagStack/Queue/Resource] AwsSolutions-SQS3: The SQS queue does not have a dead-letter queue (DLQ) enabled or have a cdk_nag rule suppression indicating it is a DLQ.

ルールに沿っていない設定があり、エラーが表示されました。
エラーメッセージを見てみると、原因は以下のようです。

  • サーバーサイドの暗号化がされていない
  • DLQの設定がされていない

cdk-nagで検出された問題を修正する

問題を修正します。

import { Stack, StackProps, Duration } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';

export class SqsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const dlQueue = new sqs.Queue(this, "DeadLetterQueue", {
      encryption: sqs.QueueEncryption.KMS_MANAGED
    })
    const queue = new sqs.Queue(this, 'Queue', {
      visibilityTimeout: Duration.seconds(300),
      encryption: sqs.QueueEncryption.KMS_MANAGED, // 暗号化を有効化
      deadLetterQueue: { // dlqを設定
        maxReceiveCount: 10,
        queue: dlQueue
      }
    });
  }
}

しかし、DLQのエラーが残っています。

[Error at /CkdNagStack/DeadLetterQueue/Resource] AwsSolutions-SQS3: The SQS queue does not have a dead-letter queue (DLQ) enabled or have a cdk_nag rule suppression indicating it is a DLQ.

よく読んでみると、どうやらDLQをルールから除外する必要があるみたいですね。

cdk-nagのルールの例外を設定する

READMEのsuppressing-ruleのところを参考に修正しました。
修正後は、エラーが無くなりCloudformationテンプレートが表示されました。


import { Stack, StackProps, Duration } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { NagSuppressions } from 'cdk-nag';

export class SqsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const dlQueue = new sqs.Queue(this, "DeadLetterQueue", {
      encryption: sqs.QueueEncryption.KMS_MANAGED
    })
    const queue = new sqs.Queue(this, 'Queue', {
      visibilityTimeout: Duration.seconds(300),
      encryption: sqs.QueueEncryption.KMS_MANAGED, // 暗号化を有効化
      deadLetterQueue: { // dlqを設定
        maxReceiveCount: 10,
        queue: dlQueue
      }
    });
    // dlQueueを除外
    NagSuppressions.addResourceSuppressions(dlQueue, [
      { id: "AwsSolutions-SQS3", reason: "DeadLetterQueue" }
    ])
  }
}

まとめ

cdk-nagについてでした。
数行追加するだけで、「AWS Solutions」や「HIPAA Security」のルールに沿っているかチェックできるのは、かなり便利だと思いました。
cdk-nagを使うことで、危険な設定のリソースを作られるリスクを減らすことができます。

事前に定義したルールに則ってリソースを作成することができるのも、CDKを使うメリットだと思います。
うまく活用してガードレールを作っていきたいです。

Amzonで「AWS」の本を見てみる

楽天で「AWS」の本をみてみる!!

cdk book
[書評]CDK使っている人は一度読んでおきたい「The CDK Book」こんにちは、ちゃりおです。 「The CDK Book」読んでみました。 CDKは比較的新しいIaCツールのため、実践的な内容につい...
CDK「aws-cdk-github-oidc」を使ってGithubActionsで引き受けれるIAMロールを作るこんにちは、ちゃりおです。 先日、OIDCを使ってGithubActionsにIAMロールを渡してAWS上の操作ができるようになりまし...
cdk
CDKでECSデプロイメントサーキットブレイカーの有効化時のサービス置き換えを回避するこんにちは、ちゃりおです。 CDKを使ってECSを運用しています。 運用中のECSサービスのデプロイメントサーキットブレイカーを有効化...