Skip to content

Commit

Permalink
Merge pull request #79 from terraform-google-modules/ludo-firewall-su…
Browse files Browse the repository at this point in the history
…bmodule

Add dynamic rules to Fabric firewall submodule
  • Loading branch information
morgante authored Oct 11, 2019
2 parents bc07616 + 52e49a9 commit 4d3ca19
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 3 deletions.
1 change: 1 addition & 0 deletions modules/fabric-net-firewall/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform.tfvars
45 changes: 42 additions & 3 deletions modules/fabric-net-firewall/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
# Google Cloud Simple VPC Firewall Creation
# Google Cloud VPC Firewall

This module allows creation of a minimal VPC firewall, supporting basic configurable rules for IP range-based intra-VPC and administrator ingress, and tag-based SSH, HTTP, and HTTPS ingress.
This module allows creation of a minimal VPC firewall, supporting basic configurable rules for IP range-based intra-VPC and administrator ingress, tag-based SSH/HTTP/HTTPS ingress, and custom rule definitions.

The HTTP and HTTPS rules use the same network tags network tags that are assigned to instances when flaggging the "Allow HTTP[S] traffic" checkbox in the Cloud Console. The SSH rule uses a generic `ssh` tag.
The HTTP and HTTPS rules use the same network tags that are assigned to instances when the "Allow HTTP[S] traffic" checkbox is flagged in the Cloud Console. The SSH rule uses a generic `ssh` tag.

All IP source ranges are configurable through variables, and are set by default to `0.0.0.0/0` for tag-based rules. Allowed protocols and/or ports for the intra-VPC rule are also configurable through a variable.

Custom rules are set through a map where keys are rule names, and values use this custom type:

```hcl
map(object({
description = string
direction = string # (INGRESS|EGRESS)
action = string # (allow|deny)
ranges = list(string) # list of IP CIDR ranges
sources = list(string) # tags or SAs (ignored for EGRESS)
targets = list(string) # tags or SAs
use_service_accounts = bool # use tags or SAs in sources/targets
rules = list(object({
protocol = string
ports = list(string)
}))
extra_attributes = map(string) # map, optional keys disabled or priority
}))
```

The resources created/managed by this module are:

- one optional ingress rule from internal CIDR ranges, only allowing ICMP by default
- one optional ingress rule from admin CIDR ranges, allowing all protocols on all ports
- one optional ingress rule for SSH on network tag `ssh`
- one optional ingress rule for HTTP on network tag `http-server`
- one optional ingress rule for HTTPS on network tag `https-server`
- one or more optional custom rules


## Usage
Expand All @@ -26,6 +46,24 @@ module "net-firewall" {
network = "my-vpc"
internal_ranges_enabled = true
internal_ranges = ["10.0.0.0/0"]
custom_rules = {
ingress-sample = {
description = "Dummy sample ingress rule, tag-based."
direction = "INGRESS"
action = "allow"
ranges = ["192.168.0.0"]
sources = ["spam-tag"]
targets = ["foo-tag", "egg-tag"]
use_service_accounts = false
rules = [
{
protocol = "tcp"
ports = []
}
]
extra_attributes = {}
}
}
}
```

Expand All @@ -36,6 +74,7 @@ module "net-firewall" {
|------|-------------|:----:|:-----:|:-----:|
| admin\_ranges | IP CIDR ranges that have complete access to all subnets. | list | `<list>` | no |
| admin\_ranges\_enabled | Enable admin ranges-based rules. | string | `"false"` | no |
| custom\_rules | List of custom rule definitions (refer to variables file for syntax). | map | `<map>` | no |
| http\_source\_ranges | List of IP CIDR ranges for tag-based HTTP rule, defaults to 0.0.0.0/0. | list | `<list>` | no |
| https\_source\_ranges | List of IP CIDR ranges for tag-based HTTPS rule, defaults to 0.0.0.0/0. | list | `<list>` | no |
| internal\_allow | Allow rules for internal ranges. | list | `<list>` | no |
Expand Down
41 changes: 41 additions & 0 deletions modules/fabric-net-firewall/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,44 @@ resource "google_compute_firewall" "allow-tag-https" {
ports = ["443"]
}
}

################################################################################
# dynamic rules #
################################################################################

resource "google_compute_firewall" "custom" {
# provider = "google-beta"
for_each = var.custom_rules
name = each.key
description = each.value.description
direction = each.value.direction
network = var.network
project = var.project_id
source_ranges = each.value.direction == "INGRESS" ? each.value.ranges : null
destination_ranges = each.value.direction == "EGRESS" ? each.value.ranges : null
source_tags = each.value.use_service_accounts || each.value.direction == "EGRESS" ? null : each.value.sources
source_service_accounts = each.value.use_service_accounts && each.value.direction == "INGRESS" ? each.value.sources : null
target_tags = each.value.use_service_accounts ? null : each.value.targets
target_service_accounts = each.value.use_service_accounts ? each.value.targets : null
disabled = lookup(each.value.extra_attributes, "disabled", false)
priority = lookup(each.value.extra_attributes, "priority", 1000)
# enable_logging = lookup(each.value.extra_attributes, "enable_logging", false)

dynamic "allow" {
for_each = [for rule in each.value.rules : rule if each.value.action == "allow"]
iterator = rule
content {
protocol = rule.value.protocol
ports = rule.value.ports
}
}

dynamic "deny" {
for_each = [for rule in each.value.rules : rule if each.value.action == "deny"]
iterator = rule
content {
protocol = rule.value.protocol
ports = rule.value.ports
}
}
}
31 changes: 31 additions & 0 deletions modules/fabric-net-firewall/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,34 @@ output "admin_ranges" {
}
}

output "custom_ingress_allow_rules" {
description = "Custom ingress rules with allow blocks."
value = [
for rule in google_compute_firewall.custom :
rule.name if rule.direction == "INGRESS" && length(rule.allow) > 0
]
}

output "custom_ingress_deny_rules" {
description = "Custom ingress rules with deny blocks."
value = [
for rule in google_compute_firewall.custom :
rule.name if rule.direction == "INGRESS" && length(rule.deny) > 0
]
}

output "custom_egress_allow_rules" {
description = "Custom egress rules with allow blocks."
value = [
for rule in google_compute_firewall.custom :
rule.name if rule.direction == "EGRESS" && length(rule.allow) > 0
]
}

output "custom_egress_deny_rules" {
description = "Custom egress rules with allow blocks."
value = [
for rule in google_compute_firewall.custom :
rule.name if rule.direction == "EGRESS" && length(rule.deny) > 0
]
}
19 changes: 19 additions & 0 deletions modules/fabric-net-firewall/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,22 @@ variable "https_source_ranges" {
description = "List of IP CIDR ranges for tag-based HTTPS rule, defaults to 0.0.0.0/0."
default = ["0.0.0.0/0"]
}

variable "custom_rules" {
description = "List of custom rule definitions (refer to variables file for syntax)."
default = {}
type = map(object({
description = string
direction = string
action = string # (allow|deny)
ranges = list(string)
sources = list(string)
targets = list(string)
use_service_accounts = bool
rules = list(object({
protocol = string
ports = list(string)
}))
extra_attributes = map(string)
}))
}

0 comments on commit 4d3ca19

Please sign in to comment.