Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wafv2): add WebAcl L2 Construct #17878

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions packages/@aws-cdk/aws-wafv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,43 @@
>
> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib

![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)

> The APIs of higher level constructs in this module are experimental and under active development.
> They are subject to non-backward compatible changes or removal in any future version. These are
> not subject to the [Semantic Versioning](https://semver.org/) 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.

---

<!--END STABILITY BANNER-->

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
## Installation

```ts nofixture
import * as wafv2 from '@aws-cdk/aws-wafv2';
Install the module:

```console
$ npm i @aws-cdk/aws-wafv2
```

<!--BEGIN CFNONLY DISCLAIMER-->
Import it into your code:

There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet.
However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly.
```ts
import * as wafv2 from '@aws-cdk/aws-wafv2';
```

## `WebAcl`

For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::WAFv2](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_WAFv2.html).
Create a web ACL that gives you fine-grained control over all of the HTTP(S) web requests that your protected resource responds to.
You can create a web ACL as following:

(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.)
```ts
import * as wafv2 from '@aws-cdk/aws-wafv2';

<!--END CFNONLY DISCLAIMER-->
new wafv2.WebAcl(this, 'WebAcl', {
webAclName: 'my-web-acl-name', // OPTIONAL
scope: wafv2.Scope.CLOUDFRONT,
defaultAction: wafv2.DefaultAction.block(),
});
```
56 changes: 56 additions & 0 deletions packages/@aws-cdk/aws-wafv2/lib/default-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Construct } from 'constructs';
import { CfnWebACL } from './wafv2.generated';

/**
* The type returned from the `bind()` method in {@link DefaultAction}.
*/
export interface DefaultActionConfig {
/**
* The configuration for this default action.
*/
readonly configuration: CfnWebACL.DefaultActionProperty;
}

/**
* The action to perform if none of the Rules contained in the WebACL match.
*/
export abstract class DefaultAction {
/**
* Specifies that AWS WAF should allow requests by default.
*/
public static allow(): DefaultAction {
return new AllowAction();
}

/**
* Specifies that AWS WAF should block requests by default.
*/
public static block(): DefaultAction {
return new BlockAction();
}

/**
* Returns the DefaultAction configuration.
*/
public abstract bind(scope: Construct): DefaultActionConfig
}

class AllowAction extends DefaultAction {
bind(_scope: Construct) {
return {
configuration: {
allow: {},
},
};
}
};

class BlockAction extends DefaultAction {
bind(_scope: Construct) {
return {
configuration: {
block: {},
},
};
}
};
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-wafv2/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from './default-action';
export * from './web-acl';

// AWS::WAFv2 CloudFormation Resources:
export * from './wafv2.generated';
104 changes: 104 additions & 0 deletions packages/@aws-cdk/aws-wafv2/lib/web-acl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Resource, Names } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { DefaultAction } from './default-action';
import { CfnWebACL } from './wafv2.generated';

/**
* Specifies whether this is for an Amazon CloudFront distribution or for a regional application.
* A regional application can be an Application Load Balancer (ALB), an Amazon API Gateway REST API,
* or an AWS AppSync GraphQL API.
*/
export enum Scope {
/**
* For regional application
*/
REGIONAL = 'REGIONAL',

/**
* For Amazon CloudFront distribution
*/
CLOUDFRONT = 'CLOUDFRONT',
}

/**
* Properties for defining an AWS WAF web ACL
*/
export interface WebAclProps {
/**
* The descriptive name of the web ACL. You cannot change the name of a web ACL after you create it.
* @default None
*/
readonly webAclName?: string;

/**
* Specifies whether this is for an Amazon CloudFront distribution or for a regional application.
*/
readonly scope: Scope;

/**
* The action to perform if none of the Rules contained in the WebACL match.
*/
readonly defaultAction: DefaultAction;
}

/**
* Defines an AWS WAF web ACL in this stack.
*/
export class WebAcl extends Resource {
/**
* Name of this web ACL rule
* @attribute
*/
public readonly webAclName: string;

/**
* The Amazon Resource Name (ARN) of the web ACL.
* @attribute
*/
public readonly webAclArn: string;

/**
* The current web ACL capacity (WCU) usage by the web ACL.
* @attribute
*/
public readonly webAclCapacity: number;

/**
* The ID of the web ACL.
* @attribute
*/
public readonly webAclId: string;

/**
* The label namespace prefix for this web ACL. All labels added by rules in this web ACL have this prefix.
* @attribute
*/
public readonly webAclLabelNamespace: string;

constructor(scope: Construct, id: string, props: WebAclProps) {
super(scope, id, {
physicalName: props.webAclName,
});

const resource = new CfnWebACL(this, 'Resource', {
name: this.physicalName,
scope: props.scope,
defaultAction: props.defaultAction.bind(this).configuration,
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: props.webAclName || Names.uniqueId(this),
sampledRequestsEnabled: true,
},
});

this.webAclName = this.getResourceNameAttribute(resource.ref);
this.webAclArn = this.getResourceArnAttribute(resource.attrArn, {
service: 'wafv2',
resource: 'webacl',
resourceName: this.physicalName,
});
this.webAclCapacity = resource.attrCapacity;
this.webAclId = resource.attrId;
this.webAclLabelNamespace = resource.attrLabelNamespace;
}
}
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-wafv2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@
"devDependencies": {
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/cdk-integ-tools": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/jest": "^27.4.1"
"@types/jest": "^27.4.1",
"jest": "^27.5.1"
},
"dependencies": {
"@aws-cdk/core": "0.0.0",
Expand All @@ -99,7 +101,7 @@
"node": ">= 10.13.0 <13 || >=13.7.0"
},
"stability": "experimental",
"maturity": "cfn-only",
"maturity": "experimental",
"awscdkio": {
"announce": false
},
Expand Down
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-wafv2/test/integ.web-acl.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"Resources": {
"WebAclE76B067C": {
"Type": "AWS::WAFv2::WebACL",
"Properties": {
"DefaultAction": {
"Block": {}
},
"Scope": "CLOUDFRONT",
"VisibilityConfig": {
"CloudWatchMetricsEnabled": true,
"MetricName": "my-web-acl-name",
"SampledRequestsEnabled": true
},
"Name": "my-web-acl-name"
}
}
}
}
18 changes: 18 additions & 0 deletions packages/@aws-cdk/aws-wafv2/test/integ.web-acl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as cdk from '@aws-cdk/core';
import * as wafv2 from '../lib';

class TestStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);

new wafv2.WebAcl(this, 'WebAcl', {
webAclName: 'my-web-acl-name',
scope: wafv2.Scope.CLOUDFRONT,
defaultAction: wafv2.DefaultAction.block(),
});
}
}

const app = new cdk.App();
new TestStack(app, 'web-acl-integ-stack');
app.synth();
6 changes: 0 additions & 6 deletions packages/@aws-cdk/aws-wafv2/test/wafv2.test.ts

This file was deleted.

Loading