@enfo/aws-cdkompliance
v1.1.0
Published
Tagging and compliant resources using the CDK
Downloads
69
Readme
Introduction
Compliant resource Constructs and tagging using the CDK. The compliant Constructs make it easier to reduce your number of Security Hub security findings. If you are using CloudFormation rather than the CDK you can check the unit tests on the source repository to get an idea of what you need to fix.
The tagging part of this package is tied to Enfo and its customers. Enfo is a Managed Service Provider for AWS. You can of course use the package without being a customer, but the tags might have no effect depending on your AWS organization setup.
Installation
The package should be installed as a dependency.
npm install @enfo/aws-cdkompliance --save
Compliant resource Constructs
In Security Hub you can find a list of security findings. We refer to resources with such findings as non-compliant. This package exposes compliant Constructs which are extensions of CDK Constructs. They have been modified to throw errors during CDK synthesis should you try to use a poorly set Construct property. Most Constructs require no input from you and will be compliant by default.
When possible the default Props used to create the Construct are exposed as well.
Application Load Balancer
The following features are available for Application Load Balancer.
- ApplicationLoadBalancer, compliant Application Load Balancer Construct. Will throw if non-compliant properties are passed
- defaultApplicationLoadBalancerProps, the ApplicationLoadBalancerProps used to make the Application Load Balancer compliant
The following Security Hub findings are managed by the ApplicationLoadBalancer Construct.
- [ELB.4] Application load balancers should be configured to drop HTTP headers
- [ELB.5] Application and Classic Load Balancers logging should be enabled
- [ELB.6] Application Load Balancer deletion protection should be enabled
Application Load Balancer creation example.
import { ApplicationLoadBalancer, Bucket } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
import { Vpc } from 'aws-cdk-lib/aws-ec2'
const stack = new Stack(undefined, 'Stack', { env: { region: 'eu-west-1' } } )
const vpc = new Vpc(stack, 'VPC')
const bucket = new Bucket(stack, 'Bucket')
const alb = new ApplicationLoadBalancer(stack, 'ALB', { vpc })
alb.logAccessLogs(bucket)
CloudFront
The following features are available for CloudFront.
- Distribution, compliant CloudFront Distribution Construct. Will throw if non-compliant properties are passed
- defaultDistributionProps, the DistributionProps used to make the distribution compliant
The following Security Hub findings are managed by the Distribution Construct.
- [CloudFront.1] CloudFront distributions should have a default root object configured
- [CloudFront.5] CloudFront distributions should have logging enabled
- [CloudFront.6] CloudFront distributions should have AWS WAF enabled
CloudFront Distribution creation example.
import { Distribution } from '@enfo/aws-cdkompliance'
import { ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront'
import { HttpOrigin } from 'aws-cdk-lib/aws-cloudfront-origins'
import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
const webAcl = new CfnWebACL(stack, 'WebACL', {
scope: 'CLOUDFRONT',
defaultAction: { allow: {} },
visibilityConfig: {
cloudWatchMetricsEnabled: false,
metricName: 'metricName',
sampledRequestsEnabled: false,
}
})
new Distribution(stack, 'Distribution', {
defaultBehavior: {
origin: new HttpOrigin('example.com'),
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
},
webAclId: webAcl.attrId
})
DynamoDB
The following features are available for DynamoDB.
- Table, Construct defaulting to using BillingMode.PAY_PER_REQUEST and point in time recovery enabled
The following Security Hub findings are managed by the Table Construct.
- [DynamoDB.1] DynamoDB tables should automatically scale capacity with demand, softly enforced
- [DynamoDB.2] DynamoDB tables should have point-in-time recovery enabled, enabled by default in the Construct. Can be disabled and the findings suppress
Table creation example without billingMode specified. Will default to PAY_PER_REQUEST. The Table will not be tagged to suppress warnings. The same will happen if billingMode is set to PAY_PER_REQUEST.
import { Table } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
import { AttributeType, BillingMode } from 'aws-cdk-lib/aws-dynamodb'
const stack = new Stack()
new Table(stack, 'Table', {
partitionKey: {
name: 'pk',
type: AttributeType.STRING
}
})
KMS
The following features are available for KMS.
- Key, compliant KMS Key Construct. Will throw if non-compliant properties are passed
- defaultKeyProps, the KeyProps used to enforce compliance if you don't supply your own
While we do not enforce alias on KeyProps we do recommend that you set it.
Key creation example
import { Key } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new Key(stack, 'Key', { alias: 'my-key' })
Lambda
The following features are available for Lambda.
- Function, compliant Lambda Function Construct
The following Security Hub findings are managed by the Function Construct.
- [Lambda.2] Lambda functions should use supported runtimes, hard enforced. We limit the supported runtimes to only the latest for each language. Custom runtimes are also fine
Function creation example
import { Function } from '@enfo/aws-cdkompliance'
import { Code, Runtime } from 'aws-cdk-lib/aws-lambda'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new Function(stack, 'Function', {
runtime: Runtime.NODEJS_16_X,
handler: 'handler',
code: Code.fromInline('myCode')
})
Lambda NodeJS
The following features are available for Lambda NodeJS.
- NodejsFunction, compliant NodeJS Lambda NodejsFunction Construct
The following Security Hub findings are managed by the NodejsFunction Construct.
- [Lambda.2] Lambda functions should use supported runtimes, hard enforced. We limit the supported runtimes to only the latest for each language. Custom runtimes are also fine
NodejsFunction creation example
import { NodejsFunction } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new NodejsFunction(stack, 'Function', {
handler: 'handler',
entry: path.join(__dirname, '../src/hello-world.ts')
})
Logs
The following features are available for Logs.
- LogGroup, compliant Log Group Key Construct. Will throw if non-compliant properties are passed
- defaultLogGroupProps, the LogGroupProps used to enforce compliance if you don't supply your own
LogGroup creation example
import { LogGroup } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new LogGroup(stack, 'LogGroup')
RDS
The following features are available for RDS
- DatabaseCluster, compliant DatabaseCluster Construct
- defaultDatabaseClusterProps, the DatabaseClusterProps used to make the DatabaseCluster compliant
- defaultInstanceProps, the InstanceProps used to make the DatabaseCluster compliant
- DatabaseEnvironment, to indicate the how a DatabaseInstance will be used
- DatabaseInstance, compliant DatabaseInstance Construct
- defaultDatabaseInstanceProps, the DatabaseInstanceProps used to make the DatabaseInstance compliant
The following Security Hub findings are managed by the DatabaseCluster Construct.
- [RDS.4] RDS cluster snapshots and database snapshots should be encrypted at rest
- [RDS.7] RDS clusters should have deletion protection enabled
- [RDS.12] IAM authentication should be configured for RDS clusters
- [RDS.13] RDS automatic minor version upgrades should be enabled
- [RDS.16] RDS DB clusters should be configured to copy tags to snapshots
DatabaseCluster creation example.
import { DatabaseCluster } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
import { Vpc } from 'aws-cdk-lib/aws-ec2'
import { AuroraPostgresEngineVersion, DatabaseClusterEngine } from 'aws-cdk-lib/aws-rds'
const stack = new Stack()
const vpc = new Vpc(stack, 'VPC')
new DatabaseCluster(stack, 'DatabaseCluster', {
engine: DatabaseClusterEngine.auroraPostgres({ version: AuroraPostgresEngineVersion.VER_13_4 }),
instanceProps: {
vpc
}
})
The following Security Hub findings are managed by the DatabaseInstance Construct.
- [RDS.2] RDS DB instances should prohibit public access, determined by the PubliclyAccessible configuration
- [RDS.3] RDS DB instances should have encryption at rest enabled
- [RDS.4] RDS cluster snapshots and database snapshots should be encrypted at rest
- [RDS.5] RDS DB instances should be configured with multiple Availability Zones
- [RDS.8] RDS DB instances should have deletion protection enabled
- [RDS.10] IAM authentication should be configured for RDS instances
- [RDS.13] RDS automatic minor version upgrades should be enabled
- [RDS.17] RDS DB instances should be configured to copy tags to snapshots
Note that DatabaseInstance defaults to MultiAZ, and you need to set environment: NOT_PRODUCTION
to be able to set MultiAZ to false.
DatabaseInstance creation example.
import { DatabaseEnvironment, DatabaseInstance } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
import { Vpc } from 'aws-cdk-lib/aws-ec2'
import { DatabaseInstanceEngine, PostgresEngineVersion } from 'aws-cdk-lib/aws-rds'
const stack = new Stack()
const vpc = new Vpc(stack, 'VPC')
new DatabaseInstance(stack, 'Database', {
vpc,
engine: DatabaseInstanceEngine.postgres({ version: PostgresEngineVersion.VER_13_4 }),
environment: DatabaseEnvironment.NOT_PRODUCTION,
multiAz: false
})
S3
The following features are available for S3.
- Bucket, compliant S3 Bucket Construct
- defaultBucketProps, the BucketProps used to enforce compliance if you don't supply your own
The following Security Hub findings are managed by the Bucket Construct.
- [S3.1] S3 Block Public Access setting should be enabled
- [S3.2] S3 buckets should prohibit public read access
- [S3.3] S3 buckets should prohibit public write access
- [S3.4] S3 buckets should have server-side encryption enabled
- [S3.5] S3 buckets should require requests to use Secure Socket Layer
- [S3.8] S3 Block Public Access setting should be enabled at the bucket level
Bucket creation example
import { Bucket } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new Bucket(stack, 'MyBucket', { bucketName: 'my-bucket' })
SNS
The following features are available for SNS. SNS requires a KMS Key Construct to be compliant.
- Topic, compliant SNS Topic Construct. Will throw if non-compliant properties are passed
The following Security Hub findings are managed by the Topic Construct.
Topic creation example
import { Key, Topic } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new Topic(stack, 'Topic', {
masterKey: new Key(stack, 'Key')
})
SQS
The following features are available for SQS.
- Queue, compliant SQS Queue Construct. Will throw if non-compliant properties are passed
- defaultQueueProps, the QueueProps used to make the queue compliant
The following Security Hub findings are managed by the Queue Construct.
Queue creation example.
import { Queue } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
new Queue(stack, 'Queue', { queueName: 'my-queue' })
Tagging
This section largely caters to Enfo customers. If you are not an Enfo customer you can still achieve the functionality described for enableBackups.
enableBackups
If you are an Enfo customer you can enable backups of databases using tags. This can easily be achieved by using the function enableBackups. This function can be applied on a Resource, Stack or App level.
If you are not an Enfo customer can achieve backups by reading this AWS guide.
Enabling backups of a single resource.
import { enableBackups, Table } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
import { AttributeType } from 'aws-cdk-lib/aws-dynamodb'
const stack = new Stack()
const myTable = new Table(stack, 'Table', {
partitionKey: {
name: 'pk',
type: AttributeType.STRING
}
})
enableBackups(myTable)
Enable backups of an entire stack.
import { enableBackups } from '@enfo/aws-cdkompliance'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
enableBackups(stack)
Enable backups of an entire app.
import { enableBackups } from '@enfo/aws-cdkompliance'
import { App } from 'aws-cdk-lib'
const app = new App()
enableBackups(app)
Where backups are stored can be controlled via the second parameter, backupPlan. It defaults to STANDARD which creates backups in the region in which the resource exists.
import { enableBackups, BackupPlan } from '@enfo/aws-cdkompliance'
import { App } from 'aws-cdk-lib'
const app = new App()
enableBackups(app, BackupPlan.STOCKHOLM)
exemptBucketFromBlockPublicAutoFix
Buckets in an AWS account managed by Enfo will automatically have [S3.1] S3 Block Public Access setting should be enabled fixed. If you do no want this to happen you can use this tagging function to exempt the bucket.
import { exemptBucketFromBlockPublicAutoFix } from '@enfo/aws-cdkompliance'
import { Bucket } from 'aws-cdk-lib/aws-s3'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
const bucket = new Bucket(stack)
exemptBucketFromBlockPublicAutoFix(bucket)
exemptBucketFromSslAutoFix
Buckets in an AWS account managed by Enfo will automatically have [S3.4] S3 buckets should have server-side encryption enabled fixed. If you do no want this to happen you can use this tagging function to exempt the bucket.
import { exemptBucketFromSslAutoFix } from '@enfo/aws-cdkompliance'
import { Bucket } from 'aws-cdk-lib/aws-s3'
import { Stack } from 'aws-cdk-lib'
const stack = new Stack()
const bucket = new Bucket(stack)
exemptBucketFromSslAutoFix(bucket)