Skip to content

Instantly share code, notes, and snippets.

@spg
Created June 16, 2021 15:20
Show Gist options
  • Save spg/a8ad5676b401cb951eac34e73aed7437 to your computer and use it in GitHub Desktop.
Save spg/a8ad5676b401cb951eac34e73aed7437 to your computer and use it in GitHub Desktop.
Cloudfront CDK sample
// ======= WAF
// Based on this example: https://docs.aws.amazon.com/waf/latest/developerguide/waf-using-managed-rule-groups.html
const acl = new waf.CfnWebACL(this, "WebAcl", {
defaultAction: { allow: {} },
scope: "REGIONAL",
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: "MyMetric",
sampledRequestsEnabled: true,
},
rules: [
{
name: "AWS-AWSManagedRulesCommonRuleSet",
priority: 0,
overrideAction: { none: {} },
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: "MetricForAMRCRS",
},
statement: {
managedRuleGroupStatement: {
vendorName: "AWS",
name: "AWSManagedRulesCommonRuleSet",
excludedRules: [
// Blocks file saves in the Botpress Code Editor
{ name: "EC2MetaDataSSRF_BODY" },
{ name: "GenericLFI_BODY" },
// Blocks the webchat via "Open Chat"
{ name: "GenericRFI_QUERYARGUMENTS" },
// Blocks saving large questions in the QnA module
{ name: "SizeRestrictions_BODY" },
{ name: "GenericRFI_BODY" },
],
},
},
},
{
name: "AWS-AWSManagedRulesSQLiRuleSet",
priority: 1,
overrideAction: { none: {} },
visibilityConfig: {
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
metricName: "MetricForAMRSQLRS",
},
statement: {
managedRuleGroupStatement: {
vendorName: "AWS",
name: "AWSManagedRulesSQLiRuleSet",
},
},
},
],
});
new waf.CfnWebACLAssociation(this, "AclAssociation1", {
webAclArn: acl.attrArn,
resourceArn: loadBalancer.loadBalancerArn,
});
// CloudFront
const originSubdomain = "your-origin";
const logBucket = new s3.Bucket(this, "CFLogBucket", {
lifecycleRules: [{ expiration: cdk.Duration.days(30) }],
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
const assetsCachePolicy = new cloudfront.CfnCachePolicy(
this,
"AssetsCachePolicy",
{
cachePolicyConfig: {
minTtl: 3600,
defaultTtl: 3600,
maxTtl: 3600,
name: "ProjectAssets",
parametersInCacheKeyAndForwardedToOrigin: {
queryStringsConfig: { queryStringBehavior: "none" },
headersConfig: { headerBehavior: "none" },
cookiesConfig: { cookieBehavior: "none" },
enableAcceptEncodingGzip: false,
enableAcceptEncodingBrotli: false,
},
},
}
);
const assetsRequestPolicy = new cloudfront.CfnOriginRequestPolicy(
this,
"AssetsRequestPolicy",
{
originRequestPolicyConfig: {
name: "ProjectAssets",
cookiesConfig: { cookieBehavior: "all" },
headersConfig: {
headerBehavior: "whitelist",
headers: ["Accept"],
},
queryStringsConfig: { queryStringBehavior: "all" },
},
}
);
const cloudFrontCertificate = acm.Certificate.fromCertificateArn(
this,
"CloudFrontCertificate",
// Certificate must be created in another stack in us-east-1 region
"arn:aws:acm:us-east-1:XXXXXXXXXX:certificate/XXXXXXX-7a7a-44d0-99bc-XXXXXXXXX"
);
const dist = new cloudfront.Distribution(this, "Dist", {
defaultBehavior: {
origin: new origins.LoadBalancerV2Origin(loadBalancer),
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
},
domainNames: [`your-subdomain.${domain}`],
certificate: cloudFrontCertificate,
logBucket,
priceClass: cloudfront.PriceClass.PRICE_CLASS_100,
});
const originId = "BotpressWebServer";
const cfnDist = dist.node.defaultChild as cloudfront.CfnDistribution;
cfnDist.addPropertyOverride(
"DistributionConfig.DefaultCacheBehavior.TargetOriginId",
originId
);
cfnDist.addPropertyOverride("DistributionConfig.Origins", [
{
CustomOriginConfig: {
OriginProtocolPolicy: "https-only",
},
DomainName: `${originSubdomain}.${domain}`,
Id: originId,
},
]);
cfnDist.addDeletionOverride(
"DistributionConfig.DefaultCacheBehavior.ForwardedValues"
);
cfnDist.addPropertyOverride("DistributionConfig.CacheBehaviors", [
{
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
PathPattern: "/assets/*",
TargetOriginId: originId,
ViewerProtocolPolicy: "allow-all",
CachePolicyId: assetsCachePolicy.attrId,
OriginRequestPolicyId: assetsRequestPolicy.attrId,
},
{
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
PathPattern: "/lite/mybot/env.js",
TargetOriginId: originId,
ViewerProtocolPolicy: "allow-all",
CachePolicyId: assetsCachePolicy.attrId,
OriginRequestPolicyId: assetsRequestPolicy.attrId,
},
{
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
PathPattern: "/api/v1/modules",
TargetOriginId: originId,
ViewerProtocolPolicy: "allow-all",
CachePolicyId: assetsCachePolicy.attrId,
OriginRequestPolicyId: assetsRequestPolicy.attrId,
},
{
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
PathPattern: "/lite/mybot/",
TargetOriginId: originId,
ViewerProtocolPolicy: "allow-all",
CachePolicyId: assetsCachePolicy.attrId,
OriginRequestPolicyId: assetsRequestPolicy.attrId,
},
{
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
PathPattern: "/api/v1/bots/mybot/mod/channel-web/botInfo",
TargetOriginId: originId,
ViewerProtocolPolicy: "allow-all",
CachePolicyId: assetsCachePolicy.attrId,
OriginRequestPolicyId: assetsRequestPolicy.attrId,
},
]);
cfnDist.addPropertyOverride(
"DistributionConfig.DefaultCacheBehavior.CachePolicyId",
// Managed-CachingDisabled
"4135ea2d-6df8-44a3-9df3-4b5a84be39ad"
);
cfnDist.addPropertyOverride(
"DistributionConfig.DefaultCacheBehavior.OriginRequestPolicyId",
// Managed-AllViewer
"216adef6-5c7f-47e4-b989-5492eafa07d3"
);
// Route53
new route53.ARecord(this, "DistRecord", {
zone: hostedZone,
recordName: "your-subdomain",
target: route53.RecordTarget.fromAlias(
new route53Targets.CloudFrontTarget(dist)
),
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment