Skip to content

Commit

Permalink
feat: Add support for Automatically deploy Adaptive Protection sugges…
Browse files Browse the repository at this point in the history
…ted rules (#61)
  • Loading branch information
imrannayer authored Aug 29, 2023
1 parent d806a37 commit 1dd4e0c
Show file tree
Hide file tree
Showing 18 changed files with 560 additions and 30 deletions.
73 changes: 69 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Cloud Armor Terraform Module
This module makes it easy to setup [Cloud Armor Security Policy](https://cloud.google.com/armor/docs/cloud-armor-overview#security_policies) with Security rules. There are four type of rules you can create in each policy:
This module makes it easy to setup [Cloud Armor Security Policy](https://cloud.google.com/armor/docs/cloud-armor-overview#security_policies) with Security rules. There are five type of rules you can create in each policy:
- [Pre-Configured Rules](#pre_configured_rules): These are based on [pre-configured waf rules](https://cloud.google.com/armor/docs/waf-rules).
- [Security Rules](#security_rules): Allow or Deny traffic from list of IP addresses or IP adress ranges.
- [Custom Rules](#custom_rules): You can create your own rules using [Common Expression Language (CEL)](https://cloud.google.com/armor/docs/rules-language-reference).
- [Threat Intelligence Rules](#threat_intelligence_rules): Add Rules based on [threat intelligence](https://cloud.google.com/armor/docs/threat-intelligence). [Managed protection plus](https://cloud.google.com/armor/docs/managed-protection-overview) subscription is needed to use this feature.
- [Automatically deploy Adaptive Protection suggested rules](#adaptive_protection_auto_deploy); When enable module will create a rule for automatically deploying the suggested rules that [Adaptive Protection generates](https://cloud.google.com/armor/docs/adaptive-protection-auto-deploy).


## Compatibility
Expand Down Expand Up @@ -276,13 +277,14 @@ module "security_policy" {

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| adaptive\_protection\_auto\_deploy | Configuration for Automatically deploy Cloud Armor Adaptive Protection suggested rules. priority and action fields are required if enable is set to true | <pre>object({<br> enable = bool<br> priority = optional(number, null)<br> action = optional(string, null)<br> preview = optional(bool, false)<br> description = optional(string, "Adaptive Protection auto-deploy")<br> load_threshold = optional(number, 0.1)<br> confidence_threshold = optional(number, 0.5)<br> impacted_baseline_threshold = optional(number, 0.01)<br> expiration_sec = optional(number, 7200)<br> redirect_type = optional(string)<br> redirect_target = optional(string)<br><br> rate_limit_options = optional(object({<br> enforce_on_key = optional(string)<br> enforce_on_key_name = optional(string)<br><br> enforce_on_key_configs = optional(list(object({<br> enforce_on_key_name = optional(string)<br> enforce_on_key_type = optional(string)<br> })))<br><br> exceed_action = optional(string)<br> rate_limit_http_request_count = optional(number)<br> rate_limit_http_request_interval_sec = optional(number)<br> ban_duration_sec = optional(number)<br> ban_http_request_count = optional(number)<br> ban_http_request_interval_sec = optional(number)<br> }), {})<br> })</pre> | <pre>{<br> "enable": false<br>}</pre> | no |
| custom\_rules | Custome security rules | <pre>map(object({<br> action = string<br> priority = number<br> description = optional(string)<br> preview = optional(bool, false)<br> expression = string<br> redirect_type = optional(string, null)<br> redirect_target = optional(string, null)<br> rate_limit_options = optional(object({<br> enforce_on_key = optional(string)<br> enforce_on_key_name = optional(string)<br> enforce_on_key_configs = optional(list(object({<br> enforce_on_key_name = optional(string)<br> enforce_on_key_type = optional(string)<br> })))<br> exceed_action = optional(string)<br> rate_limit_http_request_count = optional(number)<br> rate_limit_http_request_interval_sec = optional(number)<br> ban_duration_sec = optional(number)<br> ban_http_request_count = optional(number)<br> ban_http_request_interval_sec = optional(number)<br> }),<br> {})<br> header_action = optional(list(object({<br> header_name = optional(string)<br> header_value = optional(string)<br> })), [])<br> }))</pre> | `{}` | no |
| default\_rule\_action | default rule that allows/denies all traffic with the lowest priority (2,147,483,647) | `string` | `"allow"` | no |
| description | An optional description of this security policy. Max size is 2048. | `string` | `null` | no |
| json\_custom\_config\_content\_types | A list of custom Content-Type header values to apply the JSON parsing. Only applicable when json\_parsing is set to STANDARD. Not supported for CLOUD\_ARMOR\_EDGE policy type | `list(string)` | `[]` | no |
| json\_parsing | Whether or not to JSON parse the payload body. Possible values are DISABLED and STANDARD. Not supported for CLOUD\_ARMOR\_EDGE policy type | `string` | `"DISABLED"` | no |
| layer\_7\_ddos\_defense\_enable | (Optional) If set to true, enables Cloud Armor Adaptive Protection for L7 DDoS detection. Cloud Armor Adaptive Protection is currently not supported for CLOUD\_ARMOR\_EDGE policy type | `bool` | `false` | no |
| layer\_7\_ddos\_defense\_rule\_visibility | (Optional) Rule visibility can be one of the following: STANDARD - opaque rules. PREMIUM - transparent rules | `string` | `"STANDARD"` | no |
| layer\_7\_ddos\_defense\_enable | (Optional) If set to true, enables Cloud Armor Adaptive Protection for L7 DDoS detection. Cloud Armor Adaptive Protection is only supported in Global Security Policies of type CLOUD\_ARMOR | `bool` | `false` | no |
| layer\_7\_ddos\_defense\_rule\_visibility | (Optional) Rule visibility can be one of the following: STANDARD - opaque rules. PREMIUM - transparent rules. This field is only supported in Global Security Policies of type CLOUD\_ARMOR. | `string` | `"STANDARD"` | no |
| log\_level | Log level to use. Possible values are NORMAL and VERBOSE. Not supported for CLOUD\_ARMOR\_EDGE policy type | `string` | `"NORMAL"` | no |
| name | Name of the security policy. | `string` | n/a | yes |
| pre\_configured\_rules | Map of pre-configured rules Sensitivity levels | <pre>map(object({<br> action = string<br> priority = number<br> description = optional(string)<br> preview = optional(bool, false)<br> redirect_type = optional(string, null)<br> redirect_target = optional(string, null)<br> target_rule_set = string<br> sensitivity_level = optional(number, 4)<br> include_target_rule_ids = optional(list(string), [])<br> exclude_target_rule_ids = optional(list(string), [])<br> rate_limit_options = optional(object({<br> enforce_on_key = optional(string)<br> enforce_on_key_name = optional(string)<br> enforce_on_key_configs = optional(list(object({<br> enforce_on_key_name = optional(string)<br> enforce_on_key_type = optional(string)<br> })))<br> exceed_action = optional(string)<br> rate_limit_http_request_count = optional(number)<br> rate_limit_http_request_interval_sec = optional(number)<br> ban_duration_sec = optional(number)<br> ban_http_request_count = optional(number)<br> ban_http_request_interval_sec = optional(number)<br> }), {})<br><br> header_action = optional(list(object({<br> header_name = optional(string)<br> header_value = optional(string)<br> })), [])<br><br> preconfigured_waf_config_exclusion = optional(object({<br> target_rule_set = string<br> target_rule_ids = optional(list(string), [])<br> request_header = optional(list(object({<br> operator = string<br> value = optional(string)<br> })))<br> request_cookie = optional(list(object({<br> operator = string<br> value = optional(string)<br> })))<br> request_uri = optional(list(object({<br> operator = string<br> value = optional(string)<br> })))<br> request_query_param = optional(list(object({<br> operator = string<br> value = optional(string)<br> })))<br> }), { target_rule_set = null })<br><br> }))</pre> | `{}` | no |
Expand All @@ -291,6 +293,7 @@ module "security_policy" {
| security\_rules | Map of Security rules with list of IP addresses to block or unblock | <pre>map(object({<br> action = string<br> priority = number<br> description = optional(string)<br> preview = optional(bool, false)<br> redirect_type = optional(string, null)<br> redirect_target = optional(string, null)<br> src_ip_ranges = list(string)<br> rate_limit_options = optional(object({<br> enforce_on_key = optional(string)<br> enforce_on_key_name = optional(string)<br> enforce_on_key_configs = optional(list(object({<br> enforce_on_key_name = optional(string)<br> enforce_on_key_type = optional(string)<br> })))<br> exceed_action = optional(string)<br> rate_limit_http_request_count = optional(number)<br> rate_limit_http_request_interval_sec = optional(number)<br> ban_duration_sec = optional(number)<br> ban_http_request_count = optional(number)<br> ban_http_request_interval_sec = optional(number)<br> }),<br> {})<br> header_action = optional(list(object({<br> header_name = optional(string)<br> header_value = optional(string)<br> })), [])<br> }))</pre> | `{}` | no |
| threat\_intelligence\_rules | Map of Threat Intelligence Feed rules | <pre>map(object({<br> action = string<br> priority = number<br> description = optional(string)<br> preview = optional(bool, false)<br> feed = string<br> exclude_ip = optional(string)<br> rate_limit_options = optional(object({<br> enforce_on_key = optional(string)<br> enforce_on_key_name = optional(string)<br> enforce_on_key_configs = optional(list(object({<br> enforce_on_key_name = optional(string)<br> enforce_on_key_type = optional(string)<br> })))<br> exceed_action = optional(string)<br> rate_limit_http_request_count = optional(number)<br> rate_limit_http_request_interval_sec = optional(number)<br> ban_duration_sec = optional(number)<br> ban_http_request_count = optional(number)<br> ban_http_request_interval_sec = optional(number)<br> }),<br> {})<br> header_action = optional(list(object({<br> header_name = optional(string)<br> header_value = optional(string)<br> })), [])<br> }))</pre> | `{}` | no |
| type | Type indicates the intended use of the security policy. Possible values are CLOUD\_ARMOR and CLOUD\_ARMOR\_EDGE | `string` | `"CLOUD_ARMOR"` | no |
| user\_ip\_request\_headers | An optional list of case-insensitive request header names to use for resolving the callers client IP address | `list(string)` | `[]` | no |

## Outputs

Expand Down Expand Up @@ -327,7 +330,7 @@ module "security_policy" {
`action, priority, description, preview, rate_limit_options, header_action, redirect_type and redirect_target` are common in all the rule types. Some of then are optional and some have default value see [Input](#Inputs).

## Rate limit
`rate_limit_options` is needed for the rules where action is set to `throttle` or `rate_based_ban`. `rate_limit_options` is a map of strings with following key pairs. You can find more details about rate limit [here](https://cloud.google.com/armor/docs/rate-limiting-overview)
`rate_limit_options` is needed for the rules where action is set to `throttle` or `rate_based_ban`. `rate_limit_options` is a map of strings with following key pairs. You can find more details about rate limit [here](https://cloud.google.com/armor/docs/rate-limiting-overview).

```
rate_limit_options = {
Expand All @@ -338,6 +341,7 @@ rate_limit_options = {
ban_http_request_count = 1000 # needed only if action is rate_based_ban
ban_http_request_interval_sec = 300 # must be one of 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2700, 3600 seconds. needed only if action is rate_based_ban
enforce_on_key = "ALL" # All is default value. If null is passed terraform will use ALL as the value. Will be set to "" when `enforce_on_key_configs` is not null
enforce_on_key_configs = [
{
enforce_on_key_type = "HTTP_PATH"
Expand Down Expand Up @@ -614,6 +618,67 @@ threat_intelligence_rules = {
}
```

## adaptive_protection_auto_deploy:
Add a rule to [Automatically deploy Adaptive Protection suggested rules](https://cloud.google.com/armor/docs/adaptive-protection-auto-deploy). [Managed protection plus](https://cloud.google.com/armor/docs/managed-protection-overview) subscription is needed to use this feature. By default this feature is disabled. If `enable` is set to true you need to provide `priority` and `action` for this module to deploy auto deploy rule. Module will create a rule with expression `evaluateAdaptiveProtectionAutoDeploy()`.

### Format:
It is an object with key value pair.

```
adaptive_protection_auto_deploy = {
enable = true
action = "deny(502)"
priority = 31
description = "Automatically deploy Adaptive Protection suggested rules"
preview = false
load_threshold = 0.1
confidence_threshold = 0.5
impacted_baseline_threshold = 0.01
expiration_sec = 7200
redirect_type = null
redirect_target = null
rate_limit_options = {}
}
```

### Sample 1 (Deny):

```
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "deny(403)"
}
```

### Sample 2 (redirect):

```
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "redirect"
redirect_type = "GOOGLE_RECAPTCHA"
}
```

### Sample 3 (throttle):

```
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "throttle"
rate_limit_options = {
exceed_action = "deny(502)"
rate_limit_http_request_count = 500
rate_limit_http_request_interval_sec = 120
enforce_on_key = "IP"
}
}
```

## Requirements

These sections describe requirements for using this module.
Expand Down
5 changes: 4 additions & 1 deletion examples/security-policy-all/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Cloud Armor Policy with preconfigured rules, custom rules and security rules

This example configures a single cloud armor policy with different types of rules.
This example configures a single cloud armor policy with following types of rules:
- Pre-configured rules
- Custom rules
- Security rules

## Usage

Expand Down
1 change: 1 addition & 0 deletions examples/security-policy-all/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module "cloud_armor" {
type = "CLOUD_ARMOR"
layer_7_ddos_defense_enable = true
layer_7_ddos_defense_rule_visibility = "STANDARD"
user_ip_request_headers = ["True-Client-IP", ]

pre_configured_rules = {
"sqli_sensitivity_level_4" = {
Expand Down
4 changes: 2 additions & 2 deletions examples/security-policy-edge/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cloud Armor Policy with preconfigured rules, custom rules and security rules
# Cloud Armor Edge Security Policy with custom rule

This example configures a single cloud armor policy with different types of rules.
This example configures a single Cloud Armor Edge Security Policy with a custom rule.

## Usage

Expand Down
67 changes: 67 additions & 0 deletions examples/security-policy-managed-protection-plus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Cloud Armor Policy with rules supported by [Cloud Armor Managed Protection Plus (CAMP+)](https://cloud.google.com/armor/docs/managed-protection-overview)

This example configures a single cloud armor policy with following types of rules:
- Threat Intelligence Rules
- Rule for Automatically deploying Adaptive Protection suggested rules


## Usage

To run this example you need to execute:

```bash
export TF_VAR_project_id="your_project_id"
```

```bash
terraform init
terraform plan
terraform apply
```

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| project\_id | The project in which the resource belongs | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| policy\_name | Security Policy name |
| project\_id | The project ID |
| security\_policy | Cloud Armor security policy created |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## For testing `redirect` and `throttle` policies replace `adaptive_protection_auto_deploy` with the following in `main.tf`

### Example 1 (redirect):

```
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "redirect"
redirect_type = "GOOGLE_RECAPTCHA"
}
```

### Example 2 (throttle):

```
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "throttle"
rate_limit_options = {
exceed_action = "deny(502)"
rate_limit_http_request_count = 500
rate_limit_http_request_interval_sec = 120
enforce_on_key = "IP"
}
}
```
59 changes: 59 additions & 0 deletions examples/security-policy-managed-protection-plus/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

resource "random_id" "suffix" {
byte_length = 4
}
module "cloud_armor" {
source = "../../"

project_id = var.project_id
name = "test-camp-policy-${random_id.suffix.hex}"
description = "Test Cloud Armor security policy with with rules supported by Cloud Armor Managed Protection Plus (CAMP+)"
default_rule_action = "allow"
type = "CLOUD_ARMOR"
layer_7_ddos_defense_enable = true
layer_7_ddos_defense_rule_visibility = "PREMIUM"

## This is an example of deny policy. Examples for redirect and throttle policies are in README.
adaptive_protection_auto_deploy = {
enable = true
priority = 100000
action = "deny(403)"
}

threat_intelligence_rules = {

deny_malicious_ips = {
action = "deny(502)"
priority = 300
description = "Deny IP addresses known to attack web applications"
preview = false
feed = "iplist-known-malicious-ips"
exclude_ip = "['47.100.100.100', '47.189.12.139']"
}

deny_tor_exit_ips = {
action = "deny(502)"
priority = 400
description = "Deny Tor exit nodes IP addresses"
preview = false
feed = "iplist-tor-exit-nodes"
}

}

}
Loading

0 comments on commit 1dd4e0c

Please sign in to comment.