Skip to content

Commit 0c0e9ad

Browse files
authored
Merge pull request #23 from elsa-data/feature/optional-waf
Added the ability to specify the rules for an optional WAF to attach to the app
2 parents bed6294 + 20acc42 commit 0c0e9ad

File tree

3 files changed

+119
-2
lines changed

3 files changed

+119
-2
lines changed

dev/dev.ts

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ const descriptionWithTag = (tag?: string) =>
2222

2323
// bring this out to the top as it is the type of thing we might want to change during dev
2424
// to point to other PR branches etc
25-
const DEV_DEPLOYED_IMAGE_TAG = "0.4.4";
25+
const DEV_DEPLOYED_IMAGE_TAG = "0.4.7";
26+
27+
let rulePriorityCounter = 0;
2628

2729
/**
2830
* Stack for dev
@@ -63,6 +65,92 @@ new ElsaDataStack(
6365
},
6466
enableAccessPoints: true,
6567
},
66-
databaseName: "elsa_data",
68+
databaseName: "elsa_data_nov_2023",
69+
wafRules: [
70+
{
71+
name: "LimitRequests100",
72+
priority: rulePriorityCounter++,
73+
action: {
74+
block: {},
75+
},
76+
statement: {
77+
rateBasedStatement: {
78+
// given our site is not one where you'd expect high traffic - we set this to
79+
// the minimum, and we will see how that plays out
80+
limit: 100,
81+
aggregateKeyType: "IP",
82+
},
83+
},
84+
visibilityConfig: {
85+
sampledRequestsEnabled: true,
86+
cloudWatchMetricsEnabled: true,
87+
metricName: "LimitRequests100",
88+
},
89+
},
90+
{
91+
name: "AllowedCountriesOnly",
92+
priority: rulePriorityCounter++,
93+
action: {
94+
block: {},
95+
},
96+
statement: {
97+
notStatement: {
98+
statement: {
99+
geoMatchStatement: {
100+
// block traffic if not from below
101+
countryCodes: ["AU"],
102+
},
103+
},
104+
},
105+
},
106+
visibilityConfig: {
107+
sampledRequestsEnabled: true,
108+
cloudWatchMetricsEnabled: true,
109+
metricName: "AllowedCountriesOnly",
110+
},
111+
},
112+
{
113+
name: "AWS-AWSManagedRulesCommonRuleSet",
114+
priority: rulePriorityCounter++,
115+
statement: {
116+
managedRuleGroupStatement: {
117+
name: "AWSManagedRulesCommonRuleSet",
118+
vendorName: "AWS",
119+
// an example of how we might want to exclude rules
120+
// excludedRules: [
121+
// {
122+
// name: "SizeRestrictions_BODY",
123+
// },
124+
//],
125+
},
126+
},
127+
overrideAction: {
128+
none: {},
129+
},
130+
visibilityConfig: {
131+
sampledRequestsEnabled: true,
132+
cloudWatchMetricsEnabled: true,
133+
metricName: "AWS-AWSManagedRulesCommonRuleSet",
134+
},
135+
},
136+
{
137+
name: "AWS-AWSManagedRulesAmazonIpReputationList",
138+
priority: rulePriorityCounter++,
139+
statement: {
140+
managedRuleGroupStatement: {
141+
vendorName: "AWS",
142+
name: "AWSManagedRulesAmazonIpReputationList",
143+
},
144+
},
145+
overrideAction: {
146+
none: {},
147+
},
148+
visibilityConfig: {
149+
sampledRequestsEnabled: true,
150+
cloudWatchMetricsEnabled: true,
151+
metricName: "AWS-AWSManagedRulesAmazonIpReputationList",
152+
},
153+
},
154+
],
67155
}
68156
);

packages/aws-application/app/elsa-data-application-app-runner-construct.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { IBucket } from "aws-cdk-lib/aws-s3";
1919
import { ContainerConstruct } from "../construct/container-construct";
2020
import { IHostedZone } from "aws-cdk-lib/aws-route53";
2121
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
22+
import { CfnWebACL, CfnWebACLAssociation } from "aws-cdk-lib/aws-wafv2";
2223

2324
interface Props extends ElsaDataApplicationSettings {
2425
readonly vpc: ec2.IVpc;
@@ -109,6 +110,26 @@ export class ElsaDataApplicationAppRunnerConstruct extends Construct {
109110
vpcConnector: vpcConnector,
110111
});
111112

113+
if (props.wafRules && props.wafRules.length > 0) {
114+
const cfnWebAcl = new CfnWebACL(this, "WebAcl", {
115+
defaultAction: {
116+
allow: {},
117+
},
118+
scope: "REGIONAL",
119+
visibilityConfig: {
120+
cloudWatchMetricsEnabled: true,
121+
metricName: "MetricForWebACLCDK",
122+
sampledRequestsEnabled: true,
123+
},
124+
rules: props.wafRules,
125+
});
126+
127+
new CfnWebACLAssociation(this, "WebAclAssociation", {
128+
resourceArn: appService.serviceArn,
129+
webAclArn: cfnWebAcl.attrArn,
130+
});
131+
}
132+
112133
// register a cloudMapService for the Application in our namespace
113134
// chose a sensible default - but allow an alteration in case I guess someone might
114135
// want to run two Elsa *in the same infrastructure*

packages/aws-application/elsa-data-application-settings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2+
13
/**
24
* The user settable settings for the Elsa Data application service.
35
*/
@@ -83,6 +85,12 @@ export interface ElsaDataApplicationSettings {
8385
* The cpu assigned to the Elsa Data application container - defaults to something sensible
8486
*/
8587
readonly cpu?: number;
88+
89+
/**
90+
* If present and non-empty - tells us to use these rules for establishing a WAF.
91+
* If not present, then no WAF is installed.
92+
*/
93+
readonly wafRules?: CfnWebACL.RuleProperty[];
8694
}
8795

8896
export interface ElsaDataApplicationBuildLocal {

0 commit comments

Comments
 (0)