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

Add dynamic rules to Fabric firewall submodule #79

Merged
merged 8 commits into from
Oct 11, 2019
Merged
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
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)
}))
}