CodeWithYou

Optimizing Application Security. A Guide to Using cdk_nag with AWS CDK

Published on
Authors
e application security with AWS CDK and cdk_nag
Photo by AI

Introduction

Ensuring robust application security is crucial for modern cloud-based applications. In this blog post, we will delve into the world of AWS Cloud Development Kit (CDK) and cdk_nag, a powerful tool that helps enhance application security. By leveraging cdk_nag with AWS CDK, you can identify and address potential security issues, ensuring a secure and reliable deployment process.

What is cdk_nag?

cdk_nag is a tool that interacts with your AWS CDK application and checks for security issues. It can generate a report highlighting security issues in your application, helping you ensure that it is secure before deployment. The rules provided by cdk_nag are based on the AWS Well-Architected Framework and AWS Security Best Practices. You can also create custom rules using the cdk_nag API.

How to use cdk_nag?

Using cdk_nag is straightforward. Follow these steps to incorporate it into your AWS CDK application:

Step 1: Create an AWS CDK Application

Create a baseline AWS CDK application using TypeScript or the language of your choice. Define your infrastructure components using AWS CDK constructs.

import * as cdk from '@aws-cdk/core'
import * as s3 from '@aws-cdk/aws-s3'

export class CdkNagExampleStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    // define a s3 bucket
    new s3.Bucket(this, 'MyFirstBucket', {
      bucketName: 'my-first-bucket',
    })
  }
}

If we run cdk synth we will get the following output inside the cdk.out folder:

Resources:
  MyFirstBucketF68F3FF0:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: my-first-bucket

Step 2: Install and Configure cdk_nag

Install the cdk_nag package as a development dependency in your project:

npm install --save-dev cdk_nag

Next, configure cdk_nag by adding the necessary imports and annotations to your AWS CDK application code. Here's an example:

#!/usr/bin/env node
import 'source-map-support/register'
import * as cdk from 'aws-cdk-lib'
import { CdkStarterStackStack } from '../lib/cdk-starter-stack-stack'
import * as cdk_nag from 'cdk-nag'

const app = new cdk.App()

// Add the cdk-nag AwsSolutions Pack with extra verbose logging enabled.
// This will log all rules that are checked and the results of those checks.
cdk.Aspects.of(app).add(new cdk_nag.AwsSolutionsChecks({ verbose: true }))

new CdkStarterStackStack(app, 'CdkStarterStackStack', {})

Now, if we run cdk synth again, we will get the following output in console:


[Error at /CdkStarterStackStack/TestBucket/Resource] AwsSolutions-S1: The S3 Bucket has server access logs disabled. The bucket should have server access logging enabled to provide detailed records for the requests that are made to the bucket.

[Error at /CdkStarterStackStack/TestBucket/Resource] AwsSolutions-S10: The S3 Bucket or bucket policy does not require requests to use SSL. You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on Amazon S3 bucket policies.

Found errors
Advertisement

It also generate a csv report file inside the cdk.out folder:

Rule ID,Resource ID,Compliance,Exception Reason,Rule Level,Rule Info
"AwsSolutions-S1","CdkStarterStackStack/TestBucket/Resource","Non-Compliant","N/A","Error","The S3 Bucket has server access logs disabled."
"AwsSolutions-S2","CdkStarterStackStack/TestBucket/Resource","Compliant","N/A","Error","The S3 Bucket does not have public access restricted and blocked."
"AwsSolutions-S5","CdkStarterStackStack/TestBucket/Resource","Compliant","N/A","Error","The S3 static website bucket either has an open world bucket policy or does not use a CloudFront Origin Access Identity (OAI) in the bucket policy for limited getObject and/or putObject permissions."
"AwsSolutions-S10","CdkStarterStackStack/TestBucket/Resource","Non-Compliant","N/A","Error","The S3 Bucket or bucket policy does not require requests to use SSL."

Step 3: Fix the issues

You can see there are 2 error issues in the report. To fix these issues, we can Remediating or Suppressing them.

Suppressing issues

To suppress an issue, we need to add a cdk_nag annotation to the resource that is causing the issue. For example, to suppress the AwsSolutions-S1 issue, we can add the following annotation to the s3.Bucket resource:

// suppress AwsSolutions-S1 rule
NagSuppressions.addStackSuppressions(this, [
  {
    id: 'AwsSolutions-S1',
    reason: 'This is a test stack.',
  },
])

Remediating issues

Remediate issues is better than suppressing them. To remediate an issue, we need to fix the resource that is causing the issue. For example, to remediate the AwsSolutions-S1 issue, we can add the following code to the s3.Bucket resource:

// Remediating AwsSolutions-S10 by enforcing SSL on the bucket.
const bucket = new s3.Bucket(this, 'TestBucket', {
  enforceSSL: true,
})

Finally, the stack should look like this:

import { Stack, StackProps, RemovalPolicy } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as s3 from 'aws-cdk-lib/aws-s3'
import { NagSuppressions } from 'cdk-nag'

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

    // suppress AwsSolutions-S1 rule
    NagSuppressions.addStackSuppressions(this, [
      {
        id: 'AwsSolutions-S1',
        reason: 'This is a test stack.',
      },
    ])

    // Remediating AwsSolutions-S10 by enforcing SSL on the bucket.
    const bucket = new s3.Bucket(this, 'TestBucket', {
      enforceSSL: true,
    })
  }
}

Now, if we run cdk synth again, we will get the following output in console:

Metadata:
  cdk_nag:
    rules_to_suppress:
      - reason: This is a test stack.
        id: AwsSolutions-S1
Resources:
  TestBucket560B80BC:
    Type: AWS::S3::Bucket
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: CdkStarterStackStack/TestBucket/Resource
  TestBucketPolicyBA12ED38:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: TestBucket560B80BC
      PolicyDocument:
        Statement:
          - Action: s3:*
            Condition:
              Bool:
                aws:SecureTransport: "false"

...

It means that the AwsSolutions-S1 issue is suppressed and the AwsSolutions-S10 issue is remediated. Now the stack is ready to be deployed cdk deploy

Conclusion

By incorporating cdk_nag into your AWS CDK development workflow, you can significantly enhance your application's security posture. With its robust security checks and comprehensive reports, cdk_nag empowers you to identify and address potential vulnerabilities proactively. Implementing these security measures not only ensures a secure deployment but also helps maintain the integrity and reliability of your cloud-based applications.

Take the initiative to optimize your application security today and leverage the power of cdk_nag with AWS CDK. Safeguard your applications and provide your users with a secure and trustworthy experience.

References

The source code of this article can be found in the following repository:

https://github.com/buithaibinh/blog-tutorials/tree/main/cdk-nag

Advertisement