Optimizing Application Security. A Guide to Using cdk_nag with AWS CDK
- Published on
- Authors
- Name
- Binh Bui
- @bvbinh
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
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