eslint-plugin-awscdk
v0.0.65
Published
<!--BEGIN STABILITY BANNER-->
Downloads
1,855
Readme
ESLint Plugin for AWS CDK
This module is experimental and under active development. Features are subject to non-backward compatible changes or removal in any future version. These are not subject to the Semantic Versioning model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package.
How to use
Install
npm install --save-dev eslint-plugin-awscdk
Configure
Using ESLint configs
Using projen
import { AwsCdkTypeScriptApp } from 'projen';
const project = new AwsCdkTypeScriptApp({
...
devDeps: [
'eslint-plugin-awscdk',
],
...
});
project.eslint?.config.plugins.push('awscdk');
project.eslint?.config.extends.push('plugin:awscdk/all'); // or 'awscdk/aws-foundational' etc
without projen update eslintrc.json
{
"plugins": [
"awscdk"
],
"extends": [
"plugin:awscdk/all"
]
}
Using ESLint rules
using projen
import { AwsCdkTypeScriptApp } from 'projen';
const project = new AwsCdkTypeScriptApp({
...
devDeps: [
'eslint-plugin-awscdk',
],
...
});
project.eslint?.config.plugins.push('awscdk');
// add individual rules
project.eslint?.addRules({
'awscdk/require-bucket-encryption': [
2, // can set severity (0 = info, 1 = warning, 2 = error)
],
});
without projen update eslintrc.json
{
"plugins": [
"awscdk"
],
"rules": {
"awscdk/require-bucket-encryption": [
2
]
}
}
Rules
AWS Foundational Security Best Practices
How to enable
new apigateway.Stage(this, 'Stage', {
loggingLevel: apigateway.MethodLoggingLevel.ERROR, // or INFO
...
});
// or
new apigateway.RestApi(this, 'API', {
deployOptions: {
loggingLevel: apigateway.MethodLoggingLevel.ERROR, // or INFO
},
...
})
How to enable
// if autoScalingGroupName is provided then it should use ELB health checks
new autoscaling.AutoScalingGroup(this, 'ASG', {
autoScalingGroupName: 'my-asg',
healthCheck: autoscaling.HealthCheck.elb(),
});
How to enable
new Distribution(this, 'Distribution', {
defaultBehavior: {
...
},
defaultRootObject: 'index.html',
})
CloudFront.2 CloudFront distributions should have origin access identity enabled
CloudFront.3 CloudFront distributions should require encryption in transit
How to enable
new Distribution(this, 'Distribution', {
defaultBehavior: {
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
...
},
})
// or
new Distribution(this, 'Distribution', {
defaultBehavior: {
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.HTTPS_ONLY,
...
},
})
How to enable
new Distribution(this, 'Distribution', {
defaultBehavior: {
origin: new origins.OriginGroup(...),
}
})
Currently no L2 construct
How to enable
// either set billingMode to PAY_PER_REQUEST
new Table(this, 'Table', {
billingMode: BillingMode.PAY_PER_REQUEST,
});
new Table(this, 'Table', {
replicationRegions: ['us-east-1', 'us-east-2'], // if replication regions is specified then billingMode is set to PAY_PER_REQUEST
})
// or if billingMode is PROVISIONED, then enable autoscaling
const table = new Table(this, 'Table', {
billingMode: BillingMode.PROVISIONED, // this is also the default
});
table.autoScaleReadCapacity();
table.autoScaleWriteCapacity();
How to enable
new Table(this, 'Table', {
pointInTimeRecovery: true,
})
Currently no L2 construct
How to enable
new ec2.Volume(this, 'Volume', {
encrypted: true,
});
new efs.FileSystem(this, 'FileSystem', {
encrypted: true,
});
How to enable
const alb = new ApplicationLoadBalancer(this, 'ALB', {
...
})
alb.setAttribute('routing.http.drop_invalid_header_fields.enabled', true);
How to enable
const alb = new ApplicationLoadBalancer(this, 'ALB', {
...
})
alb.logAccessLogs(bucket);
How to enable
new ApplicationLoadBalancer(this, 'ALB', {
deletionProtection: true,
...
})
How to enable
const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB');
alb.addListener('1', {
protocol: elbv2.ApplicationProtocol.HTTP, // applies to listeners with HTTP protocol
port: 80, // if protocol is not provided then will default to http if port is 80 | 8080 | 8000 | 8008
defaultAction: elbv2.ListenerAction.redirect({
protocol: elbv2.ApplicationProtocol.HTTPS,
...
}),
});
// or
new elbv2.ApplicationListener(this, 'Listener', {
protocol: elbv2.ApplicationProtocol.HTTP, // applies to listeners with HTTP protocol
port: 80, // if protocol is not provided then will default to http if port is 80 | 8080 | 8000 | 8008
defaultAction: elbv2.ListenerAction.redirect({
protocol: elbv2.ApplicationProtocol.HTTPS,
...
}),
})
Currently no L2 construct
How to enable
new elasticsearch.Domain(this, 'Domain', {
encryptionAtRest: {
enabled: true,
}
});
How to enable
new elasticsearch.Domain(this, 'Domain', {
vpc,
});
How to enable
new elasticsearch.Domain(this, 'Domain', {
nodeToNodeEncryption: true,
});
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ['*'],
actions: ['*'],
});
Will fail rule
const user = new iam.User(this, 'User', {
managedPolicies: [...] // will fail if this is provided.
});
user.addManagedPolicy();
user.addToPolicy();
user.addToPrincipalPolicy();
user.attachInlinePolicy();
Will fail rule
import * as iam from '@aws-cdk/aws-iam';
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ['*'],
actions: ['kms:Decrypt', 'kms:ReEncryptFrom'],
});
Will fail rule
import * as iam from '@aws-cdk/aws-iam';
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ['*'],
actions: ['kms:Decrypt', 'kms:ReEncryptFrom'],
});
Will fail rule
new kms.Key(this, 'Key', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// any policy with `iam.AnyPrincipal() can't be attached to a Lambda function
const policy = new iam.PolicyStatment({
principals: [
new iam.AnyPrincipal() // equals {"AWS": "*"}
],
...
});
// Lots of ways to attach this permission to a lambda function...
// used in `initialPolicy`
const handler = new lambda.Function(this, 'Handler', {
initialPolicy: [policy],
...
});
// or
handler.grantPrincipal.addToPrincipalPolicy(policy);
//or
handler.role?.addToPrincipalPolicy(policy);
//or
handler.role?.attachInlinePolicy(policy);
//or
handler.role?.grant(new iam.AnyPrincipal(), [...]);
//or
handler.role?.grantPassRole(new iam.AnyPrincipal());
//or
handler.role?.grantPrincipal.addToPrincipalPolicy(policy);
//or
handler.addPermission('permission', {
principal: new iam.AnyPrincipal(),
...
});
//or
handler.addToRolePolicy(policy);
//or
handler.grantInvoke(new iam.AnyPrincipal());
How to enable
new lambda.Function(this, 'Handler', {
runtime: Runtime.PYTHON_3_8,
});
Will check for these runtimes:
PYTHON_3_8
PYTHON_3_7
PYTHON_3_6
NODEJS_10_X
NODEJS_12_X
NODEJS_14_X
RUBY_2_5
RUBY_2_7
JAVA_11
GO_1_X
JAVA_8
DOTNET_CORE_2_1
DOTNET_CORE_3_1
new rds.DatabaseInstance(this, 'Instance', {
...
publiclyAccessible: true,
});
default value of 'publiclyAccessible' is determined by the subnet type
new rds.DatabaseInstance(this, 'Instance', {
...
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC,
}
});
new rds.DatabaseInstance(this, 'Instance', {
...
storageEncrypted: false,
})
How to enable
new rds.DatabaseInstance(this, 'DB', {
multiAz: true,
...
});
How to enable
new rds.DatabaseInstance(this, 'Instance', {
...
enablePerformanceInsights: true,
});
// or
new rds.DatabaseInstance(this, 'Instance', {
...
enablePerformanceInsights: true,
});
or
new rds.DatabaseInstance(this, 'Instance', {
...
performanceInsightsEncryptionKey: key,
})
or
new rds.DatabaseInstance(this, 'Instance', {
...
performanceInsightsRetention: rds.PerformanceInsightsRetention.DEFAULT,
})
new rds.DatabaseCluster(this, 'Instance', {
...
deletionProtection: false,
})
How to enable
new rds.DatabaseCluster(this, 'Instance', {
...
deletionProtection: true,
})
or
new rds.DatabaseCluster(this, 'Instance', {
...
removalPolicy: cdk.RemovalPolicy.RETAIN,
})
new rds.DatabaseInstance(this, 'Instance', {
...
deletionProtection: false,
})
How to enable
new rds.DatabaseInstance(this, 'Instance', {
...
deletionProtection: true,
})
or
new rds.DatabaseInstance(this, 'Instance', {
...
removalPolicy: cdk.RemovalPolicy.RETAIN,
})
How to enable also applies to XXFromSnapshot & XXReadReplica
// log exports depend on the engine used
new rds.DatabaseCluster(this, 'Cluster', {
cloudwatchLogsExports: []
...
});
// for AURORA_POSTGRESQL
new rds.DatabaseCluster(this, 'Cluster', {
engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL,
cloudwatchLogsExports: ['Postgresql', 'Upgrade'],
...
});
// for AURORA_MYSQL & AURORA
new rds.DatabaseCluster(this, 'Cluster', {
engine: rds.DatabaseClusterEngine.AURORA_MYSQL,
cloudwatchLogsExports: ['Audit', 'Error', 'General', 'SlowQuery'],
...
});
// for MySQL
new rds.DatabaseInstance(this, 'RDS', {
engine: rds.DatabaseInstanceEngine.MYSQL,
cloudwatchLogsExports: ['Audit', 'Error', 'General', 'SlowQuery'],
});
// for POSTGRES
new rds.DatabaseInstance(this, 'RDS', {
engine: rds.DatabaseInstanceEngine.POSTGRESQL,
cloudwatchLogsExports: ['Postgresql', 'Upgrade'],
...
});
// for ORACLE_EE, ORACLE_SE, ORACLE_SE1, ORACLE_SE2
new rds.DatabaseInstance(this, 'RDS', {
engine: rds.DatabaseInstanceEngine.ORACLE_XX,
cloudwatchLogsExports: ['Alert', 'Audit', 'Trace', 'Listener'],
...
});
// for SQL_SERVER_EE, SQL_SERVER_EX, SQL_SERVER_SE, SQL_SERVER_SE, SQL_SERVER_WEB
new rds.DatabaseInstance(this, 'RDS', {
engine: rds.DatabaseInstanceEngine.SQL_SERVER_XX,
cloudwatchLogsExports: ['Error', 'Agent'],
...
});
// for MARIADB
new rds.DatabaseInstance(this, 'RDS', {
engine: rds.DatabaseInstanceEngine.MARIADB,
cloudwatchLogsExports: ['Audit', 'Error', 'General', 'SlowQuery'],
...
});
How to enable
new rds.DatabaseInstance(this, 'RDS', {
iamAuthentication: true,
...
});
// or
new rds.DatabaseInstanceFromSnapshot(this, 'RDS', {
iamAuthentication: true,
...
});
// or
new rds.DatabaseInstanceReadReplica(this, 'RDS', {
iamAuthentication: true,
...
});
Will fail rule
new redshift.Cluster(this, 'Cluster', {
publiclyAccessible: true,
});
How to enable
const parameterGroup = new redshift.ClusterParameterGroup(this, 'ParamGroup', {
parameters: {
require_SSL: '1',
},
});
new redshift.Cluster(this, 'Cluster', {
parameterGroup,
});
Currently default to 1
without the ability to change. issue link
This is automatically enabled when using the Redshift Cluster L2 Construct
How to enable
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
// or
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: new s3.BlockPublicAccess({
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}),
});
Through Block Public Access settings How to enable
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
// or
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: new s3.BlockPublicAccess({
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}),
});
Through Bucket ACL Will fail rule
new s3.Bucket(this, 'Bucket', {
accessControl: s3.BucketAccessControl.PUBLIC_READ,
});
// or
new s3.Bucket(this, 'Bucket', {
accessControl: s3.BucketAccessControl.PUBLIC_READ_WRITE,
});
// or
const bucket = new s3.Bucket(this, 'Bucket', {
accessControl: s3.BucketAccessControl.AUTHENTICATED_READ,
});
b.grantReadAccess()
bucket.grantReadAccess();
// or
new s3.Bucket(this, 'Bucket', {
publicReadAccess: true,
});
Through Bucket policy
const bucket = new s3.Bucket(this, 'Bucket');
bucket.grantPublicAccess();
// or
bucket.addToResourcePolicy(new iam.PolicyStatement({
...,
principals: ['*'],
}));
// or
const bucketPolicy = new s3.BucketPolicy(this, 'BucketPolicy', {
bucket,
});
bucketPolicy.document.addStatements([
new iam.PolicyStatement({
...,
principals: ['*'],
}),
]);
Through Block Public Access settings How to enable
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
// or
new s3.Bucket(this, 'Bucket', {
blockPublicAccess: new s3.BlockPublicAccess({
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}),
});
Through Bucket ACL Will fail rule
new s3.Bucket(this, 'Bucket', {
accessControl: s3.BucketAccessControl.PUBLIC_READ_WRITE,
});
Through Bucket policy Will fail rule
const bucket = new s3.Bucket(this, 'Bucket');
bucket.grantPublicAccess();
// or
bucket.addToResourcePolicy(new iam.PolicyStatement({
...,
principals: ['*'],
}));
// or
const bucketPolicy = new s3.BucketPolicy(this, 'BucketPolicy', {
bucket,
});
bucketPolicy.document.addStatements([
new iam.PolicyStatement({
...,
principals: ['*'],
}),
]);
How to enable
new s3.Bucket(this, 'Bucket', {
encryption: s3.BucketEncryption.XXX // any value
});
// or
new s3.Bucket(this, 'Bucket', {
encryptionKey,
});
How to enable
new s3.Bucket(this, 'Bucket', {
enforceSSL: true,
})
Will fail rule
const policy = new iam.PolicyStatement({
actions: [ // these actions are not allowed
's3:DeleteBucketPolicy',
's3:PutBucketAcl',
's3:PutBucketPolicy',
's3:PutEncryptionConfiguration',
's3:PutObjectAcl',
],
principals: [
new iam.AccountPrincipal('11111111111'), // If granting access to current account should use iam.AccountRootPrincipal()
new iam.AnyPrincipal(), // allows access from any AWS account, i.e. { "AWS": "*" }
],
...
})
Currently no L2
How to enable
const secret = new secretsmanager.Secret(this, 'Secret');
secret.addRotationSchedule();
// or
const secret = new secretsmanager.Secret(this, 'Secret');
new secretsmanager.RotationSchedule(this, 'Rotation', {
secret,
})
How to enable
new sns.Topic(this, 'Topic', {
masterKey,
...
})