Skip to content

Commit

Permalink
Merge pull request #222 from globaldatanet/4.1.4
Browse files Browse the repository at this point in the history
4.1.4
  • Loading branch information
daknhh authored Nov 8, 2023
2 parents 0cb3def + 40dfea0 commit 247119c
Show file tree
Hide file tree
Showing 13 changed files with 1,199 additions and 234 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Documentation

env:
AWS_REGION: eu-central-1
AWS_ROLE: FirewallFactoryGithubPipelineRole
AWS_ACCOUNT: 376263449237
DISTRIBUTION_ID: E2T722RW2UKIMQ
S3_BUCKET: docs.aws-firewall-factory.com

permissions:
id-token: write
contents: read
on:
push:
branches:
- master
- 4.1.4
jobs:
deploy_production_main:
name: Update Documentation
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout
uses: actions/checkout@v3
- name: 🔑 Configure AWS credentials
uses: aws-actions/[email protected]
env:
ACCOUNT_ID: ${{ env.AWS_ACCOUNT }}
with:
role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.AWS_ROLE }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: GitHubActionsSession
mask-aws-account-id: false
- name: 📦 Install dependencies
run: npm install
- name: 📄 Generate Documentation
run: npx typedoc --options typedoc.json
- name: 🚀 Upload Documentation
run: |
aws s3 sync ./docs s3://${{env.S3_BUCKET}} --delete
aws cloudfront create-invalidation --distribution-id ${{env.DISTRIBUTION_ID}} --paths "/*"
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@

## Released

## 4.1.4
### Added
- Automation for [Documentation](https://docs.aws-firewall-factory.com/) for the AWS Firewall Factory to assist you in utilizing our solution.
The documentation will be updated regularly to provide you with the most current information. We also added more comments to functions and enums to provide more information to you. [Issue 220](https://github.com/globaldatanet/aws-firewall-factory/issues/220)
- First preperations to support for [Network Firewalls](https://github.com/globaldatanet/aws-firewall-factory/issues/219)

### Fixed
- Console log error if only one Managed Rule Group was specified - the table output was not working for PostProcess.
- Bump @mhlabs/cfn-diagram from 1.1.29 to 1.1.38 -> thanks to [ljacobsson](https://github.com/ljacobsson) for the new release
- Bump @babel/traverse to 7.23.2
- Bump @types/uuid from 9.0.5 to 9.0.7
- Bump @types/node from 18.16.3 to 20.8.10

## 4.1.3
## Added
### Added
- Optional Lambda function to prerequisite Stack that send notifications about potential DDoS activity for protected resources to messengers (Slack/Teams) - [AWS Shield Advanced]
- Automated test workflows of example firewalls, to ensure code quality and test coverage

Expand Down
4 changes: 2 additions & 2 deletions bin/aws-firewall-factory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
import { FirewallStack } from "../lib/firewall-stack";
import { WafStack } from "../lib/web-application-firewall-stack";
import { PrerequisitesStack } from "../lib/prerequisites-stack";
import * as cdk from "aws-cdk-lib";
import { wrongLoggingConfiguration } from "../lib/tools/config-validator";
Expand Down Expand Up @@ -109,7 +109,7 @@ void (async () => {
console.error("\u001B[31m"," 🚨 ERROR: Amazon S3 bucket name is invalid 🚨 ", "\x1b[0m" +"\n 🪣 Amazon S3 bucket name must begin with \"aws-waf-logs-\" followed by at least one \n of the following characters [a-z0-9_.-]\n\n","\x1b[0m" + "\n\n");
process.exit(1);
}
new FirewallStack(app, `${config.General.Prefix.toUpperCase()}-WAF-${config.WebAcl.Name.toUpperCase()}-${config.General.Stage.toUpperCase()}${config.General.DeployHash ? "-"+config.General.DeployHash.toUpperCase() : ""}`, {
new WafStack(app, `${config.General.Prefix.toUpperCase()}-WAF-${config.WebAcl.Name.toUpperCase()}-${config.General.Stage.toUpperCase()}${config.General.DeployHash ? "-"+config.General.DeployHash.toUpperCase() : ""}`, {
config, runtimeProperties: runtimeProperties,
env: {
region: deploymentRegion,
Expand Down
5 changes: 3 additions & 2 deletions lib/tools/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ async function calculateCapacities(
managedrule.version
);
managedrule.capacity = capacity;
managedcapacitieslog.push([managedrule.name, managedrule.capacity, managedrule.version !== "" ? managedrule.version : "[unversioned]", managedrule.enforceUpdate ?? "false"]);
managedcapacitieslog.push([managedrule.name, capacity, managedrule.version !== "" ? managedrule.version : "[unversioned]", managedrule.enforceUpdate ?? "false"]);
runtimeProperties.ManagedRuleCapacity += capacity;
runtimeProperties.PreProcess.ManagedRuleGroupCount += 1;
managedrule.name === "AWSManagedRulesBotControlRuleSet" ? runtimeProperties.PreProcess.ManagedRuleBotControlCount +=1 : "";
Expand All @@ -312,7 +312,8 @@ async function calculateCapacities(
config.WebAcl.Scope,
managedrule.version
);
managedcapacitieslog.push([managedrule.name, managedrule.capacity, managedrule.capacity, managedrule.version !== "" ? managedrule.version : "[unversioned]", managedrule.enforceUpdate ?? "false"]);
managedrule.capacity = capacity;
managedcapacitieslog.push([managedrule.name, managedrule.capacity, managedrule.version !== "" ? managedrule.version : "[unversioned]", managedrule.enforceUpdate ?? "false"]);
runtimeProperties.ManagedRuleCapacity += capacity;
runtimeProperties.PostProcess.ManagedRuleGroupCount += 1;
managedrule.name === "AWSManagedRulesBotControlRuleSet" ? runtimeProperties.PostProcess.ManagedRuleBotControlCount +=1 : "";
Expand Down
108 changes: 100 additions & 8 deletions lib/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,151 @@ import { aws_fms as fms } from "aws-cdk-lib";
import { CfnTag } from "aws-cdk-lib";
import * as fwmEnums from "./enums";

/**
* Settings for the AWS WAF policy (type WAFV2) that specifies rule groups to run first in the corresponding AWS WAF Web ACL and rule groups to run last in the Web ACL.
*/
export interface Config {
readonly General: {
readonly Prefix: string,
readonly Stage: string,
/**
* Defines the selected logging option for the WAF.
*/
readonly LoggingConfiguration: "S3" | "Firehose"
readonly FireHoseKeyArn?: string,
readonly S3LoggingBucketName: string,
readonly DeployHash?: string,
/**
* Defines the domain(s) that can be checked to audit your WAF.
*/
readonly SecuredDomain: Array<string>,
/**
* Defines whether to set up a dashboard for your firewall in the central security account. To use this feature, cross-account functionality must be enabled in CloudWatch.
*/
readonly CreateDashboard?: boolean,
},
readonly WebAcl:{
readonly Name: string,

/**
* @TJS-pattern ^([\p{L}\p{Z}\p{N}_.:\/=+\-@]*)$
*/
readonly Description?: string,
readonly IncludeMap: fms.CfnPolicy.IEMapProperty,
readonly ExcludeMap?: fms.CfnPolicy.IEMapProperty,
readonly Scope: fwmEnums.WebAclScope | "CLOUDFRONT" | "REGIONAL",
/**
* The type of resource protected by or in scope of the policy. To apply this policy to multiple resource types, specify a resource type of ResourceTypeList and then specify the resource types in a ResourceTypeList.
*/
readonly Type: fwmEnums.WebAclTypeEnum | "ResourceTypeList" | WebAclType,
readonly TypeList?: fwmEnums.WebAclTypeEnum[] | WebAclType[],
/**
* An array of ResourceTag objects, used to explicitly include resources in the policy scope or explicitly exclude them. If this isn't set, then tags aren't used to modify policy scope. See also ExcludeResourceTags.
*/
readonly ResourceTags?: Array<fms.CfnPolicy.ResourceTagProperty>,
/**
* Used only when tags are specified in the ResourceTags property. If this property is True, resources with the specified tags are not in scope of the policy. If it's False, only resources with the specified tags are in scope of the policy.
*/
readonly ExcludeResourceTags?: boolean,
/**
* Indicates if the policy should be automatically applied to new resources.
*/
readonly RemediationEnabled?: boolean,
/**
* Indicates whether AWS Firewall Manager should automatically remove protections from resources that leave the policy scope and clean up resources that Firewall Manager is managing for accounts when those accounts leave policy scope. For example, Firewall Manager will disassociate a Firewall Manager managed web ACL from a protected customer resource when the customer resource leaves policy scope.
*/
readonly ResourcesCleanUp?: boolean,
/**
* Contains one or more IP addresses or blocks of IP addresses specified in Classless Inter-Domain Routing (CIDR) notation. AWS WAF supports IPv4 address ranges: /8 and any range between /16 through /32. AWS WAF supports IPv6 address ranges: /24, /32, /48, /56, /64, and /128.
*/
readonly IPSets?: IPSet[],
/**
* The RegexPatternSet specifies the regular expression (regex) pattern that you want AWS WAF to search for, such as B[a@]dB[o0]t. You can then configure AWS WAF to reject those requests.
*/
readonly RegexPatternSets?: RegexPatternSet[];
/**
* Defines a Set of Custom Rules and AWS ManagedRulesGroups.
*/
readonly PreProcess: RuleGroupSet,
/**
* Defines a Set of Custom Rules and AWS ManagedRulesGroups.
*/
readonly PostProcess: RuleGroupSet,
},
}

/**
* The type of resource protected by or in scope of the policy. To apply this policy to multiple resource types, specify a resource type of ResourceTypeList and then specify the resource types in a ResourceTypeList.
*/
export type WebAclType= "AWS::ElasticLoadBalancingV2::LoadBalancer" | "AWS::CloudFront::Distribution" | "AWS::ApiGatewayV2::Api" | "AWS::ApiGateway::Stage"
// | "AWS::Cognito::UserPool" | "AWS::AppSync::GraphQLApi" - waiting for support if you need a GraphQLApi Firewall just use an ApiGateway:Stage Firewall
export interface Prerequisites {
readonly General: {
readonly Prefix: string,
},
/**
* Will add a Lambda function to the prerequisite stack that sends notifications when new versions and updates to a AWS ManagedRuleGroup appear in messengers (Slack/Teams).
*/
readonly Information?:{
SlackWebhook?: string,
TeamsWebhook?: string,
}
/**
* Will add a Lambda function to prerequisite Stack that send notifications about potential DDoS activity for protected resources to messengers (Slack/Teams)
* This feature, coupled with [AWS Shield Advanced](https://aws.amazon.com/shield/).
*/
readonly DdosNotifications?:{
SlackWebhook?: string,
TeamsWebhook?: string,
}
readonly Logging?: {
readonly BucketProperties?: {
/**
* A name for the bucket. Allowed Pattern: ^[a-z0-9][a-z0-9//.//-]*[a-z0-9]$
*/
readonly BucketName?: string,
/**
* Define if a KMS Key for the bucket will be created.
*/
readonly KmsEncryptionKey: boolean,
/**
* Will add Object Lock (write-once-read-many (WORM)) to the S3 Bucket (Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely.)
*/
readonly ObjectLock?: {
readonly Days: number,
readonly Mode: "GOVERNANCE" | "COMPLIANCE"
}

},
/**
* Define if a KMS Key for Kinesis FireHose will be created.
*/
readonly FireHoseKey?: {
/**
* Define if a Alias for the KMS Key
*/
readonly KeyAlias: string
},
/**
* Defines access to a central security account. Please specify a account ID such as 123456789012.This is necessary if you want to use a different account for all your firewalls.
*/
readonly CrossAccountIdforPermissions?: string,
}
}

/**
* S3 Object Lock provides two retention modes:
- Governance mode
- Compliance mode
*/
export enum ObjectLockMode {
GOVERNANCE = "GOVERNANCE",
COMPLIANCE = "COMPLIANCE"
}


/**
* Represents all AWS Regions
*/
export type RegionString = "us-west-2" | "us-west-1" | "us-east-2" | "us-east-1" | "ap-south-1"| "ap-northeast-2" | "ap-northeast-1" | "ap-southeast-1" | "ap-southeast-2" | "ca-central-1" | "cn-north-1" | "eu-central-1" | "eu-west-1" | "eu-west-2" | "eu-west-3" | "sa-east-1" | "us-gov-west-1" | "ap-east-1" | "ap-southeast-3" | "ap-northeast-3" | "eu-south-1" | "eu-north-1" | "me-south-1";

/**
* Represents Region Codes for all AWS Regions
*/
export enum PriceRegions{
"us-west-2"= "US West (Oregon)",
"us-west-1"= "US West (N. California)",
Expand All @@ -103,6 +175,9 @@ export enum PriceRegions{
"me-south-1" = "Middle East (Bahrain)"
}

/**
* A custom response to send to the client. You can define a custom response for rule actions and default web ACL actions that are set to the block action.
*/
export type CustomResponseBodies = { [key:string]: {
/**
* @TJS-pattern [\s\S]*
Expand All @@ -111,22 +186,32 @@ export type CustomResponseBodies = { [key:string]: {
ContentType: fwmEnums.CustomResponseBodiesContentType,
}};

/**
* Defines a Set of Custom Rules and AWS ManagedRulesGroups.
*/
export interface RuleGroupSet {
CustomResponseBodies?: CustomResponseBodies,
CustomRules?: Rule[],
ManagedRuleGroups?: ManagedRuleGroup[];
}

/**
* The regex above matches both IPv4 and IPv6 in CIDR notation, e.g. 123.4.3.0/32
* @TJS-pattern (?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}\/(3[0-2]|[12]?[0-9])$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$)
*/
type IPAddress = string; // The regex above matches both IPv4 and IPv6 in CIDR notation, e.g. 123.4.3.0/32
export type IPAddress = string;

interface IPAddressWithDescription {
export interface IPAddressWithDescription {
description: string,
/**
* Defines a Ip Address - IPv4 and IPv6 in CIDR notation, e.g. 123.4.3.0/32
*/
ip: IPAddress
}

/**
* Contains one or more IP addresses or blocks of IP addresses specified in Classless Inter-Domain Routing (CIDR) notation. AWS WAF supports IPv4 address ranges: /8 and any range between /16 through /32. AWS WAF supports IPv6 address ranges: /24, /32, /48, /56, /64, and /128.
*/
export interface IPSet {
/**
* @TJS-pattern ^[a-zA-Z0-9]+$
Expand All @@ -141,6 +226,9 @@ export interface IPSet {
tags?: CfnTag[]
}

/**
* The RegexPatternSet specifies the regular expression (regex) pattern that you want AWS WAF to search for, such as B[a@]dB[o0]t. You can then configure AWS WAF to reject those requests.
*/
export interface RegexPatternSet {
/**
* @TJS-pattern ^[a-zA-Z0-9]+$
Expand All @@ -153,4 +241,8 @@ export interface RegexPatternSet {
regularExpressionList: string[],
tags?: CfnTag[]
}

/**
* Represents all AWS ManagedRuleGroups which are not versioned
*/
export const NONEVERSIONEDMANAGEDRULEGRPOUP = ["AWSManagedRulesBotControlRuleSet","AWSManagedRulesATPRuleSet","AWSManagedRulesACFPRuleSet","AWSManagedRulesAmazonIpReputationList","AWSManagedRulesAnonymousIpList"];
19 changes: 14 additions & 5 deletions lib/types/fms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { aws_wafv2 as waf } from "aws-cdk-lib";
import * as fwmEnums from "./enums";

interface CustomRequestHandling {
export interface CustomRequestHandling {
customRequestHandling?: {
insertHeaders: {
/**
Expand All @@ -19,7 +19,7 @@ interface CustomRequestHandling {
}
}

interface CustomResponse {
export interface CustomResponse {
customResponse?: {
responseCode: number,

Expand All @@ -40,15 +40,15 @@ interface CustomResponse {
}
}

interface Action {
export interface Action {
block?: CustomResponse,
allow?: CustomRequestHandling,
count?: CustomRequestHandling,
captcha?: CustomRequestHandling,
challenge?: CustomRequestHandling
}

interface RuleActionOverrideProperty {
export interface RuleActionOverrideProperty {
name: string,
actionToUse: Action
}
Expand All @@ -63,13 +63,19 @@ export interface ManagedRuleGroup {
vendor: fwmEnums.ManagedRuleGroupVendor | string | "AWS",
name: fwmEnums.AwsManagedRules | string,
version?: string,
/**
* Will be automatically set using the [Check Capacity API](https://docs.aws.amazon.com/waf/latest/APIReference/API_CheckCapacity.html).
*/
capacity?: number,
excludeRules?: NameObject[],
overrideAction?: {
type: "COUNT" | "NONE"
},
ruleActionOverrides?: RuleActionOverrideProperty[],
versionEnabled?: boolean
/**
* Enforce the [current Default version](https://docs.aws.amazon.com/waf/latest/developerguide/waf-managed-rule-groups-versioning.html) of the managed rule group to be retrieved using a Lambda Function.
*/
latestVersion?: boolean
enforceUpdate?:boolean
}
Expand All @@ -80,6 +86,9 @@ export interface Rule {
visibilityConfig: waf.CfnWebACL.VisibilityConfigProperty,
captchaConfig?: waf.CfnWebACL.CaptchaConfigProperty,
ruleLabels?: waf.CfnWebACL.LabelProperty[],
/**
* Each rule in a web ACL and each rule in a rule group must have a unique priority setting to ensure proper rule execution. [More information about processing order of rules and rule groups in a web ACL](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-processing-order.html)
*/
priority: number,
}

Expand Down Expand Up @@ -113,7 +122,7 @@ export interface ServiceDataRuleGroup extends ServiceDataAbstactRuleGroup {
ruleGroupType: "RuleGroup"
}

interface ServiceDataAbstactRuleGroup {
export interface ServiceDataAbstactRuleGroup {
overrideAction: {
type: "ALLOW" | "DENY" | "NONE" | "COUNT"
},
Expand Down
Loading

0 comments on commit 247119c

Please sign in to comment.