Skip to content

Instantly share code, notes, and snippets.

@marcandjulien
Forked from statik/waf.ts
Created January 30, 2023 15:58
Show Gist options
  • Save marcandjulien/4ddae764ba1a9b0d51c3cb90f7edc556 to your computer and use it in GitHub Desktop.
Save marcandjulien/4ddae764ba1a9b0d51c3cb90f7edc556 to your computer and use it in GitHub Desktop.
WAF with CDK examples
import * as cdk from "@aws-cdk/core";
import * as wafv2 from "@aws-cdk/aws-wafv2";
// This extends the base cdk stack properties to include a tag name input.
export interface StackProps extends cdk.StackProps {
tag: string;
applicationName?: string;
}
export class WAFStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: customProps.StackProps) {
super(scope, id, props);
cdk.Tags.of(this).add('cost-tag', String(props.tag));
const waf = new WAF(this, 'WAFv2');
const devALB = elb.ApplicationLoadBalancer.fromLookup(this, 'devALB', {
loadBalancerTags: {
// Finds a load balancer matching all tags.
'Name': 'foo-dev',
},
});
const prodALB = elb.ApplicationLoadBalancer.fromLookup(this, 'prodALB', {
loadBalancerTags: {
// Finds a load balancer matching all tags.
'Name': 'foo-prod',
},
});
// Create an association with the dev alb
new WebACLAssociation(this, 'DevAssociation',{
resourceArn: devALB.loadBalancerArn,
webAclArn: waf.attrArn,
});
// Create an association with the prod alb
new WebACLAssociation(this, 'ProdAssociation',{
resourceArn: prodALB.loadBalancerArn,
webAclArn: waf.attrArn,
});
}
}
interface WafRule {
name: string;
rule: wafv2.CfnWebACL.RuleProperty;
}
const awsManagedRules: WafRule[] = [
// AWS IP Reputation list includes known malicious actors/bots and is regularly updated
{
name: 'AWS-AWSManagedRulesAmazonIpReputationList',
rule: {
name: 'AWS-AWSManagedRulesAmazonIpReputationList',
priority: 10,
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesAmazonIpReputationList',
},
},
overrideAction: {
none: {},
},
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: 'AWSManagedRulesAmazonIpReputationList',
},
},
},
// Common Rule Set aligns with major portions of OWASP Core Rule Set
{
name: 'AWS-AWSManagedRulesCommonRuleSet',
rule:
{
name: 'AWS-AWSManagedRulesCommonRuleSet',
priority: 20,
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesCommonRuleSet',
// Excluding generic RFI body rule for sns notifications
// https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html
excludedRules: [
{ name: 'GenericRFI_BODY' },
{ name: 'SizeRestrictions_BODY' },
],
},
},
overrideAction: {
none: {},
},
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: 'AWS-AWSManagedRulesCommonRuleSet',
},
},
},
// Blocks common SQL Injection
{
name: 'AWSManagedRulesSQLiRuleSet',
rule: {
name: 'AWSManagedRulesSQLiRuleSet',
priority: 30,
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: 'AWSManagedRulesSQLiRuleSet',
},
overrideAction: {
none: {},
},
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesSQLiRuleSet',
excludedRules: [],
},
},
},
},
// Blocks common PHP attacks such as using high risk variables and methods in the body or queries
{
name: 'AWSManagedRulePHP',
rule: {
name: 'AWSManagedRulePHP',
priority: 40,
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: 'AWSManagedRulePHP',
},
overrideAction: {
none: {},
},
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesPHPRuleSet',
excludedRules: [],
},
},
},
},
// Blocks attacks targeting LFI(Local File Injection) for linux systems
{
name: 'AWSManagedRuleLinux',
rule: {
name: 'AWSManagedRuleLinux',
priority: 50,
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: 'AWSManagedRuleLinux',
},
overrideAction: {
none: {},
},
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesLinuxRuleSet',
excludedRules: [],
},
},
},
},
];
export class WAF extends wafv2.CfnWebACL {
constructor(scope: cdk.Construct, id: string) {
super(scope, id,{
defaultAction: { allow: {} },
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'foo-waf',
sampledRequestsEnabled: false,
},
scope: 'REGIONAL',
name: 'foo-prod-waf',
rules: awsManagedRules.map(wafRule => wafRule.rule),
});
}
}
export class WebACLAssociation extends wafv2.CfnWebACLAssociation {
constructor(scope: cdk.Construct, id: string, props: wafv2.CfnWebACLAssociationProps) {
super(scope, id,{
resourceArn: props.resourceArn,
webAclArn: props.webAclArn,
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment